Design Support Library(支撑Material Design)
Posted ZhangJianIsAStark
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Design Support Library(支撑Material Design)相关的知识,希望对你有一定的参考价值。
本篇博客主要记录一下Design Support Library中控件的基本使用方式。
Design Support Library是一个兼容函数库,使得开发者可以
在android 2.1及以上的设备中实现Material Design的效果。
在使用Design Support Library之前,
需要在工程的build.gradle中添加类似如下依赖:
dependencies
.........
implementation 'com.android.support:design:27.1.0'
接下来,我们就来记录下Design Support Library中控件的用法。
1 Snackbar
Snackbar是带有动画效果的快速提示栏,显示在屏幕的底部,主要用来替代Toast。
与Toast不同的是,Snackbar显示时,用户可以点击Snackbar执行相应的操作。
与Toast相似的是,如果用户没有任何操作,Snackbar到达指定时间之后就会自动消失。
Snackbar的使用方式类似于:
//使用Snackbar时,必须要指定依附的view
//Snackbar会根据传入的view,找到parent view
//即使不传入layout对应的id,最终还是能够显示在屏幕底部
View rootView = findViewById(R.id.rootView);
//第二个参数为Snackbar文本字段
//这里可以指定时长为LENGTH_INDEFINITE,于是只要不被点击,Snackbar就不会消失
Snackbar.make(rootView, "We just do a test", Snackbar.LENGTH_INDEFINITE)
//"Click"为按键对应的文本字段
//此处,当点击按键时就会显示一个Toast
.setAction("Click", new View.OnClickListener()
@Override
public void onClick(View view)
Toast.makeText(MainActivity.this,
"You click the snack bar", Toast.LENGTH_SHORT).show();
).show();
2 TextInputLayout
TextInputLayout的主要作用是作为EditText的容器,从而为EditText生成浮动的标签。
此外,它还可以对EditText的输入进行检查和提示。
我们可以看看具体的示例:
......................
//TextInputLayout作为EditText的父容器即可
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
//这里我们让TextInputLayout监控EditText的输入长度
app:counterEnabled="true"
app:counterMaxLength="11">
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
//决定软件盘确定键对应的图标
android:imeOptions="actionSearch"
android:inputType="number"
//这里定义了提示字符
android:hint="Just a test"
android:labelFor="@id/edit_text"/>
</android.support.design.widget.TextInputLayout>
......................
容易看出TextInputLayout的使用还是比较简单的。
我们来看看实际的效果:
可以看到,EditText的hint字段显示在左上角了。
而且右下角显示了EditText当前的输入长度及最大允许的长度。
如上图所示,当输入长度超过要求时,TextInputLayout还可以变换颜色进行提示。
3 TabLayout
TabLayout一般与ViewPager一起使用。
TabLayout的接口比较多,我们不一一列举了,
此处仅给出一个使用示例。
主界面XML类似于:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="@+id/tableLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!--tabMode具有两种属性,fixed和scrollable -->
<!--当Tab数量较少,不足以布满整个屏幕时,使用fixed;否则使用scrollable -->
app:tabMode="scrollable"/>
</android.support.v4.view.ViewPager>
</LinearLayout>
主Activity的代码如下:
package work.test;
...........
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
private static final int MAX_TAB_SIZE = 10;
private List<String> mDataList;
private List<Fragment> mFragmentList;
private int[] mImageRes = R.mipmap.ic_launcher, R.mipmap.ic_launcher_round;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initFragment();
TabLayout tabLayout = findViewById(R.id.tableLayout);
//初始化ViewPager
ViewPager viewPager = findViewById(R.id.viewPager);
//将Adapter和数据关联起来
LocalPagerAdapter adapter = new LocalPagerAdapter(this,
getSupportFragmentManager(), mDataList, mFragmentList, mImageRes);
viewPager.setAdapter(adapter);
//关联TabLayout和ViewPager
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); ++i)
//获取每个Tab
TabLayout.Tab tab = tabLayout.getTabAt(i);
if (tab != null)
//此处,每个Tab使用自定义的view
//需要调用setCustomView接口
tab.setCustomView(adapter.getTabView(i));
private void initData()
mDataList = new ArrayList<>();
for (int i = 0; i < MAX_TAB_SIZE; ++i)
mDataList.add("Tab: ".concat(String.valueOf(i)));
private void initFragment()
mFragmentList = new ArrayList<>();
for (int i = 0; i < mDataList.size(); ++i)
mFragmentList.add(DataFragment.newInstance(mDataList.get(i)));
//继承FragmentStatePagerAdapter
private class LocalPagerAdapter extends FragmentStatePagerAdapter
private Context mContext;
private List<String> mAdapterData;
private List<Fragment> mAdapterFragment;
private int[] mImageId;
LocalPagerAdapter(Context context, FragmentManager fm, List<String> data,
List<Fragment> fragmentList, int[] imageId)
super(fm);
mContext = context;
mAdapterData = data;
mAdapterFragment = fragmentList;
mImageId = imageId;
@Override
public Fragment getItem(int position)
return mAdapterFragment.get(position);
@Override
public int getCount()
return (mAdapterData.size() == mAdapterFragment.size()) ? mAdapterData.size() : 0;
//若Tab使用自定义的view,那么getPageTitle返回null
//否则就需要实现该接口,返回需要显示的字符集
@Nullable
@Override
public CharSequence getPageTitle(int position)
return null;
//这里就是构造每个Tab对应的View
View getTabView(int position)
View view = LayoutInflater.from(mContext).inflate(R.layout.tab_layout, null);
TextView textView = view.findViewById(R.id.tab_title);
textView.setText(mDataList.get(position));
ImageView imageView = view.findViewById(R.id.tab_img);
imageView.setImageResource(mImageId[position % (mImageId.length)]);
return view;
最后的实现效果类似于:
4 NavigationView
NavigationView主要用于实现导航抽屉,该View与DrawerLayout配合使用。
我们结合具体的例子,看看NavigationView的使用方法。
主界面的XML类似于:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
<!--NavigationView主要由两部分组成-->
<!--主要包括:头部视图和菜单视图-->
app:headerLayout="@layout/nav_header"
app:menu="@menu/nav_menu"/>
</android.support.v4.widget.DrawerLayout>
NavigationView的头部视图可以是任意形式的普通视图,类似于:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="192dp"
android:background="?attr/colorPrimaryDark"
android:paddingStart="16dp"
android:orientation="vertical"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:gravity="center|start">
<ImageView
android:id="@+id/testView"
android:layout_width="64dp"
android:layout_height="64dp"
android:scaleType="centerCrop"
android:src="@drawable/animation"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Text View"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
NavigationView的菜单视图类似于:
<!--容易看出与普通的menu视图完全一致-->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single" >
<item
android:id="@+id/nav_home"
android:icon="@android:drawable/btn_star"
android:title="Home" />
<item
android:id="@+id/nav_msg"
android:icon="@android:drawable/ic_btn_speak_now"
android:title="Message" />
<item
android:id="@+id/nav_friend"
android:icon="@android:drawable/btn_radio"
android:title="Friend" />
</group>
<item android:title="Sub items">
<menu>
<item
android:icon="@mipmap/ic_launcher"
android:title="Sub item 1" />
<item
android:icon="@mipmap/ic_launcher_round"
android:title="Sub item 2" />
</menu>
</item>
</menu>
NavigationView在代码中的使用方式类似于:
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
DrawerLayout mDrawerLayout;
//定义一个常规的menu
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.actionbar_menu, menu);
return super.onCreateOptionsMenu(menu);
//点击menu的按键后,将DrawerLayout绘制到主界面
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.action_settings:
//未绘制时,才绘制
if (!mDrawerLayout.isDrawerVisible(GravityCompat.START))
mDrawerLayout.openDrawer(GravityCompat.START);
break;
default:
return super.onOptionsItemSelected(item);
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawerLayout);
//定义NavigationView的按键时,与普通menu一致
NavigationView navigationView = findViewById(R.id.nav_view);
if (navigationView != null)
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener()
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item)
switch (item.getItemId())
case R.id.nav_home:
item.setCheckable(true);
break;
case R.id.nav_friend:
//..........
break;
case R.id.nav_msg:
//..........
break;
default:
//点击后可以隐藏
mDrawerLayout.closeDrawers();
return true;
);
具体的使用效果类似于:
5 FloatingActionButton
FloatingActionButton的使用方式与普通button类似。
对应的XML类似于:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="15dp"
<!--可以指定绘制时和点击后的阴影-->
app:elevation="6dp"
app:pressedTranslationZ="20dp" />
</FrameLayout>
具体的使用方式与button一致:
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton button = findViewById(R.id.fab);
button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//............
);
6 CoordinatorLayout
CoordinatorLayout的用途是使不同的视图组件直接相互作用,协调动画效果。
我们结合具体的例子看看它的用法。
XML的定义类似于:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
app:elevation="6dp"
app:pressedTranslationZ="20dp"
android:layout_gravity="end|bottom"/>
</android.support.design.widget.CoordinatorLayout>
实际使用时的代码如下:
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton button = findViewById(R.id.fab);
button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Snackbar.make(view, "Test", Snackbar.LENGTH_INDEFINITE)
.setAction("Remove", new View.OnClickListener()
@Override
public void onClick(View view)
//...........
).show();
);
对于前文提及的XML文件,如果使用普通的ViewGroup时,例如FrameLayout,点击视图后的效果类似于:
从图上可以看出,Snackbar会遮挡住按键。
如果使用CoordinatorLayout,点击视图后的效果类似于:
从图上可以看出,当Snackbar出现时,按键会自动移动。
点击Snackbar使之消失时,按键会回到原来的位置。
7 CollapsingToolbarLayout
CollapsingToolbarLayout主要用于实现:屏幕内容滑动时,收缩视图的作用。
CollapsingToolbarLayout主要与CoordinatorLayout、AppBarLayout协同工作。
这里我们也从一个例子入手,看看基本的使用方法。
XML文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!--最外层布局CoordinatorLayout, 协调AppBarLayout与NestedScrollView-->
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--AppBarLayout包裹CollapsingToolbarLayout-->
<android.support.design.widget.AppBarLayout
android:id="@+id/barLayout"
android:layout_width="match_parent"
android:layout_height="400dp">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/p_1"
<!--这里的scroll表示CollapsingToolbarLayout会随着屏幕内容上滑收缩 -->
<!--自己使用时感觉,exitUntilCollapsed主要针对Toolbar -->
<!--有该标志时,随着滑动收缩,Toolbar最后可以停留在屏幕上,否则将随CollapsingToolbarLayout消失-->
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/ic_launcher"
<!--有两种模式,当为parallax时,该视图在CollapsingToolbarLayout收缩的同时滑动 -->
<!--当为pin时,CollapsingToolbarLayout收缩到该视图对应的位置时,才会滑动 -->
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!--声明该behavior时,滑动其中的内容,才能触发AppBarLayout滑动-->
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:id="@+id/scrollText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/large_text" />
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
在实际的代码中,我们可以监听AppBarLayout的滑动,例如:
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
ActionBar mActionBar;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mActionBar = getSupportActionBar();
if (mActionBar != null)
mActionBar.hide();
AppBarLayout appBarLayout = findViewById(R.id.barLayout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener()
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset)
//verticalOffset表示AppBarLayout移动的偏移量
//表示未移动
if (verticalOffset == 0)
if (mActionBar != null)
mActionBar.hide();
//达到最大移动范围
else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange())
if (mActionBar != null)
mActionBar.show();
);
实际的运行效果类似于:
初始状态:
移动过程中,AppBarLayout逐渐收缩:
当AppBarLayout最终消失时,我们的代码加载了ActionBar。
例子比较简单,实际的使用就要参考具体的需求了。
8 BottomSheetBehavior
BottomSheetBehavior主要用于实现底部弹出界面的功能。
它需要配合CoordinatorLayout使用。
我们来看一个具体的例子:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/bottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!--这个表示界面高出屏幕底端的距离,为0则表示整个隐藏 -->
app:behavior_peekHeight="10dp"
<!--指定这个behavior,linear就变成BottomSheet -->
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/large_text" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
如上图所示,蓝色框对应的就是LinearLayout对应的位置。
我们既可以手动上滑BottomSheet,也可以直接用代码修改对应的状态或监听变化。
示例代码类似于:
/**
* @author zhangjian
*/
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View bottomSheet = findViewById(R.id.bottomSheet);
final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
//可以注册回调监听变化
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback()
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState)
Log.v("ZJTest", "state changed to: " + newState);
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset)
Log.v("ZJTest", "slideOffset: " + slideOffset);
);
//也可以直接修改状态
Button button = findViewById(R.id.test);
button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
int state = behavior.getState();
if (state == BottomSheetBehavior.STATE_COLLAPSED)
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
else if (state == BottomSheetBehavior.STATE_EXPANDED)
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
);
以上是关于Design Support Library(支撑Material Design)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用android design support library
Android Design Support Library概览
Android Design Support Library使用详解
Material Design 开发利器:Android Design Support Library 介绍