仿扇贝单词----自定义可拖拽控件

来源:互联网 发布:淘宝创意礼物知乎 编辑:程序博客网 时间:2024/04/30 06:11

仿扇贝单词—-自定义可拖拽控件

最近在做项目时需要实现一个可以拖动的控件,用于在有限的屏幕内显示更多的内容.先给大家看一下效果图.
这里写图片描述

这个效果的主要特点有以下几点:
1.只有按住拖拽的按钮时才可以拖动,下面的内容布局无法拖动.
2.内容布局的触摸事件处理.判断当前的点击位置是否在拖拽控件内,如果在则消耗掉该事件,反之则传递到内部.
1.首先是布局

<?xml version="1.0" encoding="utf-8"?><FrameLayout 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"    >    <RelativeLayout        android:id="@+id/rl_content"        android:layout_width="match_parent"        android:layout_height="match_parent">        <Button            android:id="@+id/btn"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:text="button"/>    </RelativeLayout>    <com.iyuba.myapplication.view.DragView        android:id="@+id/dgview"        android:layout_width="match_parent"        android:layout_height="match_parent">        <ImageView            android:id="@+id/iv_drag"            android:layout_width="wrap_content"            android:layout_height="40dp"            android:src="@mipmap/ic_drag_handle_black_24dp"            />        <RelativeLayout            android:id="@+id/rl"            android:background="#009688"            android:layout_width="match_parent"            android:layout_height="match_parent">        </RelativeLayout>    </com.iyuba.myapplication.view.DragView></FrameLayout>

这里根布局使用Fragment,自定义的DragView 在最上层.DragView 中的布局有两个子View,一个是拖拽按钮,一个是用于放置内容的布局.布局还是比较清晰的.
2.自定义的DragView

package com.iyuba.myapplication.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewGroup;import android.widget.Scroller;/** * Author:Howard on 2016/6/3 10:00 * Email:Howard9891@163.com */public class DragView extends ViewGroup {    //子view初始高度    private int mTop = 400;    //拖拽按钮     private  View iv_drag;    //容器    private  View  contentView;    private int lastY;    private int lastX;    private Context mContext;    private int dy;    //存放view 在屏幕中的坐标    private int[] viewLocation;    //存放父view 在屏幕中的坐标    private int[] parentLocation;    //记录按下时的X坐标    private int mInitialMotionX;    //记录按下时的Y坐标    private int mInitialMotionY;    //Scrllor 帮助类    private Scroller mScroller;    //设置滑动偏差值    private int touchSlop =20;    //父view 高度    private int mHeight;    //拖拽按钮高度    private int ivHeight;    //获取滑动速度的帮助类    private VelocityTracker mVelocityTracker;    public DragView(Context context) {        this(context,null);    }    public DragView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.mContext = context;        init();    }    private void init() {        mScroller = new Scroller(mContext);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);        int measureHeight = MeasureSpec.getSize(heightMeasureSpec);        //测量子类         for(int i=0;i<getChildCount();i++){            View  child =getChildAt(i);            child.measure(measureWidth,measureHeight);        }        setMeasuredDimension(measureWidth,measureHeight);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {    //设置每个子View 在父view中的位置        iv_drag = getChildAt(0);        contentView =  getChildAt(1);        iv_drag.layout(0,mTop,r,mTop+ iv_drag.getMeasuredHeight());        contentView.layout(0,mTop+iv_drag.getMeasuredHeight(),r,mTop+this.getHeight());        Log.e("DragView","height>>>"+this.getMeasuredHeight());        mHeight =this.getMeasuredHeight();        ivHeight = iv_drag.getMeasuredHeight();    }    @Override    public boolean onTouchEvent(MotionEvent event) {        int action = event.getAction();        obtainVelocity(event);        switch (action){            case MotionEvent.ACTION_DOWN:                obtainVelocity(event);                Log.e("DragView","down");                mInitialMotionX= lastX = (int) event.getX();                mInitialMotionY= lastY = (int) event.getY();                Log.e("DragView","lastY:>>>"+lastY);                break;            case MotionEvent.ACTION_MOVE:                Log.e("DragView","move");                getVelocity();                dy = (int)event.getY()-lastY;                //判断用户是否按住拖拽按钮,并获得当前滑动速度   // 平稳滑动                if(isViewHit(iv_drag,lastX,lastY)&&Math.abs(getVelocity())<2000){                    //滑动到最顶端,禁止在往上滑动                    if(viewLocation[1]<parentLocation[1]&&dy<0){                        break;                    }                    //滑动到最底端,禁止往下滑动                    if(viewLocation[1]-parentLocation[1]>=mHeight-ivHeight&&dy>0){                        break;                    }                    scrollBy(0,-dy);                    lastY = (int) event.getY();                    lastX = (int) event.getX();                }////判断用户是否按住拖拽按钮,并获得当前滑动速度   // 快速滑动                else if(isViewHit(iv_drag,lastX,lastY)&&Math.abs(getVelocity())>=2000){                    if(dy<0){                        mScroller.startScroll(0,getScrollY(),0,mTop-getScrollY());                        postInvalidate();                    }                }                break;            case MotionEvent.ACTION_UP:            //当前是按住按钮不动,松开后,View滑到最低部                if(Math.abs(event.getX()-mInitialMotionX)<touchSlop                &&Math.abs(event.getY()-mInitialMotionY)<touchSlop                        &&isViewHit(iv_drag,(int)event.getX(),(int)event.getY())){                    mScroller.startScroll(0,getScrollY(),0,ivHeight-mHeight+mTop-getScrollY(),1000);                    postInvalidate();                }//边界处理,滑到超过顶部,滚到顶部                if(viewLocation[1]<parentLocation[1]){                    mScroller.startScroll(0,getScrollY(),0,viewLocation[1]-parentLocation[1]);                    postInvalidate();                }//边界处理,滑到超过底部,滚到底部                if(viewLocation[1]-parentLocation[1]>=mHeight-ivHeight){                    mScroller.startScroll(0,getScrollY(),0,(viewLocation[1]-parentLocation[1]-mHeight+ivHeight));                    postInvalidate();                }                Log.e("DragView","viewPosition[1]"+viewLocation[1]);                Log.e("DragView","up");                recycleVelocity();                break;            case MotionEvent.ACTION_CANCEL:                recycleVelocity();                break;        }        return isViewHit(iv_drag,lastX,lastY)||isViewHit(contentView,lastX,lastY);    }    /**    *用于判断传入的x,y 坐标是否在view 范围内.    *    */    public boolean isViewHit(View view,int x,int y){        viewLocation = new int[2];        view.getLocationInWindow(viewLocation);        parentLocation = new int[2];        this.getLocationInWindow(parentLocation);        int screenX  = parentLocation[0] + x;        int screenY  = parentLocation[1] + y;        return screenX > viewLocation[0]&&screenX< viewLocation[0]+view.getWidth()&&                screenY > viewLocation[1]&&screenY< viewLocation[1]+view.getHeight();    }    /**     * 获取y方向的加速度     *     * @return     */    private int getVelocity()    {        mVelocityTracker.computeCurrentVelocity(1000);        return (int) mVelocityTracker.getYVelocity();    }    /**     * 释放资源     */    private void recycleVelocity()    {        if (mVelocityTracker != null)        {            mVelocityTracker.recycle();            mVelocityTracker = null;        }    }    private void obtainVelocity(MotionEvent event)    {        if (mVelocityTracker == null)        {            mVelocityTracker = VelocityTracker.obtain();        }        mVelocityTracker.addMovement(event);    }    @Override    public void computeScroll() {        Log.e("DragView","computeScroll");        super.computeScroll();        if(mScroller.computeScrollOffset()){            Log.e("DragView1","mScroller.getCurrY()"+mScroller.getCurrY());            scrollTo(0,mScroller.getCurrY());            postInvalidate();        }    }}

里面有很多高度的计算,大家在草稿纸上画一下就清楚了.

1 0
原创粉丝点击