Android之ScrollView嵌套两个ListView及冲突解决

一:先来效果图吧、

 

二:实现步骤:

1.主Activity的布局、

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="com.example.wergr.myapplication.MainActivity"
    tools:ignore="Orientation">

    <com.example.wergr.myapplication.MyScrollView
        android:id="@+id/scroller"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="none">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <com.example.wergr.myapplication.MyListView
                android:id="@+id/list_top"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

            </com.example.wergr.myapplication.MyListView>

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:scaleType="fitXY"
                android:src="@mipmap/meinv" />

            <com.example.wergr.myapplication.MyListView
                android:id="@+id/list_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"></com.example.wergr.myapplication.MyListView>
        </LinearLayout>
    </com.example.wergr.myapplication.MyScrollView>
</RelativeLayout>

2.自定义的Scrollview、

package com.example.wergr.myapplication;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * Created by wergr on 2018/5/4.
 * 自定义scrollview
 */

public class MyScrollView extends ScrollView {
    public MyScrollView(Context context) {
        super(context);

    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private ScrollViewListener scrollViewListener = null;

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    private boolean allowChildViewScroll = true;

    public void setAllowChildViewScroll(boolean allowChildViewScroll) {
        this.allowChildViewScroll = allowChildViewScroll;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if(!allowChildViewScroll){
            return true;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
        super.onScrollChanged(x, y, oldx, oldy);

        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
        }
    }
    public interface ScrollViewListener {
        void onScrollChanged(ScrollView scrollView,int x, int y, int oldx, int oldy);
    }
}

3.自定义的ListView

package com.example.wergr.myapplication;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;
import android.widget.ScrollView;

/**
 * Created by wergr on 2018/5/4.
 * 自定义的LisvtView
 */

public class MyListView extends ListView {
    private ScrollView scrollView;
    private boolean notAllowParentScroll = true;

    public void setNotAllowParentScroll(boolean notAllowParentScroll) {
        this.notAllowParentScroll = notAllowParentScroll;
    }

    public void setScrollView(ScrollView scrollView) {
        this.scrollView = scrollView;
    }

    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if(notAllowParentScroll){
            switch(event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    scrollView.requestDisallowInterceptTouchEvent(false);//如果为true的话滑动不流畅,等滑两次才开始改变位置
                    break;
                case MotionEvent.ACTION_UP:
                    scrollView.requestDisallowInterceptTouchEvent(false);//同样为true滑动不流畅,得滑动两次才改变位置
                    break;
            }
        }
        return super.dispatchTouchEvent(event);
    }

}

4.adapter(这里为了区分两个listview所以写了两个listview,其实一个就可以)、

(1):第一个adapter、

package com.example.wergr.myapplication;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * Created by wergr on 2018/5/4.
 */

public class MyAdapter extends BaseAdapter {
    private List<String> list;
    private LayoutInflater inflater;
    private Context ctx;

    public MyAdapter(List<String> list, Context ctx) {
        this.list = list;
        this.ctx = ctx;
        inflater =LayoutInflater.from(ctx);
    }

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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView==null){
            convertView = inflater.inflate(R.layout.list_item_top,parent,false);
            holder = new ViewHolder();
            holder.tv = (TextView) convertView.findViewById(R.id.text_top);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        holder.tv.setText(list.get(position));
        return convertView;
    }
    class ViewHolder{
        public TextView tv;
    }
}

(2):第一个适adapter的item布局、

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

    <TextView
        android:id="@+id/text_top"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="这是第一个listview"
        android:textColor="#232323"
        android:textSize="18dp" />
</RelativeLayout>

(3):第二个adapter、

package com.example.wergr.myapplication;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * Created by wergr on 2018/5/4.
 */

public class MyAdapterbutton extends BaseAdapter {
    private List<String> list;
    private LayoutInflater inflater;
    private Context ctx;

    public MyAdapterbutton(List<String> list, Context ctx) {
        this.list = list;
        this.ctx = ctx;
        inflater =LayoutInflater.from(ctx);
    }

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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView==null){
            convertView = inflater.inflate(R.layout.list_item_button,parent,false);
            holder = new ViewHolder();
            holder.tv = (TextView) convertView.findViewById(R.id.text_button);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        holder.tv.setText(list.get(position));
        return convertView;
    }
    class ViewHolder{
        public TextView tv;
    }
}

(4):第二个adapter的布局、

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

    <TextView
        android:id="@+id/text_button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="这是第二个listview"
        android:gravity="center"
        android:textColor="#232323"
        android:textSize="18dp" />
</RelativeLayout>

5.主Activity的核心代码、

package com.example.wergr.myapplication;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ScrollView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {

    private MyListView list_top, list_button;
    private MyAdapter adapter;
    private MyAdapterbutton adapterbutton;
    private MyScrollView scroller;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initlayout();
    }

    private void initlayout() {
        scroller = (MyScrollView) findViewById(R.id.scroller);
        list_top = (MyListView) findViewById(R.id.list_top);
        list_button = (MyListView) findViewById(R.id.list_button);
        scroller.setOnTouchListener(this);
        adapter = getAdapter("第一个listview");
        list_top.setAdapter(adapter);
        setListViewHeightBasedOnChildren(list_top);
        list_top.setScrollView(scroller);

        adapterbutton = getAdapterbutton("第二个listview");
        list_button.setAdapter(adapterbutton);
        setListViewHeightBasedOnChildren(list_button);
        list_button.setScrollView(scroller);
        list_top.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                        // 判断滚动到底部,scrollview滚动,listview1滚动屏蔽
                        if (view.getLastVisiblePosition() == (view.getCount() - 1)) {
                            list_top.setNotAllowParentScroll(false);
                            scroller.setAllowChildViewScroll(false);
                        }
                        break;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });


        list_button.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                        // 判断滚动到顶部,listview2开始滚动,scrollview滚动屏蔽
                        if (view.getFirstVisiblePosition() == 0) {
                            scroller.setAllowChildViewScroll(false);
                            list_button.setNotAllowParentScroll(false);
                            scroller.requestDisallowInterceptTouchEvent(true);
                        }
                        break;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

        scroller.setScrollViewListener(new MyScrollView.ScrollViewListener() {
            @Override
            public void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) {
                int[] listview2location = new int[2];
                list_button.getLocationOnScreen(listview2location);
                int[] location1 = new int[2];
                scroller.getLocationOnScreen(location1);

                //在scrollview滚动过程中,如果listview2正好填满整个屏幕,此时需要屏蔽scrollview的滚动
                if (listview2location[1] == location1[1]) {

                    list_button.setNotAllowParentScroll(true);
                    scroller.setAllowChildViewScroll(true);
                    return;

                }
                int[] listview1location = new int[2];
                list_top.getLocationOnScreen(listview1location);
                //在scrollview滚动过程中,如果listview1正好填满整个屏幕,此时需要屏蔽scrollview的滚动
                if (listview1location[1] == location1[1]) {
                    scroller.setAllowChildViewScroll(true);
                    list_top.setNotAllowParentScroll(true);
                    return;
                }
                //在scrollview滚动过程中,屏蔽listview的滚动
                scroller.setAllowChildViewScroll(false);

            }
        });

    }

    /**
     * 动态设置ListView的高度
     *
     * @param listView
     */
    public static void setListViewHeightBasedOnChildren(ListView listView) {
        if (listView == null) return;
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            // pre-condition
            return;
        }
        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //屏蔽listview的滚动造成listview
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                scroller.setAllowChildViewScroll(false);
                break;
            case MotionEvent.ACTION_UP:
                scroller.setAllowChildViewScroll(true);
                break;
        }
        return false;
    }

    private MyAdapter getAdapter(String str) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(str);
        }
        return new MyAdapter(list, this);
    }

    private MyAdapterbutton getAdapterbutton(String str) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add(str);
        }
        return new MyAdapterbutton(list, this);
    }
}

注意:

     因为scrollview嵌套listview会导致冲突,解决办法是这个方法:

setListViewHeightBasedOnChildren();

 

----------------------最后把demo地址奉上:点击打开链接

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶已初秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值