說說Android CoordinatorLayout

5.0之后的Android系統(tǒng),google推出了自己的移動(dòng)端設(shè)計(jì)規(guī)范,Material Design,同時(shí)sdk包中也加入了support.design包,加入了很多符合md風(fēng)格的組件。這里主要講解一下CoordinatorLayout這個(gè)布局和它的使用。

什么是CoordinatorLayout

? 正如它的名字,這個(gè)布局是用來協(xié)調(diào)2個(gè)控件之間的聯(lián)動(dòng)。我們使用一個(gè)圖片來說明這個(gè)布局的最終效果。

? 可以發(fā)現(xiàn)地下的視圖滑動(dòng)上去之后上面圖片所在的區(qū)域會(huì)被折疊,然后會(huì)有一個(gè)Toolbar懸停在頂部。

? 下面我來實(shí)現(xiàn)以下這個(gè)效果

? 引入design包里面的組件:

compile 'com.android.support:design:25.3.1'

? 新建一個(gè)Activity和布局文件

? 布局文件如下:

<android.support.design.widget.CoordinatorLayout
    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:layout_width="match_parent"
        android:layout_height="200dp">
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="@color/colorPrimary"
            app:layout_scrollFlags="exitUntilCollapsed|scroll|enterAlways"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            >

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/head_img"
                app:layout_collapseMode="parallax"
                android:scaleType="centerCrop"
                />

            <android.support.v7.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

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

?

這個(gè)布局的分析如下:

最外層使用CoordinatorLayout,頂部的折疊部分使用AppBarLayout,在AppBarLayout中我們加入了一個(gè)圖片和Toolbar,圖片和Toolbar需要包含在一個(gè)CollapsingToolbarLayout里面。

下方是一個(gè)用來滑動(dòng)的RecyclerView。

分析一下一些默認(rèn)屬性的作用:

CollapsingToolbarLayout

app:contentScrim 折疊后Toolbar的顏色

app:layout_scrollFlags 滑動(dòng)折疊的五種效果

  • scroll Child View 伴隨著滾動(dòng)事件而滾出或滾進(jìn)屏幕。注意兩點(diǎn):第一點(diǎn),如果使用了其他值,必定要使用這個(gè)值才能起作用;第二點(diǎn):如果在這個(gè)child View前面的任何其他Child View沒有設(shè)置這個(gè)值,那么這個(gè)Child View的設(shè)置將失去作用。
  • enterAlways 滾動(dòng)優(yōu)先級(jí)。比較scroll和scroll|enterAlways, 設(shè)置該屬性后,向下滾動(dòng)的時(shí)候,前者優(yōu)先滾動(dòng)可滾動(dòng)的組件,后者優(yōu)先滾動(dòng)child view。
  • enterAlwaysCollapsed enterAlways的附加值。這里涉及到Child View的高度和最小高度,向下滾動(dòng)時(shí),Child View先向下滾動(dòng)最小高度值,然后Scrolling View開始滾動(dòng),到達(dá)邊界時(shí),Child View再向下滾動(dòng),直至顯示完全。
  • exitUntilCollapsed child view不完全退出屏幕,child view向上滾動(dòng)停住以后再往上滾動(dòng)滾動(dòng)組件。例如折疊后Toolbar不退出屏幕,懸停在上方,然后RecyclerView的視圖向上滑動(dòng)。
  • snap child view要么顯示要么全部退出屏幕。
child view中的

app:layout_collapseMode 折疊的模式,有三種。其中none表示沒有效果。其余2個(gè)分別是

  • pin 固定模式,折疊后固定在頂端。
  • parallax 視差模式,在折疊的時(shí)候會(huì)有個(gè)視差折疊的效果。

####### 可滾動(dòng)的控件

app:layout_behavior 行為,指定在scroll view上面的。這里我們?cè)O(shè)置為

app:layout_behavior="@string/appbar_scrolling_view_behavior"

這個(gè)指的是AppBarLayout中的內(nèi)部類ScrollingViewBehavior,這個(gè)用來指定RecyclerView和AppBarLayout之間的聯(lián)動(dòng)。查看源碼

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    // We depend on any AppBarLayouts
    return dependency instanceof AppBarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
View dependency) {
    offsetChildAsNeeded(parent, child, dependency);
    return false;
}

這段代碼的含義分別是指定滑動(dòng)行為根據(jù)AppBarLayout決定。在onDependentViewChanged方法中我們指定了移動(dòng)的方式。具體代碼在這不贅述。

這個(gè)時(shí)候我們的基本效果就實(shí)現(xiàn)了??梢娺@個(gè)MD控件的強(qiáng)大。當(dāng)然它的具體實(shí)現(xiàn)也是很復(fù)雜的。

常見問題

同時(shí)我們可以發(fā)現(xiàn)Toolbar的行為是根據(jù)CollapsingToolbarLayout來控制的。

設(shè)置Toolbar的title,會(huì)發(fā)現(xiàn)效果沒有達(dá)到預(yù)期。title不會(huì)隨著滑動(dòng)縮放。

那么問題來了,我們?nèi)绾卧O(shè)置Toolbar的標(biāo)題呢?

Toolbar的標(biāo)題我們可以如下設(shè)置:

mCollapsingToolbarLayout.setTitle("標(biāo)題");
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        finish();
    }
});

現(xiàn)在問題又來了,正常我們不設(shè)置的時(shí)候,會(huì)發(fā)現(xiàn)有一個(gè)md規(guī)范控件自帶的效果,標(biāo)題會(huì)在滾動(dòng)過程中上下移動(dòng)并且縮放大小的效果。有時(shí)候我們并不想把標(biāo)題顯示在下發(fā),這個(gè)時(shí)候應(yīng)該怎么辦呢?

可以在style文件中設(shè)置

<style name="collapsing_toolbar_text_size">
    <item name="android:textSize">0sp</item>
</style>

在Activity中設(shè)置

mCollapsingToolbarLayout
  .setExpandedTitleTextAppearance(R.style.collapsing_toolbar_text_size);

這句代碼的含義是設(shè)置滑動(dòng)后的標(biāo)題字體大小,我們?cè)O(shè)置為0sp,就不會(huì)有任何顯示了。

附上最后Activity里面的代碼,也可以參考我在github上的demo代碼

public class CoordinatorTestActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private List<String> data = new ArrayList<>();
    private CollapsingToolbarLayout collapsingToolbarLayout;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_coordinator);
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        initData();
        MyAdapter adapter = new MyAdapter(this,data);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout_1);
        collapsingToolbarLayout.setTitle("標(biāo)題");
        collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.collapsing_toolbar_text_size);
    }

    private void initData() {
        for (int i = 0;i < 20;i++) {
            data.add("str"+i);
        }
    }

    class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {
        private Context mContext;
        private List<String> mData;

        public MyAdapter(Context context, List<String> data) {
            mContext = context;
            mData = data;
        }

        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyHolder(LayoutInflater.from(mContext).inflate(android.R.layout.simple_list_item_1, parent, false));
        }

        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            String text = mData.get(position);
            holder.tv.setText(text);
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        class MyHolder extends RecyclerView.ViewHolder{
            TextView tv;
            public MyHolder(View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(android.R.id.text1);
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容