一个Demo带你认识Design库,纯原生控件也能做出很漂亮的效果

时间:2021-10-22 11:18:58

欢迎转载,转载请注明出处http://blog.csdn.net/w804518214/article/details/51340984


不得不说开发者头条的APP真的是Material Design的典范,纯原生控件也能做出很漂亮的效果,并且不需要处理各种复杂的滑动冲突!!其主页基本把Design库的几个控件展示了一遍,今天就顺手借开发者头条主页的实现来简单介绍下官方Design扩展包里几个控件的使用.本文不会详细展开讲每个控件,仅仅针对demo效果的实现,想深入研究的推荐看官方指南!

先上效果图:
一个Demo带你认识Design库,纯原生控件也能做出很漂亮的效果

布局

  1. 最外层是个侧滑控件v4包里的 DrawerLayout 导航用的是 design包里的 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"
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>
  1. 主界面布局

主界面的根布局是CoordinatorLayout,其内部上半部分是 AppBarLayout,下面是一个ViewPager. 右下角有一个FloatingActionButton。 AppBarLayout内部包含代替系统actionbar的Toolbar和可以关联ViewPager做页面选项卡的TabLayout。
而viewpager的每个页面内只是一个包含在SwipeRefreshLayout内部的RecyclerView而已.

各控件布局之间的包含关系如下

DrawerLayout  CoordinatorLayout AppBarLayout         Toolbar
TabLayout

ViewPager

FloatingActionButton

NavigationView 导航头部自定义布局layout/nav_header_main

menu

app_bar_main.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"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.sleepycoder.designexample.MainActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/appBarLayout"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />

<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
app:tabIndicatorColor="#fff"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
android:layout_height="wrap_content">

</android.support.design.widget.TabLayout>
</android.support.design.widget.AppBarLayout

<android.support.v4.view.ViewPager
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewPager">

</android.support.v4.view.ViewPager>


<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

DrawerLayout

  • DrawerLayout内部包含至少包含两个布局,
  • 第一个子布局必须为主View,主View的宽和高必须是match_parent,
  • 后面的子布局是menu view,menu view必须指定android:layout_gravity,
  • 如果有2个menu view,分别设置layout_gravity为 “start”和”end”,就会同时有左滑和右滑菜单。
  • 根据设计规范 menu view宽度不能太宽,最好不要超过320dp

我们这里的menu view是个NavigationView

DrawerLayout和Toolbar绑定,这里使用的是官方推荐的ActionBarDrawerToggle,点击自带动画效果

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

创建ActionBarDrawerToggle并关联toolbar
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
//给DrawerLayout添加监听
drawer.addDrawerListener(toggle);
//同步关联DrawerLayout的状态
toggle.syncState();

重写Activity的onBackPressed事件 点击返回如果DrawerLayout处于侧滑打开状态则关闭

    @Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
//关闭layout_gravity="start" 的侧滑菜单
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}

NavigationView顾名思义专门用来做导航的侧滑或者在平板模式上做侧边导航的view,使用起来也非常简单
- 在xml里绑定布局

    //头部布局
app:headerLayout="@layout/nav_header_main"
//菜单
app:menu="@menu/activity_main_drawer"

headerLayout是一个自定义layout 内部空间可以通过findViewById拿到
app:menu 是menu的xml资源

  • 为menu绑定监听
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);

CoordinatorLayout

CoordinatorLayout是Design包里最大牌的控件了,使用情形也比较多,网上有很多教程,这里就不展开来讲了,只讲一下demo里隐藏toolbar的使用

先看一下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"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.sleepycoder.designexample.MainActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/appBarLayout"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
app:tabIndicatorColor="#fff"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
android:layout_height="wrap_content">

</android.support.design.widget.TabLayout>
</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewPager">

</android.support.v4.view.ViewPager>


<android.support.design.widget.FloatingActionButton android:id="@+id/fab"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

CoordinatorLayout的作用就是不需要代码处理就可以实现各种比较炫的动画效果,这里是关联
Toolbar和下面的recyclerView使toolbar可以随recyclerView的向下滚动而展示,随recyclerView的向上滚动而消失。
CoordinatorLayout本身可以看做一个FrameLayout,其内部控件的布局和FrameLayout一致。在需要动态关联的控件上分别加上app:layout_scrollFlags和app:layout_behavior属性。

在需要联动的目标控件内加上app:layout_scrollFlags属性,滑动事件源控件加上app:layout_behavior属性

这里用到的”@string/appbar_scrolling_view_behavior”都是在design包内定义好的,
需要注意的是这些属性都是5.x以后的新控件才支持的,以前的控件不支持,扩展包的内的控件也需要相应版本的(22+),如listview就不支持,所以尽快抛弃listview转投recyclerview的怀抱吧

CoordinatorLayout的用法详解看这里http://my.oschina.net/kooeasy/blog/484593

AppBarLayout

AppBarLayout就是一个垂直的LinearLayout,但是添加了很多系统支持能和其他可滑动控件做交互。用法就当个线性布局用就好了,内部需要滑动交互的控件需设置app:layout_scrollFlags属性。需要和CoordinatorLayout一起使用,详细使用见CoordinatorLayout的连接。

TabLayout

Tablayout是官方提供的选项卡控件,内部的tab可以代码添加,也可以写下xml布局文件里,还可以与viewpager绑定通过PagerAdapter自动生成相应tab。

  • TabLayout代码添加tab
 TabLayout tabLayout = ...;
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab3"));
  • 布局文件添加Tab
 <android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">

<android.support.design.widget.TabItem
android:text="@string/tab_text"/>

<android.support.design.widget.TabItem
android:icon="@drawable/ic_android"/>

</android.support.design.widget.TabLayout>
  • 与ViewPager绑定

demo里使用的就是这种方法

 viewPager = (ViewPager) findViewById(R.id.viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
···
viewPager.setAdapter(myPagerAdapter);
tabLayout.setupWithViewPager(viewPager);

需要注意的是 viewpager的Adapter必须重写public CharSequence getPageTitle(int position)方法返回的Title就是tab的title

  • 常用xml属性
 //指示条颜色
app:tabIndicatorColor="#fff"
//指示条高度
app:tabIndicatorHeight="3dp"
//tab模式 fixed固定平均分布 ,scrollable可滑动的 TabLayout本身就是
app:tabMode="fixed"
// center:当tab较少的时候集中居中显示 fill:正常填充模式
app:tabGravity="center"

···

详细介绍请看官方文档,国内的博客没见有讲的详细又通俗的,官方文档讲的倒是很好理解。

SwipeRefreshLayout + RecyclerView 下拉刷新 滑动到底部自动加载 分组悬停

  • 下拉刷新 进入界面自动加载数据并出现刷新动画

SwipeRefreshLayout下拉属性的使用很简单就不说了,但有时候我们想进入界面自动加载数据并出现刷新动画就需要特别操作一下了
实现很简单 使用handler.postDelay方法就行,如下

  getHandler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
refreshListener.onRefresh();
}
}, 100);
  • 滑动到底部自动加载

设置监听滑动即可

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
RecyclerView.LayoutManager mLayoutManager = recyclerView.getLayoutManager();
int lastVisibleItem = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
int totalItemCount = mLayoutManager.getItemCount();
//最后一项显示且是下滑的时候调用加载
if (lastVisibleItem >= totalItemCount-1 && dy > 0) {
//需要自己设置排除多次重复调用
}
}
});

底部加载的动画的简单实现: 在单项布局里面隐藏一个加载布局,在onBindViewHolder内判断显示隐藏即可,还可以在设置个标志位表示没有更多数据

    @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(position>0 ){
((ContentHolder)holder).tvContent.setText(dataList.get(position-1));
if(position>5 && position==dataList.size()){
((ContentHolder)holder).pBar.setVisibility(View.VISIBLE);
}else{
((ContentHolder)holder).pBar.setVisibility(View.GONE);
}
}
}
  • 分组悬停

分组悬停即stickyheader效果推荐使用第三方库,该库提供了一个Adapter接口和一个ItemDecoration,控件还是使用原生的RecyclerView
·

compile ‘com.timehop.stickyheadersrecyclerview:library:0.4.3’

1.使用 adapter实现StickyRecyclerHeadersAdapter接口

public class StickyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements StickyRecyclerHeadersAdapter<RecyclerView.ViewHolder>

2.使用adapter构造ItemDecoration,调用recyclerView.addItemDecoration


adapter = new StickyRecyclerAdapter(dataList);
recyclerView.setAdapter(adapter);
//设置悬停
recyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(adapter));
//分割线
recyclerView.addItemDecoration(new DividerDecoration(getActivity()));

具体的实现参见demo代码

其他

  • Snackbar ==强烈推荐使用==

Snackbar是Toast的替代者,样式更美观,还可添加交互功能更强大,算是个Toast和Notification的结合,使用很方便示例:

Snackbar.make(view, "那些让你相见恨晚的方法、类或接口", Snackbar.LENGTH_LONG)
.setAction("查看", new View.OnClickListener() {
@Override
public void onClick(View v) {
···
}
}).show();

本来想详细介绍一下的,不过正好鸿洋大神今天就写了一篇,比我这小白强太多了,具体用法大家就看鸿洋的文章吧没时间解释了,快使用SnackBar!

  • FloatingActionButton的使用

FloatingActionButton就是加了特效的ImageView,使用方法参考ImageView就可以,可以参考鸿洋的博客http://blog.csdn.net/lmj623565791/article/details/46678867

  • Toolbar的使用

参见http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1118/2006.html

Demo下载地址

http://download.csdn.net/detail/w804518214/9513346
下载的压缩包解压后的文件夹是AndroidStudio的一个module,不是一个完整的工程项目,你可以新建一个工程导入module也可以在你自己的工程上导入demo。