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 libraryPagerTitleStrip 的人一定熟悉这个,并且新的TabLayout 的实现使用完全相同的机制得到跳转的每个 tab item的文本。

下面我们需要看一下主布局。之前我们定义了一个FrameLayout 包含Toolbar,现在我们需要添加TabLayoutViewPager

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 ——这个控件将给我们做好所有工作!我们已经选择了一个操作模式——fixedtabs 是动态的大小,因此TabLayout 是完全适配可用的空间;还有scrollabletabs 是一个固定的大小,如果它们超过可用空间用户可以滚动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关联到初始了tabsViewPager 上,并且关联了所有的 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>

我们声明了同样的颜色值作为colorPrimarycolorPrimary 将会被用作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/

0 0
原创粉丝点击