ListView使用ViewPager作头布局遇到的问题及处理

来源:互联网 发布:手机弹电子琴软件 编辑:程序博客网 时间:2024/05/16 11:19

今天在做一个小项目用到了ListView去加载头布局,头布局用的是ViewPager,发现了一些问题。

一、加载头布局时报ClassCastException

MainActivity文件

package com.example.shawn.listviewandviewpagerdemo;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {private List<String> listData;//ListView中的数据集合private ListView listView;private List<View> views;//ViewPager中的View集合private ViewPager viewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    listView = (ListView) findViewById(R.id.lv_test);    //给ListView使用的数据    listData=new ArrayList<>();    for (int i = 0; i < 30; i++) {        listData.add("测试数据"+i);    }    //加载ViewPager的布局    View view = LayoutInflater.from(this).inflate(R.layout.layout_view_pager, null);    initViews();    //找到ViewPager    viewPager = (ViewPager) view.findViewById(R.id.vp_test);    //给ViewPager设置自定义的适配器    viewPager.setAdapter(new MyPagerAdaper(views));    //**给ListView添加头布局,注意这行代码必须在setAdapter()之前调用。**    listView.addHeaderView(viewPager);    listView.setAdapter(new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,listData));}/** * 初始化ViewPager中加载的内容 */private void initViews() {    views = new ArrayList<>();    View view1 = getLayoutInflater().inflate(R.layout.page1_layout, null);    View view2 = getLayoutInflater().inflate(R.layout.page2_layout, null);    View view3 = getLayoutInflater().inflate(R.layout.page3_layout, null);    View view4 = getLayoutInflater().inflate(R.layout.page4_layout, null);    views.add(view1);    views.add(view2);    views.add(view3);    views.add(view4);}}

ViewPager的适配器
package com.example.shawn.listviewandviewpagerdemo;

import android.support.v4.view.PagerAdapter;import android.view.View;import android.view.ViewGroup;import java.util.List;public class MyPagerAdaper extends PagerAdapter {private List<View> views;public MyPagerAdaper(List<View> views) {    this.views = views;}@Overridepublic int getCount() {    return views.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {    return view==object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {    container.addView(views.get(position));    return views.get(position);}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {    container.removeView((View) object);}}

当我在initViews() 方法中使用上面这种方式去添加ViewPager中的内容时,就会报java.lang.ClassCastException: android.widget.LinearLayoutLayoutParamscannotbecasttoandroid.widget.AbsListViewLayoutParams,查了资料后才知道原因。要将一个View添加到另一个布局中,必须设定该View的布局参数为其父类所使用的布局参数类型,即要在代码中动态改变某组件的高度,其布局参数类型应该是其父类所使用的布局参数类型。
修改onCreate()方法中代码如下:

 **viewPager.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 500));**

这样修改后就不会报错了。但是当我把ViewPager要添加的View改成ImageView时,居然不会报ClassCastException,这时我就懵圈了,原因是啥正在研究。

 private void initViews() {    views = new ArrayList<>();//注意此时的List泛型为ImageView    ImageView imageView1 = new ImageView(this);    imageView1.setScaleType(ImageView.ScaleType.CENTER_CROP);    imageView1.setImageResource(R.mipmap.aaa);    ImageView imageView2 = new ImageView(this);    imageView2.setScaleType(ImageView.ScaleType.CENTER_CROP);    imageView2.setImageResource(R.mipmap.bbb);    ImageView imageView3 = new ImageView(this);    imageView3.setImageResource(R.mipmap.aaa);    imageView3.setScaleType(ImageView.ScaleType.CENTER_CROP);    ImageView imageView4 = new ImageView(this);    imageView4.setImageResource(R.mipmap.bbb);    imageView4.setScaleType(ImageView.ScaleType.CENTER_CROP);    mlistpic.add(imageView1);    mlistpic.add(imageView2);    mlistpic.add(imageView3);    mlistpic.add(imageView4);    }

layout_page1
四个layout_page都一样,只是背景色不同。

二、滑动冲突

ListView和ViewPager的滑动方向不一样,在滑动时可能造成冲突。处理方式:

方法一:自定义MyListView继承ListView,重写onInterceptTouchEvent方法。在activity_main.xml文件中引入自定义的MyListView,MainActivity中listview的类型改为MyListView。这样在viewPage里面去上下滑动,listview不会响应。

package com.example.shawn.listviewandviewpagerdemo;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ListView;public class MyListView extends ListView {    public MyListView(Context context) {        super(context);    }public MyListView(Context context, AttributeSet attrs) {    super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {    return false;}}

因为ViewPager是加载到父容器ListView中的,返回false表示父容器把点击事件丢给子控件去处理。

方法二:自定义MyViewPager继承ViewPager,重写onInterceptTouchEvent方法。之后的操作与上面的方法类似。
package com.example.shawn.listviewandviewpagerdemo;

import android.content.Context;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.MotionEvent;public class MyViewPager extends ViewPager {    public MyViewPager(Context context) {        super(context);    }public MyViewPager(Context context, AttributeSet attrs) {    super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {    switch (ev.getAction()) {        case MotionEvent.ACTION_DOWN:            getParent().requestDisallowInterceptTouchEvent(true);            break;        case MotionEvent.ACTION_MOVE:            getParent().requestDisallowInterceptTouchEvent(true);            break;    }  return super.onInterceptTouchEvent(ev);}}

在ViewPager内部去拦截点击事件,自己处理。MotionEvent.ACTION_UP一般可以不用去判断。

1 0
原创粉丝点击