仿NestedScrollingParent嵌套滑动

来源:互联网 发布:3g软件开发培训学校 编辑:程序博客网 时间:2024/05/14 15:27

用NestedScrollingParent很方便实现嵌套滑动,今天我们就用原始的套路自定义View来实现嵌套滑动功能,下次直接用NestedScrollingParent来实现。
先看下实现的效果:
效果图

先简单分析下思路:向上滑动时,当滑动高度没有超过头部的时候,滑动事件是被父类消费的,直到滑动的高度头超过头部的时候,滑动事件才传递给它的子view(这里是listview),此时选项按钮布局被固定在顶端。这时候listview可以自由滑动,当listview滑动到顶端不可再向下滑动时,滑动事件重新交给父类,头部View可滑动到之前的状态。

布局相关代码

<?xml version="1.0" encoding="utf-8"?><com.yq.nesting.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:background="#ff00ff"    >    <RelativeLayout        android:id="@+id/rl_headview"        android:background="#033399"        android:layout_width="match_parent"        android:layout_height="200dp">        <TextView            android:layout_centerInParent="true"            android:textSize="20sp"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="NESTING"            android:textColor="#000000"            android:textStyle="bold"            />    </RelativeLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="50dp">        <TextView            android:gravity="center"            android:layout_weight="1"            android:layout_width="0dp"            android:layout_height="match_parent"            android:text="NESTING_1"            android:background="#00ffff"            />        <TextView            android:gravity="center"            android:layout_weight="1"            android:layout_width="0dp"            android:layout_height="match_parent"            android:text="NESTING_2"            android:background="#00ffff"            />        <TextView            android:gravity="center"            android:layout_weight="1"            android:layout_width="0dp"            android:layout_height="match_parent"            android:text="NESTING_3"            android:background="#00ffff"            />    </LinearLayout>    <ListView        android:background="#ffff00"        android:layout_width="match_parent"        android:id="@+id/listview"        android:layout_height="match_parent">    </ListView></com.yq.nesting.MyLinearLayout>

自定view代码,里边有详细的注释

public class MyLinearLayout extends LinearLayout{    private Context mContext;    public MyLinearLayout(Context context) {        super(context);        mContext = context;        init();    }    public MyLinearLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        init();    }    public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        init();    }    private RelativeLayout rl_headview;    private ListView listview;    private int screenHeight,screenWidth;    public void init(){         //获取屏幕信息        WindowManager wm = (WindowManager) getContext()                .getSystemService(Context.WINDOW_SERVICE);        screenWidth = wm.getDefaultDisplay().getWidth();        screenHeight = wm.getDefaultDisplay().getHeight();        Log.e("screenHeight","screenHeight:"+screenHeight);    }    private int headViewHeight,listviewHeight,marginTop;    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        for (int i=0;i<this.getChildCount();i++){            measureChild(this.getChildAt(i),widthMeasureSpec,heightMeasureSpec);        }        rl_headview = (RelativeLayout)this.getChildAt(0);        headViewHeight = rl_headview.getMeasuredHeight();        Log.e("headViewHeight","headViewHeight:"+headViewHeight);        listview =(ListView)this.getChildAt(2);        listviewHeight = listview.getMeasuredHeight();        Log.e("listviewHeight","listviewHeight:"+listviewHeight);        //设置listview的高度,为了防止当头部View不见时,listview的高度没有填充整个页面        ViewGroup.LayoutParams myp = listview.getLayoutParams();        myp.height=screenHeight-this.getChildAt(1).getMeasuredHeight();        listview.setLayoutParams(myp);    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        return super.onTouchEvent(ev);    }    private float delaY;    private float scrollY;    private float scrollInstanceY;    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                scrollY = ev.getRawY();                break;            case MotionEvent.ACTION_MOVE:                delaY = scrollY -ev.getRawY();                scrollY = ev.getRawY();                if(delaY>0){                    //向上滑时操作                    scrollInstanceY = scrollInstanceY+delaY;                    Log.e("delaY","delaY:"+delaY+"----:"+scrollInstanceY);                    if(scrollInstanceY>headViewHeight){//当headview不可见是让选项布局停留在顶端                        scrollInstanceY = headViewHeight;                        scrollTo(0,(int)scrollInstanceY);                        return super.dispatchTouchEvent(ev);                    }else if(scrollInstanceY<=headViewHeight){//滑动的距离没有超过headview的高度时                        scrollTo(0,(int)scrollInstanceY);                        return true;                    }                }else{                    //向下滑时操作                    Log.e("scrollInstanceY","scrollInstanceY:"+scrollInstanceY);                    Log.e("delaY----","delaY----:"+delaY);                    if(!isListViewTop()){                    }else{                        // 可以向下滑                        scrollInstanceY = scrollInstanceY+delaY;                        if(scrollInstanceY<=0){//限制不能一直往下滑                            scrollInstanceY = 0;                        }                        scrollTo(0,(int)scrollInstanceY);                        return true;                    }                    return super.dispatchTouchEvent(ev);                }            case MotionEvent.ACTION_UP:                break;        }        return super.dispatchTouchEvent(ev);    }    //判断listview是否滑动到了顶部    public boolean isListViewTop(){        int fistVisiblePosition = listview.getFirstVisiblePosition();        if(fistVisiblePosition == 0&&getListViewScrollY()==0){            return true;        }        return false;    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return super.onInterceptTouchEvent(ev);    }    //获得listview的滚动高度,只限每个item高度都一样    public int getListViewScrollY() {        View c = listview.getChildAt(0);        if (c == null) {            return 0;        }        int firstVisiblePosition = listview.getFirstVisiblePosition();        int top = c.getTop();        Log.e("top","top:"+top);        return -top + firstVisiblePosition * c.getHeight() ;    }}

MainActivity代码

public class MainActivity extends Activity {    private ListView listview;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listview = (ListView)findViewById(R.id.listview);        listview.setAdapter(new MyAdapter());    }    public class MyAdapter extends BaseAdapter{        @Override        public int getCount() {            return 60;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            TextView tv = new TextView(MainActivity.this);            tv.setText("我是第"+position+"条");            tv.setPadding(0,10,0,10);            tv.setTextSize(25);            return tv;        }    }}
0 0