仿折800,拖拽控件悬停在左边右边 用的是 ViewDragHelper

之前想做一个类似刷新的控件,拖动悬停的,大部分app都有这个功能了,之前做的思路是:onTouchEvent 里面拿到xy,onlayout 给位置,这样做也不错,不过不是自带的,而且在抬起的事件里面也是判断的坐标,来给的位置,是没有动画的。看起来不是很友好。


直接放源码不难的:如果你对它不熟可以看

http://blog.csdn.net/lmj623565791/article/details/46858663


package com.example.wuyakun.myapplication1.view;

import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

/**
 * Created by WYK on 16/8/15.
 */
public class VDHLayout extends LinearLayout {

    private ViewDragHelper mViewDragHelper;

    public VDHLayout(Context context) {
        super(context);
        throw new RuntimeException("you can not do this.");
    }

    public VDHLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VDHLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                //是否可以拖拽
                return true;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                //不允许超过  控件左边到  最左边-paddingLeft的距离
                final int leftBound = getPaddingLeft();
                final int rightBound = getWidth() - child.getWidth() - getPaddingRight();
                return Math.min(Math.max(left, leftBound), rightBound);
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                //同理
                final int topBound = getPaddingTop();
                final int bottomBound = getHeight() - child.getHeight() - getPaddingBottom();
                return Math.min(Math.max(top, topBound), bottomBound);
            }

            //手指释放的时候回调
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {

                int x = releasedChild.getLeft();

                int y = releasedChild.getTop();

                int paddingLeft = getPaddingLeft();

                int paddingRight = getPaddingRight();

                if (x > (getWidth() - releasedChild.getWidth()) / 2 - paddingLeft) {
                    //如果在右边一半
                    x = getWidth() - paddingRight - releasedChild.getWidth();
                } else {
                    //否则就在左边
                    x = paddingLeft;
                }

                //控制它动画返回到哪里
                mViewDragHelper.settleCapturedViewAt(x, y);
                invalidate();
            }

            /**
             * 大于 0 才可以拖动
             * 因为设置了android:clickable="true"
             * 也就是点击事件,需要在下面方法里面返回大于 0 要不然不能拖了
             * @param child
             * @return
             */

            @Override
            public int getViewHorizontalDragRange(View child) {
                return getMeasuredWidth() - child.getMeasuredWidth();
            }

            @Override
            public int getViewVerticalDragRange(View child) {
                return getMeasuredHeight() - child.getMeasuredHeight();
            }

        });
    }

    /**
     * Touch 交给 ViewDragHelper
     *
     * @param event
     * @return
     */

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        return true;
    }

    /**
     * 拦截 交给 ViewDragHelper
     *
     * @param ev
     * @return
     */

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    /**
     * 为滚动而生 -- 主要是为了 settleCapturedViewAt
     * 想知道为啥可以看下上面的链接里的文章
     */

    @Override
    public void computeScroll() {
        if (mViewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

}



layout 也很简单:


<?xml version="1.0" encoding="utf-8"?>
<com.example.wuyakun.myapplication1.view.VDHLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/fab_margin"
    android:paddingLeft="@dimen/fab_margin"
    >

    <LinearLayout
        android:id="@+id/lyt_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:orientation="vertical"
        >

        <TextView
            android:id="@+id/textView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#7ccccccc"
            android:gravity="center"
            android:text="New Text"/>

    </LinearLayout>

</com.example.wuyakun.myapplication1.view.VDHLayout>


activity 也贴一下


package com.example.wuyakun.myapplication1;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

/**
 * Created by WYK on 16/8/16.
 */
public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.test_layout);

        findViewById(R.id.lyt_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(TestActivity.this, "test", Toast.LENGTH_SHORT).show();
            }
        });
    }
}



可能有计算啥的错了一点点,需要你去学会了大笑,直接改




动态图我就不贴了,防止你偷懒大笑




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值