1. 程式人生 > >Android CoordinatorLayout實現多列表切換並和頭佈局聯動;

Android CoordinatorLayout實現多列表切換並和頭佈局聯動;

注意:不是雙列表聯動,是多列表和頭佈局聯動;

大概就是和餓了麼店鋪首頁類似的佈局框架吧,頭佈局顯示時,列表RecyclerView或ScrollView和頭佈局一起滾動,頭佈局完全隱藏後列表再去滾動,可以多個列表切換;

有空再上圖看效果吧;

1、主要的佈局檔案,註釋寫的很清楚;

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  <android.support.design.widget.AppBarLayout
      android:id="@+id/appbar"
      android:layout_width="match_parent"
      android:layout_height="222dp">

      <!--最為重要的屬性就是 app:layout_scrollFlags :設定上半部分滑動的方式
        1.scroll 表示CollapsingToolbarLayout可以滾動(不設定的話頭部的ImageView將不能摺疊)
        2.enterAlways 表示底部的滾動控制元件只要向下滾動,頭部就顯示出來
        3.enterAlwaysCollapsed 表示當底部滾動控制元件滾動見頂時,頭部顯示出來
        4.exitUntilCollapsed 表示頭部摺疊到最小高度時(Toolbar的高度),就不再摺疊
        5.snap 表示在滑動過程中如果停止滑動,則頭部會就近摺疊(要麼恢復原狀,要麼摺疊成一個Toolbar)-->
      <!--app:contentScrim="@color/colorWhite"  摺疊後的顏色-->

      <android.support.design.widget.CollapsingToolbarLayout
          android:layout_width="match_parent"
          app:contentScrim="@color/colorWhite"
          app:layout_scrollFlags="scroll|exitUntilCollapsed"
          android:layout_height="match_parent">

          <!--app:layout_collapseParallaxMultiplier="0.6" 視差效果-->

          <RelativeLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@drawable/banner"
              app:layout_collapseMode="parallax"
              app:layout_collapseParallaxMultiplier="0.6"
              ></RelativeLayout>

          <!--app:layout_collapseMode="pin" Toolbar的狀態,是否一直顯示-->

          <android.support.v7.widget.Toolbar
              app:layout_collapseMode="pin"
              app:contentInsetStart="0dp"
              android:layout_width="match_parent"
              android:layout_height="48dp">
              <TextView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="#00ffffff"
                  android:text="點選開始搜尋"
                  android:textSize="16dp"
                  android:gravity="center"
                  android:id="@+id/tv"
                  ></TextView>
          </android.support.v7.widget.Toolbar>
      </android.support.design.widget.CollapsingToolbarLayout>
  </android.support.design.widget.AppBarLayout>

    <!--app:layout_behavior="@string/appbar_scrolling_view_behavior" 在整體佈局的下面-->
<RelativeLayout
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_width="match_parent"
    android:background="@color/colorWhite"
    android:layout_height="match_parent">
    <android.support.design.widget.TabLayout
        android:id="@+id/tab"
        android:layout_width="match_parent"
        android:layout_height="46dp">
    </android.support.design.widget.TabLayout>
    <c.c.b.listortoolbar.NotConflictViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/tab"
        ></c.c.b.listortoolbar.NotConflictViewPager>

</RelativeLayout>

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

2、該佈局中的Activity寫法:

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;
    private NotConflictViewPager vp;
    private TextView tv;
    private AppBarLayout appbar;
    private List<String> datas = Arrays.asList("呢呢","嘿嘿","哈哈");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tabLayout = (TabLayout)findViewById(R.id.tab);
        vp = (NotConflictViewPager)findViewById(R.id.vp);
        tv = (TextView) findViewById(R.id.tv);
        appbar = (AppBarLayout) findViewById(R.id.appbar);
        tabLayout.setupWithViewPager(vp);
        vp.setAdapter(new Ap(getSupportFragmentManager()));

        appbar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
                if (i == 0){ //開啟
                    tv.setTextColor(getResources().getColor(R.color.colorWhite));
                }else if (Math.abs(i) >= appbar.getTotalScrollRange()){ //摺疊
                    tv.setTextColor(getResources().getColor(R.color.defaultTextview));
                }else {
//                    中間
                }
            }
        });
    }

    class Ap extends FragmentStatePagerAdapter{

        public Ap(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int i) {
            return new cFragment(datas.get(i));
        }

        @Override
        public int getCount() {
            return datas.size();
        }

        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return datas.get(position);
        }
    }
}

3、填充ViewPager的Fragment;

R.layout.fragment_c (子條目的layout就不寫了,隨便一個有內容的佈局就行)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".cFragment">

<android.support.v7.widget.RecyclerView
    android:id="@+id/rv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>

</FrameLayout>
public class cFragment extends Fragment {


    public cFragment() {

    }
    private String title;
    @SuppressLint("ValidFragment")
    public cFragment(String title) {
      this.title = title;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_c, container, false);
        initView(v);
        return v;
    }

    private void initView(View view) {
        RecyclerView rv = view.findViewById(R.id.rv);
        if("嘿嘿".equals(title)){
            rv.setLayoutManager(new GridLayoutManager(getActivity(),2));
            rv.addItemDecoration(new GridDividerItemDecoration(getActivity())); //分割線,報錯刪除就行了;
        }else {
            rv.addItemDecoration(new DividerItemDecoration(getActivity(),1));
            rv.setLayoutManager(new LinearLayoutManager(getActivity()));
        }
        rv.setAdapter(new Ap());
    }

     class Ap extends RecyclerView.Adapter<Ap.Vh>{
         @Override
         public Vh onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
             return new Vh(LayoutInflater.from(getContext()).inflate(R.layout.item_rv, viewGroup, false));
         }

         @Override
         public void onBindViewHolder(@NonNull Vh vh, int i) {
         vh.tv.setText(title);
         }

         @Override
         public int getItemCount() {
             return 20;
         }

         class Vh extends RecyclerView.ViewHolder{
             TextView tv;
            public Vh(@NonNull View itemView) {
                super(itemView);
                tv = itemView.findViewById(R.id.tv);

            }
        }
     }
}

   列表和ViewPager衝突解決;

public class NotConflictViewPager extends ViewPager {
    public NotConflictViewPager(Context context) {
        super(context);
    }

    public NotConflictViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
private float mX;
    private float mY;
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
               mX = ev.getX();
                mY = ev.getY();
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(mX-ev.getX())> Math.abs(mY-ev.getY())){
                    getParent().requestDisallowInterceptTouchEvent(true);
                }else{
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                getParent().requestDisallowInterceptTouchEvent(false);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
}