android design supprot library
注:来自对一篇文章的摘录。
地址: http://www.jianshu.com/p/1078568e859f
设计风格
首先开始:
activity的风格为:
在stytle里面添加:
<item name="colorPrimary">#2196f3</item>
<item name="colorPrimaryDark">#1565c0</item>
<item name="colorAccent">#E91e63</item>
添加android design supprot library的依赖,
在app的build.gradle文件添加一行代码:
compile 'com.android.support:design:22.0.0'
添加FAB
Floating Action Button (FAB) 是一个有阴影的圆形按钮,悬浮在app上面。
需要一些父类来使它在屏幕的右下方位置对齐,所以用 FrameLayout 来包裹 FloatingActionButton。
<android.support.v4.widget.DrawerLayout ...
xmlns:app="http://schemas.android.com/apk/res-auto"
....>
<FrameLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="@drawable/ic_plus"
app:fabSize="normal" />
</FrameLayout>
...
</android.support.v4.widget.DrawerLayout>
android:src 是用来定义的资源文件ID,而app:fabSize=”normal” 是用来定义FAB的大小的,
normal是指标准尺寸56dp的按钮,mini是小一点的,大小为40dp。
此时在4.4上,
而在5.0上面是这样的效果:
这是尚未完善的bug,利用配置资源来解决这个问题L:
在 res/values/dimens.xml
<dimen name="codelab_fab_margin_right">0dp</dimen>
<dimen name="codelab_fab_margin_bottom">0dp</dimen>
在res/values-21/dimens.xml
<dimen name="codelab_fab_margin_right">0dp</dimen>
<dimen name="codelab_fab_margin_bottom">0dp</dimen>
res/layout/xml里面:
<android.support.design.widget.FloatingActionButton
...
android:layout_marginBottom="@dimen/codelab_fab_margin_bottom"
android:layout_marginRight="@dimen/codelab_fab_margin_right"
.../>
这样就可以了。
设置阴影:
利用:app:borderWidth=”0” 来解决。
使用snackbar
snackbar 屏幕的地步一个微小的黑色线条显示一条简短的消息,类似于Toast,
它是作为UI的一部分,而不是覆盖在屏幕上的。
由下面代码实现:
Snackbar.make(someView, "hello,I am Snackbar!", Snackbar.LENGTH_SHORT)
.setAction("undo", new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO
}
})
.show();
第一个参数view或是layout,在它的底部显示一个snackbar,
setAction()是用在设置动作显示在snackbar的右侧,并有对应的监听,这不是必须的,可以移除。
如果是这样实现:
fabBtn = (FloatingActionButton) findViewById(R.id.fabBtn);
fabBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(rootLayout, "Hello. I am Snackbar!", Snackbar.LENGTH_SHORT)
.setAction("Undo", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
})
.show();
}
});
则效果是这样的:
这样不完善,需要设置snackbar 和FAB 之间的关联。
需要一个新的特殊的布局,使子views协调工作,是CoordinatorLayout
coordinatorlayout
CoordinatorLayout是一个让子views协调工作的布局
在CoordinatorLayout包裹一个FAB:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
... />
</android.support.design.widget.CoordinatorLayout>
现在结果: FAB随着Snackbar 的出现和消失而移动,也可以滑动使Snackbar消失。
但是在低于5.0的系统上面,
当Snackbar滑动消失时,FAB忘记移动下来了,
这是一个bug,可以设置FAB的margin bottom 和margin right 为一些非零的正数值时,
它是正常实现的,修改:
res/values/dimens/xml
<dimen name="codelab_fab_margin_right">0.1dp</dimen>
<dimen name="codelab_fab_margin_bottom">0.1dp</dimen>
结果:
如果计划使用android design support library, 要注意CoordinatorLayout,
它就像是整个library的核心。
使用toolbar代替actionbar
在style属性里面隐藏actionbar:
<style name="AppTheme" parent="Theme.App.Compat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
然后在CoordinatorLayout里面的FAB之前正确的放一个toolbar组件。
<android.support.design.widget.CoordinatorLayout
...>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
/>
<android.support.design.widget.FloatingActionButton
...>
</android.support.design.widget.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>
现在要在.java里面说明,要使用toolbar:
Toolbar toolbar;
private void initInstances() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
...
}
由于放在CoordinatorLayout的东西必须被设计和实现成与它一起合作,否则将不与其view协作。
但是toolbar是不合适的,所以准备了另外一个组件AppBarLayout包裹toolbar:
<android.support.design.widget.CoordinatorLayout
...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
...>
<android.support.design.widget.FloatingActionBar
...>
</android.support.design.widget.FloatingActionBar
</android.support.design.widget.CoordinatorLayout
现在就可以了!
在内容区域里放东西。
放两个button,
...
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yo Yo"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yo Yo"/>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
...>
这些按钮放在了toolbar的下面,,有些不协调。
这是因为linearlayout没有被设计成与CoordinatorLayout协同工作,类似与之前的toolbar,
它的解决方法更简单一些,在linearlayout里面添加一个属性,告诉它滚动的行为:
<LinearLayout
...
app:layout_behavior="@string/appbar_scrolling_view_behavior"
...>
现在就可以了:
TabLayout
应该把tab放在屏幕的顶部而不是底部,它应该在阴影部分的上面,所以应该把它放在
AppBarLayout(里面有toolbar)里面,沿着toolbar,这是可行的,因为AppBarLayout
是继承一个垂直的LinearLayout.
<android.support.design.widget.AppBarLayout ...>
<android.support.v7.widget.Toolbar ... />
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>
在Java里面添加一些tabs
TabLayout tabLayout;
private void initInstances() {
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
...
}
结果:
背景色会自动设置为primary color(主题色),而导航线的颜色则是强调色,
tab的字体颜色仍然是黑色的,希望是白色的,在tablayout添加属性:
<android.support.design.widget.TabLayout
...
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
现在是白色的了,结果:
可以像上面那样手动控制tabLayout,或者让它和viewPager一起工作,自动调用
setupWithViewPager()…
调整两个属性来显示TabLayout:
app:tabMode 如果想在屏幕上显示每个单独的tab,就设置tab为fixed;
只适合少数的tab,或者设置为scrollable让用户去滚动tab,想GooglePlayStroe.
app:tabGravity 如果想要分配所有的空间给每个tab,则设置这个属性为fill,
如果想要所有的tab在屏幕的中间设为center,注意如果tabMode设为scrollable,
则这个属性被忽略。
当随着内容滚动时,让AppBarLayout退出屏幕
让AppBar可以随着内容滚出屏幕,来获得更多的空间显示内容。
首先在linearLayout里面多加几个button,使屏幕需要滚动,
然后用ScrollView 包裹这个linearLayout,不要忘记把linearLayout里面的
layout_behavior 移动到ScrollView,因为现在ScrollView是CoordinatorLayout的
最直接的子view。
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
...
</LinearLayout>
</ScrollView>
然后为toolbar添加一个滚动的标志,
<android,support.v7.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways" />
结果为:
toolbar并没有随着内容而滚出屏幕,原因和上面一样,因为ScrollView没有设计成与
CoordinatorLayout协同工作,需要利用另外一个view: NestedScrollView,Android
Support Library v4 里有提供,设计出来的目的就是为了与CoordinatorLayout协同
工作的。
<android.support.v4.widget.NestedScrollView
...>
<LinearLayout
...>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
注意:listview也是和CoordinatorLayout不能协同工作的,只有recyclerView可以。
以后的发展也许会的。
结果:
注意到toolbar滚出了屏幕,但tabLayout仍然还在,因为没有给tabLayout
设置任何滚动标志,如果想要tablayout也在屏幕上消失,只需要设置属性:
<android.support.design.widget.TabLayout
...
app:layout_scrollFlags="scroll|enterAlways" />
结果:
这里会有一些手势上的bug,把它拉回屏幕是很困难的,要等下一个版本修复了。
看一下四个属性值:
scroll 设置这个view随着内容滚动,
enterAlwaysCollapsed 定义view是如何回到屏幕的,当view已经声明了一个最小高度
(minHeight)并且使用了这个标志,那么view只有回到最小高度的时候才会展开,
只有当view已经到达顶部后它才会重新展开全部高度,滚动标志这样使用:
scroll|enterAlwaysCollapsed
enterAlways 这个标志确保了任何向下滚动的操作都会让这个view变得可见,达到快速返回
(quick return)的效果,使用:scroll|enterAlways
exitUntilCollapsed view 将关闭滚动知道它被折叠起来(有minHeight)并且一直保持这样。
例如:
<android.support.v7.widget.Toolbar
...
android:layout_height="192dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:gravity="bottom"
android:paddingBottom="12dp"
android:minHeight="?attr/actionBarSize"
结果如下:
为了实现其他的功能,先移除TabLayout
在布局里面删掉:
<!--android.support.design.widget.TabLayout -->
在Java里面,删除:
//tabLayout = (TabLayout) findViewById(R.id.tabLayout);
//tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
//tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
//tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
Make toobar collapsable 使toolbar可折叠
就像在exitUnitilCollapsed所示的例子,toolbar可以展开折叠,但是toolbar仍然
离开了屏幕,最好的体验是让这些icon应该留在屏幕内。
Design Support Library已经为这个准备好了,利用CollapsingToolbarLayout可以让toolbar
折叠起来,像其他组件一样,具体操作如下:
- 用collapsingToolbarLayout 包裹toolbar,但仍然在AppBarLayout里面
- 从toolbar中删除layout_scrollFlags
- 为collapsingToolbarLayout声明layout_scrollFlags,并且将layout_scrollFlags设置成
scroll|exitUntilCollapsed - 改变AppBarLayout扩张状态时的布局高度大小,这里使用256dp
最终代码:
<android.support.design.widget.AppBarLayout
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
这里的结果是:
如果没有app:layout_collapseMode=”pin”,则toolbar icon仍然会滚出屏幕。
但是现在没有标题文字了,因为在用CollapsingToolbarLayout包裹tool后,它就没有了,
需要在.java里面手动设置:
collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout);
collapsingToolbarLayout.setTitle("Design Library");
这时标题字体是黑色的,这是没有对AppBar设置主题,在xml里面的AppBarLayout里面加一句:
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
结果:
由于CollapsingToolbarLayout 的 特点,应用的标题文字在收缩和展开状态是会自动过渡的,
想要在展开状态改变标题文字的位置,则可以通过应用的 margin 的四个属性,
app:expandedTitleMargin, app:expandedTitleMarginBottom, app:expandedTitleMarginEnd
以及 app:expandedTitleMarginStart
想要在折叠和展开状态时改变文本的显示,可以这样来简单的实现:
设置TextAppence分别通过 app:collapsedTitleTextAppearance 和
app:expandedTitleTextAppearance 来设置。
设置margin为64dp
<android.support.design.widget.CollapsingToolBarLayout
...
app:expandedTitleMarginStart="64dp"
结果:
为appBar添加图片
CollapsingToolbarLayout 是继承自 FrameLayout,可以添加一个ImageView作为
toolbar的背景图片:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/header" />
<android.support.v7.widget.Toolbar
...
这里结果:
蓝色的导航条仍旧显示着,这是要解决的问题,有一个 Toolbar 的背景看起来不是酷炫,
从 Toolbar 移除它,只需要下面这行代码就行了:
android:background="?attr/colorPrimary"
结果:
基本是实现了,但是看起来太呆,采用视差模式可以更加优雅,
只需声明 collapse 就行了:
<ImageView
...
app:layout_collapseMode="parallax" />
结果:
可自行设置视差系数,在0.0-1.0 之间。
app:layout_collapseParallaxMultiplier="0.7"
注意到 App Bar 的背景总显示一张图片, 可以让它在收缩的时候自动恢复到普通的颜色,
通过声明属性: app:contentScrim
<android.support.design.widget.CollapsingToolbarLayout
...
app:contentScrim="?attr/colorPrimary">
结果:
Navigation Drawer 侧滑
首先,为Drawer Menu创建一个标题布局文件:
res/layout/nav_header.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="192dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/nav_header_bg"
android:scaleType="centerCrop" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/nuuneoi"
android:layout_gravity="bottom"
android:layout_marginBottom="36dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="16dp"
android:text="nuuneoi"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</FrameLayout>
创建一个菜单资源文件:
res/menu/navigation_drawer_items.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="all">
<item
android:id="@+id/navItem1"
android:icon="@drawable/ic_action_location_found_dark"
android:title="Home"/>
<item
android:id="@+id/navItem2"
android:icon="@drawable/ic_action_location_found_dark"
android:title="Blog"/>
<item
android:id="@+id/navItem3"
android:icon="@drawable/ic_action_location_found_dark"
android:title="About"/>
<item
android:id="@+id/navItem4"
android:icon="@drawable/ic_action_location_found_dark"
android:title="Contact"/>
</group>
</menu>
naviagtion与两个资源文件绑定起来,作为 Drawer Menu的菜单区域
用下面的代码代替已经存在的白色的LinearLayout:
...
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:itemIconTint="#333"
app:itemTextColor="#333"
app:menu="@menu/navigation_drawer_items" />
</android.support.v4.widget.DrawerLayout>
现在就可以利用Drawer Menu.
效果:
为了处理菜单项的点击事件,声明setNavigationItemSelectedListener来监听,
Navigation navigation;
private void initInstances() {
...
navigation = (NavigationView) findViewById(R.id.navigation);
navigation.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id) {
case R.id.navItem1:
break;
case R.id.navItem2:
break;
case R.id.navItem3:
break;
}
return false;
}
});
}
在实际使用中,可以随意声明你想要定义的header view和修改菜单项。
添加TextInputLayout
替换旧的editText,让风格升级,
需要用TextInputLayout包裹住一个editText,
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username" />
</android.support.design.widget.TextInputLayout>
在里面再次添加一个password的editText,
然后把这两个控件放到NestedScrollView看结果:
后记
这【篇总结是我看着另外一个作者的博客,一点一点写下来的,我自己之前已经在
android studio上实现了这个效果,感觉这个真的很棒,很赞,
便自己记录下来,也学到了一些东西,希望在不久这些很优雅的APP更多。
注:用的到的地方
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
<!--Tab被选中字体的颜色-->
app:tabSelectedTextColor="@android:color/holo_blue_bright"
<!--Tab未被选中字体的颜色-->
app:tabTextColor="@android:color/black"
<!--Tab指示器下标的颜色-->
app:tabIndicatorColor="@android:color/holo_blue_bright"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
chenzhao@hustunique.com