开发的过程中,会遇到一些不好解决的问题,列表太多会导致滑动事件的冲突,下图中的情况中就是一个很典型的案例。
前言
要保证这个页面能正常显示,需要顶部的内容整体一起滑动上去,这样才能尽可能的扩大商品信息的展示面积,这也是有效信息。底部的双列表类似于饿了么的点餐界面。如果贸然使用ScrollView嵌套ListView的话,会导致ListView反复计算高度,导致内容错乱,进而影响页面效率的问题发生。因此需要寻找其他方式解决这个问题。
CoordinatorLayout
CoordinatorLayout是Google在com.android.support:design中封装的一个控件,其主要实现的效果需要配合ToolBar和AppBarLayout,由于ToolBar的可控性太低,因此在这里不使用ToolBar,使用LinearLayout放在屏幕顶部悬浮即可。
另外,由于底部显示的是结构有些复杂,因此将其他信息中的网页和店铺商品中的双列表分别放在两个Fragment中,用ViewPager统一显示。这样,可以尽可能避免事件冲突,并且还可以保持代码整洁。
编码
activity的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/main_green">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:text="供货商详情"
android:textColor="@color/white"
android:textSize="@dimen/textsize_9" />
</FrameLayout>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@color/white"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.8">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123321\n123321\n123321\n123321\n123321\n123321\n123321\n123321\n123321\n" />
</FrameLayout>
</android.support.design.widget.CollapsingToolbarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/txtOtherInfo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="其他信息" />
<TextView
android:id="@+id/txtShopGoods"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="店铺商品" />
</LinearLayout>
</android.support.design.widget.AppBarLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/grey_line" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
左侧fragment布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
原生的WebView 外面要加一层NestedScrollView,以便让外部的CoordinatorLayout获取滑动事件的监听,另外WebView的android:layout_height要设置为"match_parent",否则网页中的返回顶部和到达底部等功能可能都无法使用了。
右侧fragment布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<View
android:layout_width="100dp"
android:layout_height="match_parent"
android:background="@color/black_light" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Activity代码
public class CollapsingToolbarLayoutActivity extends AppCompatActivity {
private TextView txtOtherInfo, txtShopGoods;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_collapsing);
super.onCreate(savedInstanceState);
txtOtherInfo = (TextView) findViewById(R.id.txtOtherInfo);
txtShopGoods = (TextView) findViewById(R.id.txtShopGoods);
txtOtherInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewPager.setCurrentItem(0);
}
});
txtShopGoods.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewPager.setCurrentItem(0);
}
});
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
}
private static class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return WebViewFragment.getInstance();
default:
return ShopGoodsListFragment.getInstance();
}
}
@Override
public int getCount() {
return 2;
}
}
}
ShopGoodsListFragment代码
public class ShopGoodsListFragment extends MyFragment {
public ShopGoodsListFragment() {
super();
}
public static ShopGoodsListFragment getInstance() {
return new ShopGoodsListFragment();
}
private MyActivity activity;
private RecyclerView recyclerView;
@Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.fragment_shop_goods);
super.onCreate(savedInstanceState);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(new MyRecyclerAdapter(activity));
}
private static class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
private Context context;
public MyRecyclerAdapter(Context context) {
this.context = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycleritem_goods, null, false);
return new ViewHolder(view);
}
@Override
public int getItemCount() {
return 50;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
}
WebViewFragment代码
public class WebViewFragment extends MyFragment {
public WebViewFragment() {
super();
}
public static WebViewFragment getInstance() {
return new WebViewFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.fragment_viewpager);
super.onCreate(savedInstanceState);
HemaWebView webView = (HemaWebView) findViewById(R.id.webView);
webView.loadUrl("https://atwinner.github.io/2016/12/27/top-hover/");
}
}
效果
后记
由于时间仓促,没有将UI的内容100%的还原,但是代码中已经可以看到雏形,可以实现上下左右共存的滑动事件,并且展示复杂列表数据。可见com.android.support:design中给出的控件还是非常强大的,值得研究。