MaterialDesign下的多个UI框架的综合案例详解
2016-09-10 13:03
387 查看
写了几篇关于Design下的UI框架,今天打算结合协调者布局CoordinatorLayout及ToolBar等多个Design下的控件。然后集成成一个小Demo供大家学习。不多说了,大家先看下效果图吧。
首先是布局文件,大体框架是DrawerLayout里面包含一个NavigationView和一个CoordinatorLayout。CoordinatorLayout中则包括AppBarLayout和ViewPager。AppBarLayout里面包含了ToolBar和TabLayout。来看下activity_main.xml:
http://blog.csdn.net/tracy1024/article/details/52202034
内容布局的 include_content_main.xml 就是我所说的CoordinatorLayout:
接下来我就来介绍下这个布局中的CoordinatorLayout,我习惯称作协调者布局,可以看做一个容器,协调各种子布局的联动。它属于MaterialDesign中比较重要的东东,最常见的情况下是结合CollapsingToolbarLayout一起使用,配合两个空间的不同属性设置形成比较炫酷的动画效果,本例将有涉及到。我接着介绍下上面布局文件中需要注意的地方。CoordinatorLayout内层的AppBarLayout需跟ScollingView并列,我们这里的ScollingView指的是ViewPager。而ViewPager中必须得有
http://blog.csdn.net/tracy1024/article/details/52318946
然后这里的ViewPager我们需要用到一个简单的Fragment,由RecyclerView,RecyclerView里的item为CardView组成,RecyclerView和CardView的使用之前文章也有专门介绍过,需要连接的话请移步:
http://blog.csdn.net/tracy1024/article/details/52463503
下面分别是Fragment的布局文件及RecyclerView的布局文件,首先是fragment_dummy.xml:
然后就是item_recyclerview_dummyfragment.xml:
这些如果看了之前我的几篇文章相信都看得明白。这里的数据我为了方便是写死了的。
好了,第一个页面的大体结构就是这样子。我们看下代码怎么用,MainActivity.java:
这样的话则跟普通Toast一样,只是样式不一样。
如果是写成我代码上的那种方式,则可以为弹出的SnackBar中的Action添加点击事件进行具体操作。用法比较简单。上面出现的DummyFragment和MyPagerAdapter这里我也贴下代码。比较简单,DummyFragment:
到这里结束就是主页面的显示了。接下来就点击MainActivity中的cardView然后跳转的DetailActivity.首先看下它的布局文件:
这个页面的话我是用CoordinatorLayout和CollapsingToolbarLayout一起配合使用。我来解释下每个节点的属性意思:
ImageViewz中的
Toolbar中的
最后是FloatingActionButton的
好了。布局文件就是这样子。下面看下DetailActivity的代码:
到此。完成的例子就讲解到这里了。不好的地方请指出。
共勉!
首先是布局文件,大体框架是DrawerLayout里面包含一个NavigationView和一个CoordinatorLayout。CoordinatorLayout中则包括AppBarLayout和ViewPager。AppBarLayout里面包含了ToolBar和TabLayout。来看下activity_main.xml:
<android.support.v4.widget.DrawerLayout android:id="@+id/drawerLayout_main" 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="false"> <!-- 内容布局--> <include layout="@layout/include_content_main"/> <android.support.design.widget.NavigationView android:id="@+id/navigationView_main" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/navigation_header" app:menu="@menu/menu_navigationview"/> </android.support.v4.widget.DrawerLayout>其中NavigationView的介绍,在之前的文章已经介绍了,需要了解的话请到
http://blog.csdn.net/tracy1024/article/details/52202034
内容布局的 include_content_main.xml 就是我所说的CoordinatorLayout:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinatorLayout_main" 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.support.design.widget.AppBarLayout android:id="@+id/appBarLayout_main" 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_main" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> <android.support.design.widget.TabLayout android:id="@+id/tabLayout_main" android:layout_width="match_parent" android:layout_height="wrap_content"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager_main" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" android:onClick="clickButton" android:src="@mipmap/ic_done"/> </android.support.design.widget.CoordinatorLayout>
接下来我就来介绍下这个布局中的CoordinatorLayout,我习惯称作协调者布局,可以看做一个容器,协调各种子布局的联动。它属于MaterialDesign中比较重要的东东,最常见的情况下是结合CollapsingToolbarLayout一起使用,配合两个空间的不同属性设置形成比较炫酷的动画效果,本例将有涉及到。我接着介绍下上面布局文件中需要注意的地方。CoordinatorLayout内层的AppBarLayout需跟ScollingView并列,我们这里的ScollingView指的是ViewPager。而ViewPager中必须得有
app:layout_behavior="@string/appbar_scrolling_view_behavior"这个属性。而如果AppBarLayout中的子布局想跟ViewPager联动的话,必须有
app:layout_scrollFlags="scroll|enterAlways"这个属性与ViewPager的app:layout_behavior相呼应。这个属性代表的意思这个是可以滚动的且一旦向下拉,该属性所修饰的控件就显示。后面我会介绍该属性的其他设置方法。AppBarLayout的话我里面还多放了TabLayout。之前文章也有介绍了,需要了解的话请移步:
http://blog.csdn.net/tracy1024/article/details/52318946
然后这里的ViewPager我们需要用到一个简单的Fragment,由RecyclerView,RecyclerView里的item为CardView组成,RecyclerView和CardView的使用之前文章也有专门介绍过,需要连接的话请移步:
http://blog.csdn.net/tracy1024/article/details/52463503
下面分别是Fragment的布局文件及RecyclerView的布局文件,首先是fragment_dummy.xml:
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerView_fragment" android:layout_width="match_parent" android:layout_height="match_parent" />
然后就是item_recyclerview_dummyfragment.xml:
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView 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="wrap_content" android:layout_margin="@dimen/card_margin" android:elevation="5dp" android:paddingLeft="8dp" android:paddingRight="8dp" android:paddingTop="8dp" app:cardCornerRadius="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:orientation="horizontal"> <LinearLayout android:layout_width="120dp" android:layout_height="120dp" android:gravity="center" android:orientation="vertical"> <ImageView android:layout_width="120dp" android:layout_height="70dp" android:background="@mipmap/abc"/> <Button android:layout_width="match_parent" android:layout_height="30dp" android:layout_margin="8dp" android:background="@drawable/button_bg" android:text="+关注" android:textColor="#FFFFFF"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:orientation="vertical"> <TextVie 4000 w android:layout_width="match_parent" android:layout_height="wrap_content" android:text="文章标题" android:textSize="20sp" android:textStyle="bold"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="浏览量:40000" android:textSize="12sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:ellipsize="end" android:maxLines="2" android:text="故事,启迪你的人生;美文,陶冶你的情操,有声朗读,洗礼你的耳朵……" android:textSize="18sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="05-20 更新至第78期"/> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>
这些如果看了之前我的几篇文章相信都看得明白。这里的数据我为了方便是写死了的。
好了,第一个页面的大体结构就是这样子。我们看下代码怎么用,MainActivity.java:
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private Context mContext = this; private DrawerLayout drawerLayout_main; private NavigationView navigationView_main; private ViewPager viewPager_main; private TabLayout tabLayout_main; private Toolbar toolbar_main; private List<Fragment> totalList = new ArrayList<Fragment>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initToolbar(); initTabsAndViewPager(); } private void initView() { drawerLayout_main = (DrawerLayout) findViewById(R.id.drawerLayout_main); //初始化导航试图 navigationView_main = (NavigationView) findViewById(R.id.navigationView_main); navigationView_main.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem item) { item.setChecked(true); drawerLayout_main.closeDrawers(); return true; } }); } private void initToolbar() { // toolbar_main = (Toolbar) findViewById(R.id.toolbar_main); // setSupportActionBar(toolbar_main); // // //重新设置logo前方的图标 // toolbar_main.setNavigationIcon(R.mipmap.ic_menu); // //toolbar_main.setLogo(R.mipmap.ic_launcher); // toolbar_main.setTitle("MaterialDesign综合案例"); toolbar_main = (Toolbar) findViewById(R.id.toolbar_main); setSupportActionBar(toolbar_main); // 重新设置logo前方的图标 toolbar_main.setNavigationIcon(R.mipmap.ic_menu); //title默认为APP的名称,也可以重新设置 toolbar_main.setTitle("Design综合案例"); //如果不设置子标题,那么title在垂直居中的位置显示。如果设置则上下各一行显示。可以分别设置文字颜色。 toolbar_main.setSubtitle("Design介绍");//设置子标题 toolbar_main.setTitleTextColor(Color.WHITE);//设置Title的颜色 toolbar_main.setSubtitleTextColor(Color.YELLOW);//设置子标题的颜色 } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } private void initTabsAndViewPager() { tabLayout_main = (TabLayout) findViewById(R.id.tabLayout_main); String[] arrTabTitles = getResources().getStringArray(R.array.arrTabTitles); viewPager_main = (ViewPager) findViewById(R.id.viewPager_main); for (int i = 0; i < arrTabTitles.length; i++) { //tabLayout_main.newTab().setIcon(R.mipmap.ic_launcher); DummyFragment fragment = DummyFragment.getInstance(i + 1); totalList.add(fragment); } PagerAdapter adapter = new MyPagerAdapter( getSupportFragmentManager(), totalList, arrTabTitles); viewPager_main.setAdapter(adapter); tabLayout_main.setupWithViewPager(viewPager_main);//必须设置该属性才能使tab跟ViewPager关联起来 tabLayout_main.setTabsFromPagerAdapter(adapter);//使TabLayout中的tab与Adapter中的fragment对应起来 } public void clickButton(View view) { switch (view.getId()) { //FloatingActionButton的监听事件 case R.id.fab_main: Snackbar.make(view, "Snackbar comes out", Snackbar.LENGTH_LONG) .setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "Toast comes out", Toast.LENGTH_SHORT).show(); } }).show(); break; } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //ToolBar上面的图标的监听事件,打开NavigationView case android.R.id.home: drawerLayout_main.openDrawer(GravityCompat.START); break; } return super.onOptionsItemSelected(item); } }上面需要注意的我添加了注释,上面出现了一个SnackBar,这个我前面并没有说过。这里简单说一下。它也是Design下的控件,跟Toast用法相似,只是它多了个点击监听,如果写成
Snackbar.make(view, "Snackbar comes out", Snackbar.LENGTH_LONG).show();
这样的话则跟普通Toast一样,只是样式不一样。
如果是写成我代码上的那种方式,则可以为弹出的SnackBar中的Action添加点击事件进行具体操作。用法比较简单。上面出现的DummyFragment和MyPagerAdapter这里我也贴下代码。比较简单,DummyFragment:
public class DummyFragment extends Fragment { private RecyclerView recyclerView_fragment; public static DummyFragment getInstance(int tabindex) { DummyFragment fragment = new DummyFragment(); Bundle bundle = new Bundle(); bundle.putInt("tabindex", tabindex); fragment.setArguments(bundle); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { recyclerView_fragment = (RecyclerView) inflater.inflate(R.layout.fragment_dummy, container, false); return recyclerView_fragment; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); recyclerView_fragment.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); recyclerView_fragment.setAdapter(new MainRecyclerAdapter(getActivity())); } }MyPagerAdapter:
public class MyPagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> list = null; private String[] arrTabTitles = null; public MyPagerAdapter(FragmentManager fm, List<Fragment> list, String[] arrTabTitles) { super(fm); this.list = list; this.arrTabTitles = arrTabTitles; } @Override public Fragment getItem(int position) { return list.get(position); } @Override public int getCount() { return list.size(); } @Override public CharSequence getPageTitle(int position) { return arrTabTitles[position]; } }然后我们再来看看DummyFragment中RecyclerView中需要的Adapter:MainRecyclerAdapter:
public class MainRecyclerAdapter extends RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder> { private Context mContext; public MainRecyclerAdapter(Context mContext) { this.mContext = mContext; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_recyclerview_dummyfragment, parent, false); return new ViewHolder(view); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onBindViewHolder(final ViewHolder holder, int position) { final View view = holder.mView; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //为每个CardView设置动画过渡然后跳转到详情页 ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationZ", 20, 0); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mContext.startActivity(new Intent(mContext, DetailActivity.class)); } }); animator.start(); } }); } @Override public int getItemCount() { return 10; } public static class ViewHolder extends RecyclerView.ViewHolder { public final View mView; public ViewHolder(View view) { super(view); mView = view; } } }
到这里结束就是主页面的显示了。接下来就点击MainActivity中的cardView然后跳转的DetailActivity.首先看下它的布局文件:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout android:id="@+id/main_content" 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.AppBarLayout android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsingToolbarLayout_detail" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="#880000ff" app:expandedTitleMarginEnd="0dp" app:expandedTitleMarginStart="10dp" app:layout_scrollFlags="scroll|enterAlwaysCollapsed|exitUntilCollapsed"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:scaleType="fitXY" android:src="@mipmap/ic_banner" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.8"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar_detail" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView_detail" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_width="match_parent" android:layout_height="match_parent"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_detail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/fab_margin" android:onClick="clickButton" android:src="@mipmap/ic_discuss" app:layout_anchor="@id/collapsingToolbarLayout_detail" app:layout_anchorGravity="bottom|right|end"/> </android.support.design.widget.CoordinatorLayout>
这个页面的话我是用CoordinatorLayout和CollapsingToolbarLayout一起配合使用。我来解释下每个节点的属性意思:
android:fitsSystemWindows="true"这句话代表的是设置应用布局时是否考虑系统窗口布局;如果为true,将调整系统窗口布局以适应我自定义的布局。
app:contentScrim="#880000ff"这个的话我理解为衬托的颜色。就是当我们把页面向下拉的时候,CollapsingToolbarLayout折叠完成时显示的衬托颜色。
app:expandedTitleMarginEnd="0dp" app:expandedTitleMarginStart="10dp"这两个属性我是用来展开状态改变标题文字的位置。我们还可以用
app:expandedTitleMargin,
app:expandedTitleMarginBottom这两个来控制。
app:layout_scrollFlags="scroll|enterAlwaysCollapsed|exitUntilCollapsed"这个的话是用来控制CollapsingToolbarLayout滑动时和设置了behavior属性的控件之间联动的关系。scroll表示是可以滑动的,enterAlwaysCollapsed表示的时向下拉动到顶部时,View才出现。exitUntilCollapsed表示的是当折叠完全(高度已到最小值)时停止折叠。enterAlways表示的是一旦向下拉动,View就露头。snap表示的是滚动到一半后一放手,则全部完成折叠。
ImageViewz中的
app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.8"首先前者没设置为pin,后者则为设置视差。简单来说就是为了ImageView产生视差效果。后者值越大则越不同步。
Toolbar中的
app:layout_collapseMode="pin"表示在折叠完毕时,停在顶部。
最后是FloatingActionButton的
app:layout_anchor="@id/collapsingToolbarLayout_detail" app:layout_anchorGravity="bottom|right|end"这两个属性只有在CoordinatorLayout中才有效,前者表示依附在哪个控件上。后者则表示依附在控件的哪个位置上。
好了。布局文件就是这样子。下面看下DetailActivity的代码:
public class DetailActivity extends AppCompatActivity { private CollapsingToolbarLayout collapsingToolbarLayout_detail; private RecyclerView recyclerView_detail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); initView(); } private void initView() { collapsingToolbarLayout_detail = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout_detail); collapsingToolbarLayout_detail.setTitle("我的课程"); Toolbar toolbar_detail = (Toolbar) findViewById(R.id.too b2bd lbar_detail); setSupportActionBar(toolbar_detail); toolbar_detail.setNavigationIcon(R.mipmap.ic_menu); recyclerView_detail = (RecyclerView) findViewById(R.id.recyclerView_detail); recyclerView_detail.setLayoutManager(new LinearLayoutManager(this , LinearLayoutManager.VERTICAL , false)); recyclerView_detail.setAdapter(new DetailRecyclerAdapter(this)); } public void clickButton(View view) { switch (view.getId()) { case R.id.fab_detail: Snackbar.make(view, "您点击了Snackbar!", Snackbar.LENGTH_SHORT).show(); break; } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); break; } return super.onOptionsItemSelected(item); } }比较简单,我把里面用到的Adapter也贴下代码:
public class DetailRecyclerAdapter extends RecyclerView.Adapter<DetailRecyclerAdapter.ViewHolder> { private Context mContext; public DetailRecyclerAdapter(Context mContext) { this.mContext = mContext; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_cardview_detail, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { } @Override public int getItemCount() { return 10; } public static class ViewHolder extends RecyclerView.ViewHolder { public final View mView; public ViewHolder(View view) { super(view); mView = view; } } }
到此。完成的例子就讲解到这里了。不好的地方请指出。
共勉!
相关文章推荐
- 跟着Code走,详解Symbian UI程序框架(3)——窗口管理及绘制过程
- 【web】赵雅智_Apache—DBUtils框架详解与案例
- Web自动化框架LazyUI使用手册(8)--excel数据驱动详解(ExcelDataProvider)
- SpringMVC学习(1):SpringMVC框架结构详解和入门案例详解
- 【iOS】UI基础Day3-笔记(UIButton、购物车综合案例)
- 跟着Code走,详解Symbian UI程序框架(1)——UI程序结构
- UI基础控件综合案例之XML布局编写
- Web自动化框架LazyUI使用手册(4)--控件抓取工具Elements Extractor详解(批量抓取)
- Web自动化框架LazyUI使用手册(4)--控件抓取工具Elements Extractor详解(批量抓取)
- Scrapy 爬虫框架入门案例详解
- 高可用群集HA综合案例详解(High Available)
- IOS基础UI之(六)综合小案例-应用管理
- iOS开发-综合UI案例-彩票
- Web自动化框架LazyUI使用手册(8)--excel数据驱动详解(ExcelDataProvider)
- 3-综合案例:月福首页-多媒体-图片热点-框架
- 【servlet】Apache—DBUtils框架详解与案例
- 框架页面JS实现各种级别直接的页面跳转@刷新页面@框架集的综合案例
- SSH:Hibernate框架(Hibernate实现分页和综合查询详解)
- state框架分析,多态,接口,综合案例
- UI基础控件综合案例之案例介绍及案例分析