注意:不是双列表联动,是多列表和头布局联动;
大概就是和饿了么店铺首页类似的布局框架吧,头布局显示时,列表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);
}
}