Android Material Design Library系列教程(二)
来源:互联网 发布:淘宝里怎么店铺收藏 编辑:程序博客网 时间:2024/06/07 16:37
尊重劳动成果,转载请注明出处:http://blog.csdn.net/growth58/article/details/48382913
关注新浪微博:@于卫国
邮箱:yuweiguocn@gmail.com
Google在2015 I/O大会上公布了Material Design Support Library,使用它可以创建materail应用在API 19以下突然变得很容易。在这个系列中,我们将使用RSS阅读器应用,我们用于Material系列的基础应用,重写让它完全使用新的Design Support Library。
在前面我们做了基本的navigation drawer,在这篇文章中我们将学习怎样实现一个tab bar。
ViewPager已经存在有一段时间并且是一个很好使用和理解的组件,因此我很乐意在这里对它做一个完整的说明。让我们看看在ViewPager中使用Fragment的实现。RSS订阅中每个item的内容是基本的HTML,因此我们将使用WebView来控制渲染(请不要讨厌我对这个渲染是多么可怕——它是基本的HTML没有任何CSS呈现进行渲染的。本文的重点是关于内容周围发生的东西而不是怎样渲染内容本身)。
让我们看看fragment布局:
res/layout/fragment_item.xml
<WebView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" />
那是相当直接的,也让我们再看一下Fragment 的实现:
ItemFragment.java
public class ItemFragment extends Fragment { private static final String KEY_ITEM = "ARG_ITEM"; public static final String NEWLINE = "\\n"; public static final String BR = "<br />"; public static final String HTML_MIME_TYPE = "text/html"; public static Fragment newInstance(Context context, Item item) { Bundle args = new Bundle(); args.putSerializable(KEY_ITEM, item); return Fragment.instantiate(context, ItemFragment.class.getName(), args); } @Override @SuppressLint("SetJavaScriptEnabled") public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Item item = (Item) getArguments().getSerializable(KEY_ITEM); View view = inflater.inflate(R.layout.fragment_item, container, false); if (item != null) { WebView webView = (WebView) view.findViewById(R.id.web_view); String html = item.getContent(); html = html.replaceAll(NEWLINE, BR); webView.getSettings().setUseWideViewPort(true); webView.getSettings().setLoadWithOverviewMode(true); webView.getSettings().setJavaScriptEnabled(true); webView.loadData(html, HTML_MIME_TYPE, null); } return view; }}
还是很直接——进入一个Item,内容被渲染在WebView中。唯一值得注意的是我们替换了换行为了提高渲染。我们也调用了setUseViewPortMode(true) 和setLoadWithOverviewMote(true)方法在启动时缩小(所以整个内容的宽可以被显示)。这是为移除所有的水平滚动,它将会影响ViewPager容器中的操作。(再次说明,不要讨厌我——ViewPager 是本文的焦点因此我们将修复WebView 渲染以免干扰)。
现在我们已经定义了ViewPager 中的pages ,让我们看看关联到ViewPager上的Adapter:
ArticleViewPagerAdapter.java
public final class ArticleViewPagerAdapter extends FragmentPagerAdapter { private final Article article; private final Context context; private final Resources resources; public static ArticleViewPagerAdapter newInstance(FragmentManager fragmentManager, Context context, Article article) { Resources resources = context.getResources(); return new ArticleViewPagerAdapter(fragmentManager, context, resources, article); } private ArticleViewPagerAdapter(FragmentManager fragmentManager, Context context, Resources resources, Article article) { super(fragmentManager); this.context = context; this.resources = resources; this.article = article; } @Override public Fragment getItem(int position) { Item item = article.getPartAtPosition(position); return ItemFragment.newInstance(context, item); } @Override public void destroyItem(ViewGroup container, int position, Object object) { FragmentManager manager = ((Fragment) object).getFragmentManager(); FragmentTransaction trans = manager.beginTransaction(); trans.remove((Fragment) object); trans.commit(); super.destroyItem(container, position, object); } @Override public int getCount() { return article.getPartsCount(); } @Override public CharSequence getPageTitle(int position) { return resources.getString(R.string.part_title, article.getPartNumber(position)); }}
这是一个很普通的Adapter 实现。唯一值得注意的是包含了一个getPageTitle()方法的实现(我们用 “Part X”形式生成了一个标题)。使用过v4 support library中PagerTitleStrip 的人一定熟悉这个,并且新的TabLayout 的实现使用完全相同的机制得到跳转的每个 tab item的文本。
下面我们需要看一下主布局。之前我们定义了一个FrameLayout 包含Toolbar,现在我们需要添加TabLayout 和 ViewPager:
res/layout/include_main.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/main_layout" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> <android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:clipToPadding="false" android:paddingLeft="@dimen/home_offset" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:tabMode="scrollable" /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
在这我们已经添加了TabLayout ——这个控件将给我们做好所有工作!我们已经选择了一个操作模式——fixed:tabs 是动态的大小,因此TabLayout 是完全适配可用的空间;还有scrollable:tabs 是一个固定的大小,如果它们超过可用空间用户可以滚动tabs获取所有。
一般情况下tabs的个数相对少的时候使用fixed模式可以很好的展现,但当tabs的个数太多时使用scrollable模式效果最佳。在这个应用的每篇文章中items 的数量是不定的并且有时可能很大(在示例视频中Dirty Phrasebook包含6部分),因此我选择了scrollable模式。
因为我选择了scrollable 模式,我实际上想让第一个tab文本左边和Toolbar的标题文本对齐,因此我设置了android:paddingLeft来实现这个。当我们滚动tabs时通过设置android:clipToPadding=”false” tabs 将会滚动到左边空白区域。
在布局文件中就还只剩下我们的ViewPager组件。
剩下的工作就是在Activity文件进行关联:
MainActivity.java
public class MainActivity extends AppCompatActivity implements ArticlesConsumer { private static final String DATA_FRAGMENT_TAG = DataFragment.class.getCanonicalName(); private static final int MENU_GROUP = 0; private DrawerLayout drawerLayout; private NavigationView navigationView; private ViewPager viewPager; private TabLayout tabLayout; private Articles articles; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); navigationView = (NavigationView) findViewById(R.id.nav_view); viewPager = (ViewPager) findViewById(R.id.viewpager); tabLayout = (TabLayout) findViewById(R.id.tab_layout); setupToolbar(); setupNavigationView(); setupDataFragment(); } . . . private void setCurrentArticle(Article article) { setTitle(article.getTitle()); ArticleViewPagerAdapter adapter = ArticleViewPagerAdapter.newInstance(getSupportFragmentManager(), this, article); viewPager.setAdapter(adapter); if (article.getPartsCount() <= 1) { tabLayout.setVisibility(View.GONE); } else { tabLayout.setVisibility(View.VISIBLE); } tabLayout.setupWithViewPager(viewPager); }}
当选择一个新的Article时所有的工作在setCurrentArticle()方法中完成。首先我们设置一个新ArticleViewPagerAdapter 实例基于新的Article,然后我们应用到了ViewPager。紧接着做了一个快速检查如果article中只有一部分隐藏TabLayout ,否则显示TabLayout 。最后我们将TabLayout关联到初始了tabs的ViewPager 上,并且关联了所有的 paging / tab的选择逻辑。这是一次强有力的方法调用!
运行我们可以看到我们已经完全实现了tab bar:
然而这还有一个很微妙的问题。tab bar支持在已选择的tab的最下面有一个指示条。这个消失的原因是我们在主题中定义了colorAccent值:
res/values/styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Base.AppTheme" /> <style name="Base.AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/sa_green</item> <item name="colorPrimaryDark">@color/sa_green_dark</item> <item name="colorAccent">@color/sa_green</item> <item name="colorControlHighlight">@color/sa_green_transparent</item> </style></resources>
我们声明了同样的颜色值作为colorPrimary。colorPrimary 将会被用作AppBarLayout背景颜色,colorAccent 将被用作指示条的颜色。因为它们的颜色是相同的,所以我们的指示条没有显示。现在我们将colorAccent 设置为白色(但这将会导致一个问题和FloatingActionButton一块使用时,我们遇到时再做处理 ):
res/values/styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Base.AppTheme" /> <style name="Base.AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/sa_green</item> <item name="colorPrimaryDark">@color/sa_green_dark</item> <item name="colorAccent">@android:color/white</item> <item name="colorControlHighlight">@color/sa_green_transparent</item> </style></resources>
现在我们可以看到指示条已经起作用:
看起来相当不错,但对于如果我们可以做一个非常material化的东西它还不够好,比如向下滚动Toolbar 消失,还有提供一个快速返回作为用户向上滚动返回。在下一篇文章我们将实现这些。
源代码可以从这下载。
请我喝杯咖啡,请使用支付宝扫描下方二维码:
原文地址:https://blog.stylingandroid.com/design-library-part-2/
- Android Material Design Library系列教程(二)
- Android Material Design Library系列教程(一)
- Android Material Design Library系列教程(三)
- Android Material Design Library系列教程(四)
- Android Material Design Library系列教程(五)
- Android Material Design support library
- Material Design:Android Design Support Library
- Material Design Library系列之TextInputLayout
- Material Design Library系列之TabLayout
- Material Design Library系列之NavigationView
- Material Design Library系列之CoordinatorLayout
- android material design之Snackbar(二)
- Android Material Design 学习(二)
- Android 5.0 Material Design系列
- android material design 布局教程
- 深度剖析之 Material Design Android Library
- Android:Material Design(二) Material主题
- 使用Android Design Support Library创建一个Android Material Design
- 杂感
- Reactivecoco 文档翻译(1) 基本操作方法
- swwuwnzzvfitp
- EventBus, otto, LocalBroadcast的选择
- 一个有趣的SQL:根据登录日志,求系统无人登录时间
- Android Material Design Library系列教程(二)
- 旧手机利用 第二弹 ——网络摄像头
- 海明码学习小结
- EditText的drawableleft跟随其Gravity
- 【Android实战项目】Odoo 邮箱客户端的经历
- Android插件化学习
- [leetcode] 187 Repeated DNA Sequences
- 编译原理第一次作业
- Ubuntu实现网络链接设置