注意:现在比较流行使用AndroidX了,这个博客中的代码都是使用Android.support中的类库。但是用法都是一样的,代码仅供参考。
Google I/O 2014 发布了Material Design。希望统一 Android平台设计语言规范。然而再国内的很多产品和设计师并不吃这一套,还是各种仿IOS的UI。作为一个Google粉当然要学会Android Material控件的使用。而且这些控件使用起来非常方便。以下是Android Material常用控件的整理。
请注意:介绍了多个控件、多图预警,流量党珍惜下流量。
介绍的控件:
1、Toolbar和Menu。
2、基于CoordinatorLayout的联动。
3、NavigationView。
4、CardView。
5、TextInputLayout。
6、RecyclerView。
7、TabLayout。
8、SnackBar
9、FloatingActionButton
github地址:https://github.com/AxeChen/MaterialDesignSimple
1、Toolbar
ToolBar是Android 5.0推出的一个新的导航控件用于取代之前的ActionBar。
1.1、基本使用
导入依赖
compile 'com.android.support:appcompat-v7:25.3.1'
修改主题
我们需要使用Toolbar代替Actionbar,就必须将需要使用Toolbar的Activity的Theme设为NoActionBar。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
由于示例代码中只有一个Activity,所以我将整个AppTheme继承了Theme.AppCompat.Light.NoActionBar。
如果实际情况只有·部分Activity使用Toolbar,可以单独为这些Activity设置没有ActionBar的主题。
布局文件中定义Toolbar
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.mg.axe.toolbarsimple.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
</RelativeLayout>
setSupportActionBar
这个方法是 AppCompatActivity 中的方法,所以使用的 Activity 必须继承 AppCompatActivity。
private Toolbar toolbar;
private void initToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
通过以上三步,Toolbar就能展示了。
1.2、修改toolbar的属性
通过调用Toolbar提供的方法。
可以直接调用Toolbar的一些方法来改变样式:
我写的示例代码中调用的Toolbar方法。
private void setToolbarProperty() {
// 设置正标题
toolbar.setTitle("正标题");
// 设置副标题
toolbar.setSubtitle("副标题");
// 设置左边按钮图片
toolbar.setNavigationIcon(R.mipmap.ic_launcher_round);
// 设置(Log)标题与左边按钮之间图标
toolbar.setLogo(R.mipmap.ic_launcher);
}
实际上Toolbar提供修改Toolbar属性的方法非常多,远不止以上提供的方法。
在xml文件里修改
先导入命名空间:
xmlns:app="http://schemas.android.com/apk/res-auto"
属性太多就不整理了。对修改Toolbar的属性,这篇简书整理得不错,可以直接拿来用:http://www.jianshu.com/p/2c21676033db
通过Actionbar来修改
通过Actionbar的一些方法也能够修改Toolbar的一些样式(因为里面用了代理模式,具体还在研究中)。
这篇简书也有提到 : http://www.jianshu.com/p/7b5c99e1cfa3
部分方法的作用:http://blog.csdn.net/andygo_520/article/details/51439688
1.3、Toolbar点击的回调
Toolbar的点击回调主要是左边的按钮点击回调和toolbar上面的Menu点击回调。
对于Menu的点击回调更习惯重写onOptionsItemSelected方法来监听回调,后面的Menu会提到。
// 点击左侧按钮监听
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "点击了Navigation按钮", Toast.LENGTH_SHORT).show();
}
});
// toolbar的Menu回调
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
});
1.4、Toolbar添加Menu
Menu是Toolbar非常重要的部分,可以将一些功能放在Menu上来实现,常见的有发送,分享等等。
添加Menu
首先必须在Activity重写onCreateOptionsMenu方法,添加Menu的操作都在这个方法中执行。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
添加Menu有两种方式:
- 通过加载Menu资源文件
- 代码添加
如果通过资源文件添加,先要在res/menu下添加一个menu的资源文件。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:icon="@android:drawable/ic_menu_set_as"
android:orderInCategory="100"
android:title="设置"
app:showAsAction="never" />
<item
android:id="@+id/action_share"
android:icon="@android:drawable/ic_menu_share"
android:orderInCategory="100"
android:title="分享"
app:showAsAction="always" />
<item
android:id="@+id/action_edit"
android:icon="@android:drawable/ic_menu_edit"
android:orderInCategory="100"
android:title="编辑"
app:showAsAction="ifRoom" />
</menu>
如果是通过代码添加,onCreateOptionsMenu方法中调用menu.add()方法。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//使用代码创建menu
//menu.add(0, 0, 0, "搜索").setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0, 0, 0, "搜索").setIcon(android.support.v7.appcompat.R.drawable.abc_ic_search_api_material).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
//使用加载xml文件的方式创建
getMenuInflater().inflate(R.menu.test_menu, menu);
//添加子菜单
menu.addSubMenu(0, 1, 0, "submenu").setIcon(R.mipmap.ic_launcher).addSubMenu(0, 2, 0, "submenu1");
return super.onCreateOptionsMenu(menu);
}
这里有个重要的属性showAsAction,选项和作用如下:
never:永远不显示的ToolBar上,只放在OverFlow按钮中(最右边三个点的按钮)。只有OverFlow按钮才会弹出。
always :总会展示在Toolbar上。
ifRoom :如Toolbar还有足够的空间,则显示在Toolbar上。否则就放在OverFlow按钮中。
withText,collapseActionView没用过,看下这篇博客的说明吧:http://www.jianshu.com/p/4106e1414d64
3.5、监听Menu点击
首先重写onOptionsItemSelected方法。
根据MenuItem.getItemId()的方法即可找点击的Menu。
如果是加载Menu资源文件,那么ItemId就是给Item设置的id。
<item
android:id="@+id/action_settings"
android:icon="@android:drawable/ic_menu_set_as"
android:orderInCategory="100"
android:title="设置"
app:showAsAction="never" />
如果通过代码添加的Menu,那么ItemId就是调用add方法传入的itemid。看下add方法的源码就可以找到。
public MenuItem add(int groupId, int itemId, int order, CharSequence title);
监听点击的代码。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
Toast.makeText(this, "点击搜索", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(this, "点击submenu", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(this, "submenu1", Toast.LENGTH_SHORT).show();
break;
case R.id.action_settings:
Toast.makeText(this, "点击设置", Toast.LENGTH_SHORT).show();
break;
case R.id.action_edit:
Toast.makeText(this, "点击编辑", Toast.LENGTH_SHORT).show();
break;
case R.id.action_share:
Toast.makeText(this, "点击分享", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
附上Fragment中使用Menu的博客:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0104/777.html
2、基于CoordinatorLayout的联动
CoordinatorLayout是Android Material Design的重要组件,实现协调其他组件实现联动的效果。
2.1、 CollapsingToolbarLayout
效果图:
添加依赖
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:appcompat-v7:25.3.1'
布局结构
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.mg.axe.collapsingtoolbarlayout.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/yangmi"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
既然是基于CoordinatorLayout,所以控件的父布局就是CoordinatorLayout。
重要的属性(这些没有设置是无法实现效果的):
- CollapsingToolbarLayout中的属性
app:layout_scrollFlags="scroll|exitUntilCollapsed“
决定CollapsingToolbarLayout的滑动方式,这些flag的作用:
enterAlways: 一旦向上滚动这个view就可见。
enterAlwaysCollapsed: 当你定义了一个minHeight,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
exitUntilCollapsed: 当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。
当然这些flag最好是实际使用看效果。
- NestedScrollView中的属性
app:layout_behavior="@string/appbar_scrolling_view_behavior”
这个属性用于通知AppBarLayout 。View(这里是NestedScrollView
)何时发生了滚动事件。
1.2、向上滑动隐藏Toolbar
效果图:
添加依赖
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:appcompat-v7:25.3.1'
布局结构
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.mg.axe.coordinatorlayoutscrollsimple.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
这里同样需要设置这两个属性:
app:layout_scrollFlags="scroll|enterAlways"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
1.3、其他的一些问题
通过以上的两个例子可以总结出基于CoordinatorLayout联动的两点规律:
1、父布局肯定是CoordinatorLayout
2、一定会设置app:layout_scrollFlags
和app:layout_behavior
两个属性。
滑动的View:滑动的view官方建议使用NestedScrollView或者RecyclerView。ListView在5.0以下就没有效果了。
高阶的使用:高阶使用当然是自定义behavior了。http://blog.csdn.net/gdutxiaoxu/article/details/53453958
3、NavigationView
NavigationView用来实现侧滑导航的布局。
效果图:
如果使用Android studio新建Android项目,在选择Activity时会有Navigation Drawer Activity。选择它会生成一个带有侧滑导航栏的Activity。
添加依赖
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
布局结构
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
NavigationView中,主要的两个属性:
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer"
如下图所示,NavigationView分为两部分,headerView 和 menu:
headview:就是普通的布局。
<?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="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:src="@mipmap/ic_launcher_round" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:text="AxeChen"
android:textColor="@android:color/secondary_text_light"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="不务正业的码农!" />
</LinearLayout>
menu:需要在res/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_camera" android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item android:id="@+id/nav_gallery" android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item android:id="@+id/nav_slideshow" android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item android:id="@+id/nav_manage" android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</group>
<item android:title="Communicate">
<menu>
<item android:id="@+id/nav_share" android:icon="@drawable/ic_menu_share"
android:title="Share" />
<item android:id="@+id/nav_send" android:icon="@drawable/ic_menu_send"
android:title="Send" />
</menu>
</item>
</menu>
3.1 修改样式
- 用代码修改 : NavigationView提供了很多setXXX()的方法。
-
xml文件中修改:
记得添加命名空间
3.1、其他的问题
menu图片为灰色问题
在使用的时候,会发现所有的图片多会展示成灰色,不管你的图片是否为彩色的图片。
如下方法解决:
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setItemIconTintList(null);
4、CardView
效果图:
CardView并不属于design包,所以使用CardView必须先添加依赖:
compile 'com.android.support:cardview-v7:25.3.1'
CardView是一个继承FrameLayout的View。用于布局的圆角、阴影等效果。基本使用只要知道CardView一些常用属性即可。
属性 | 作用 |
---|---|
cardElevation | 阴影的大小 |
cardElevation | 阴影最大高度 |
cardElevation | 卡片的背景色 |
cardCornerRadius | 卡片的圆角大小 |
contentPadding | 卡片内容于边距的间隔 |
contentPaddingBottom | 卡片内容与底部的边距 |
contentPaddingTop | 卡片内容与顶部的边距 |
contentPaddingLeft | 卡片内容与左边的边距 |
contentPaddingRight | 卡片内容与右边的边距 |
contentPaddingStart | 卡片内容于边距的间隔起始 |
contentPaddingEnd | 卡片内容于边距的间隔终止 |
cardUseCompatPadding | 设置内边距,V21+的版本和之前的版本仍旧具有一样的计算方式 |
cardPreventConrerOverlap | 在V20和之前的版本中添加内边距,这个属性为了防止内容和边角的重叠 |
如果直接给CardView添加android:foreground="?attr/selectableItemBackground"
就会加上水波纹点击反馈。
** 遇到的问题:**如果你在RecyclerView中使用CardView,如果你用的context是getApplicationContext(),可能会出现展示出夜间模式的效果。我当时使用getApplicationContext()是为了防止内存溢出。具体原因暂时还不清楚。
出现问题的代码。
public RecommendAdapter(Context context, List<ParkBean> parkBeanList) {
this.context = context.getApplicationContext();
this.parkBeanList = parkBeanList;
}
解决方案:不使用 context.getApplicationContext();
public RecommendAdapter(Context context, List<ParkBean> parkBeanList) {
//this.context = context.getApplicationContext();
this.context = context;
this.parkBeanList = parkBeanList;
}
5、TextInputLayout
5.1 基本使用
使用TextInputLayout控件的效果,需要将EditText作为TextInputLayout的子控件使用,而且只能有一个EditText。
添加依赖
compile 'com.android.support:design:25.3.1'
布局结构
<android.support.design.widget.TextInputLayout
android:id="@+id/tilayoutUserName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="30dp"
>
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="请输入用户名" />
</android.support.design.widget.TextInputLayout>
效果图:
5.2 错误提示
效果图:
TextInputLayout提供了非常方便的错误提示:
- 当需要错误提示时,调用TextInputLayout的
setError("错误提示文字")
。 - 如果要清空错误提示时,调用TextInputLayout的
setError(null)
。
以效果图中的用户名为例:
实现Editext的addTextChangedListener方法,监听输入字符。然后根据字符判断输入的字符串是否合理。
private void initListener() {
edName.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
checkName(s.toString());
}
});
}
private void checkName(String s) {
if (s.length() < 10) {
nameInput.setError("名字长度太短");
} else {
nameInput.setError(null);
}
}
6、RecyclerView
RecyclerView是Android程序员必学控件,如果现在还不会RecyclerView就赶紧学起来!
RecyclerView可以实现GirdView,ListView和瀑布流的效果。可以设置滑动的方向。
添加依赖
compile 'com.android.support:appcompat-v7:25.3.1'
6.1、LayoutManager
决定RecyclerView以一种怎样的形式展示由LayoutManager决定。
设置GridLayoutManager,实现GridView的效果。
设置LinearLayoutManager,实现ListView的效果。
设置StaggeredGridLayoutManager,实现瀑布流的的效果。
6.2 RecyclerView.Adapter、 RecyclerView.ViewHolder
实现数据的展示需要用到Adapter和ViewHolder
继承RecyclerView.Adapter的Adapter
必须重写的三个方法:
onCreateViewHolder: 创建ViewHolder并返回,负责为给Item创建视图。
onBindViewHolder: 负责将数据绑定到Item的视图上。
getItemCount: 返回总数据条数。
private class MyAdapter extends RecyclerView.Adapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder(LayoutInflater.from(RecyclerListViewActivity.this).inflate(R.layout.item_list, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
bindItemViewHolder((ItemViewHolder) holder, position);
}
@Override
public int getItemCount() {
return items.size();
}
}
继承RecyclerView.ViewHolder的ViewHolder
和使用Listview的Viewholder差不多。里面是一些初始化控件的操作。
public class ItemViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView tvTitle;
private TextView tvDescription;
public ItemViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.ivImg);
tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
tvDescription = (TextView) itemView.findViewById(R.id.tvDescription);
}
}
6.3 实现ListView、Gridview的效果
前面已经提到过设置不同LayoutManager会展示不同的效果。
实现Listview效果:
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
注意:LinearLayoutManager.VERTICAL为垂直滑动,如果设置成LinearLayoutManager.HORIZONTAL则会水平滑动。
效果图:
实现GridView效果:
recyclerView.setLayoutManager(new GridLayoutManager(this, 3, LinearLayoutManager.VERTICAL, false));
至于瀑布流,由于平时使用比较少,这里就不做详细的解释了。
7、TabLayout
效果图:
添加依赖
compile 'com.android.support:design:26.0.0-alpha1'
7.1、如何添加Tab。
从上图可看出,TabLayout提供了addTab()的方法来添加Tab。初始化Tab之后可以调用setXXX()
来决定是展示文字、图片或者自定义布局。
7.2、TabMode
TabLayout.MODE_SCROLLABLE:当元素过多时会超出父布局,并可以滑动Tab,Tab的宽度为Tab的实际宽度。
TabLayout.MODE_FIXED:无论界面由多少元素都会充满父布局。并且平均分配Tab的宽度。
7.3、监听Tab的选择状态
tabLayoutOne.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
7.4、修改TabLayou的样式
-
在布局文件中设置
在使用自定义属性时,记得添加命名空间。
在代码中设置
调用Tablayout的setXXX()的方法。在styles中修改
继承Widget.Design.TabLayout修改TabLayout的样式。
继承TextAppearance.Design.Tab修改Tab的样式。
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabMaxWidth">@dimen/tab_max_width</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>
<style name="MyCustomTabTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:textColorSecondary</item>
<item name="textAllCaps">true</item>
</style>
修改完毕之后记得将styles设置到TabLayout控件上。
7.5、与Viewpager的联动
效果图:
Viewpager+fragment+导航栏的这种UI结构。已经应用得非常广泛了,几乎是随处可见。TabLayout提供了和Viewpager联动方法,实现简单联动的方法也比较简单。
注:这里代码只考虑了Tab展示Text的情况。如果Tab展示的是图片或者自定义View,会稍微麻烦点。
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
viewPager设置完PagerAdapter之后,调用 tabLayout.setupWithViewPager(viewPager);即可。
PagerAdapter重写getPageTitle方法,根据Viewpager页面的position来展示不同Tab的Text。
@Override
public CharSequence getPageTitle(int position) {
return "第" + (position + 1) + "页";
}
不过这里还是埋了坑,有时候会出现Tab无法展示的情况(写过的都懂)。
这个链接可以解决这个问题:http://blog.csdn.net/sundy_tu/article/details/52682246
8、SnackBar
添加依赖
compile 'com.android.support:design:26.0.0-alpha1'
效果图:
SnackBar和Toast的用法差不多,都是通过show方法展示。和Toast不同之处是能和用户交互,同时提供了一些展示和消失的回调,修改SnackBar的文字颜色也比较简单。
8.1 SnackBar的基本使用
-
仅仅只提示文字:
弹出提示文字之后一段时间后会消失。
Snackbar.make(button, "第一次使用SnackBar", Snackbar.LENGTH_SHORT).show();
-
提供一个可以点击的按钮:
添加一个可以点击的按钮。
Snackbar.make(button, "第一次使用SnackBar", Snackbar.LENGTH_SHORT).setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}).show();
-
必须和用户交互之后才消失:
Snackbar.make()设置时间的参数改为:Snackbar.LENGTH_INDEFINITE。如果不设置这个参数,Snackbar都会在一段时间后消失。
Snackbar.make(button, "第一次使用SnackBar", Snackbar.LENGTH_INDEFINITE).setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}).show();
-
添加状态回调:
监听Snackbar的展示和消失。
Snackbar.make(button, "第一次使用SnackBar", Snackbar.LENGTH_INDEFINITE).setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
}).addCallback(new Snackbar.Callback() {
@Override
public void onShown(Snackbar sb) {
super.onShown(sb);
Toast.makeText(MainActivity.this, "弹出了", Toast.LENGTH_SHORT).show();
}
@Override
public void onDismissed(Snackbar transientBottomBar, int event) {
super.onDismissed(transientBottomBar, event);
Toast.makeText(MainActivity.this, "消失了", Toast.LENGTH_SHORT).show();
}
}).show();
8.2、修改Snackbar的样式
Snackbar只提供了一个修改按钮文字的方法:snackbar.setActionTextColor(Color.GREEN)
如需修改提示文字,背景的颜色等。可以通过snackbar.getView()获取到Snackbar对应的View进行修改。获取到Snackbar的View之后通过findById就能获取其他的一些控件。(Snackbar对应的布局文件在源码中可以找到。)
注意:这种方式还是存在风险。如果哪天Snackbar更新,Snackbar开发者修改了这些控件的Id,那就无法获取了。
Snackbar snackbar = Snackbar.make(button, "第一次使用SnackBar", Snackbar.LENGTH_INDEFINITE).setAction("确定", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
snackbar.setActionTextColor(Color.GREEN);
//修改背景
snackbar.getView().setBackgroundResource(R.color.colorPrimaryDark);
/* snackbar 并没有提供修改提示文字颜色的方法。不过可以通过找到
snackbar的布局design_layout_snackbar_include通过布局可以找到textview的id。
再通过snackbar.getView().findViewById(R.id.snackbar_text);
*/
TextView textView = (TextView) snackbar.getView().findViewById(R.id.snackbar_text);
textView.setTextColor(getResources().getColor(R.color.colorAccent));
snackbar.show();
9、FloatingActionButton
FloatingActionButton:界面浮动的标签,一般用于页面关键功能入口。FloatingActionButton非常简单,知道了解FloatingActionButton的一些属性和点击回调即可。
效果图:
常用属性:
先加入命名空间!
属性 | 作用 |
---|---|
fabSize | 定义FloatingActionButton的大小。auto(大) mini(小) normal(中) |
elevation | 普通状态下的阴影深度 |
pressedTranslationZ | 按下时的阴影深度 |
backgroundTint | 默认展示的背景颜色 |
rippleColor | 按下时的颜色(5.0以后为水波纹的颜色) |
layout_anchor | 定位其他控件,和其他控件边界相交 |
layout_anchorGravity | 和layout_anchor属性联用,在其他控件的相对位置 |
useCompatPadding | 设置内边距 |
borderWidth | 边框宽度(使用的比较少,效果也不好看) |
点击回调:
FloatingActionButton fabOne = (FloatingActionButton) findViewById(R.id.fabOne);
fabOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(v, "正在打开地图", Snackbar.LENGTH_SHORT).show();
}
});
最后
感谢各位程序员老爷看完这个又臭又长的博客!
源码地址:https://github.com/AxeChen/MaterialDesignSimple (欢迎star)