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

本文介绍了如何在Android应用中结合使用ListView和ViewPager,并解决了在实践中遇到的问题,包括ClassCastException异常和滑动冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在做一个小项目用到了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;

@Override
protected 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;
}

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

@Override
public boolean isViewFromObject(View view, Object object) {
    return view==object;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    container.addView(views.get(position));
    return views.get(position);
}

@Override
public 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);
}

@Override
public 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);
}

@Override
public 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一般可以不用去判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值