Android-自定义仿QQ列表Item滑动

Posted 原创Android 努力学习 专一安卓 持之以恒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android-自定义仿QQ列表Item滑动相关的知识,希望对你有一定的参考价值。

效果图:

 

布局中去指定自定义FrameLayout:

<!-- 自定义仿QQ列表Item滑动 -->
<view.custom.shangguigucustomview.MyCustomFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:orientation="vertical"
    tools:context=".ShangGuiguTestActivity"
    android:background="@android:color/darker_gray">

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="@android:color/white"
        android:textColor="@android:color/black"
        android:textSize="20dp"
        android:text="你有一条消息未读"
        android:gravity="center"
        android:drawableLeft="@mipmap/ic_launcher_round"
        android:paddingRight="40dp"
        />

    <TextView
        android:id="@+id/tv_menu"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:background="@android:color/holo_orange_dark"
        android:textColor="#f00000"
        android:textSize="20dp"
        android:text="删除"
        android:gravity="center"
        android:paddingLeft="30dp"
        android:paddingRight="30dp"
        />

</view.custom.shangguigucustomview.MyCustomFrameLayout>

 

自定义FrameLayout:

public class MyCustomFrameLayout extends FrameLayout { // 继承于FrameLayout属于继承ViewGroup,因为它包含了孩子

    private static final String TAG = MyCustomFrameLayout.class.getSimpleName();

    /**
     * 拿到两个控件的宽和三个的高
     * @param context
     * @param attrs
     */
    private int myHeigth; // 统一的高度
    private int myContentWidth; // 中间内容TextView的宽度
    private int myMenuWidth; // 菜单的宽度

    private Scroller scroller;

    public MyCustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        scroller = new Scroller(context);
    }

    private View tvContent;
    private View tvMenu;

    /**
     * 当布局加载完成✅后就会回调此方法
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        tvContent = getChildAt(0); // 拿到第一个孩子
        tvMenu = getChildAt(1); // 得到第二个孩子
    }

    /**
     * 测量两个孩子的高宽
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        myContentWidth = tvContent.getMeasuredWidth(); // 等价于getMeasuredWidth();因为这个是后去父控件的宽度,父控件和这个孩子控件宽度是一样的
        myHeigth = getMeasuredHeight();
        myMenuWidth = tvMenu.getMeasuredWidth();
    }

    /**
     * 为何不让实现者强制重写,应该在FrameLayout中已经重写过了
     * @param changed
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        // 指定位置
        tvContent.layout(0, 0, myContentWidth, myHeigth);
        tvMenu.layout(myContentWidth, 0 , myContentWidth + myMenuWidth, myHeigth);
    }

    private float startX;
    private int x;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                startX =  event.getX();
                break;
            case MotionEvent.ACTION_UP:
                float upEnd = event.getX();
                float thisUp = upEnd;
                // float myx = getScrollX() - thisUp;
                if (getScrollX() > myMenuWidth / 2) {
                    // x = myMenuWidth;

                    openM();
                } else {
                    // x = 0;

                    closeM();
                }
                /*invalidate();
                scroller.startScroll(getScrollX(), getScrollY(), x, Math.abs(1000));*/
                // scrollTo(x, getScrollY());
                break;
            case MotionEvent.ACTION_MOVE:
                int endX = (int) event.getX();
                int thisX = (int) (endX - startX);

                int scrollX = getScrollX();
                Log.i(TAG, ">>>>> scrollX" + scrollX);

                x =  scrollX - thisX;

                // 非法值的屏蔽
                if (x < 0) {
                    x = 0;
                } else if (x > myMenuWidth) {
                    x = myMenuWidth;
                }

                scrollTo(x, getScrollY());

                startX = event.getX();

                break;
            default:
                break;
        }
        return true;
    }

    private void openM() {
        invalidate();
        int dx = myMenuWidth - getScrollX();
        scroller.startScroll(getScrollX(), getScrollY(), dx, Math.abs(1000));
    }

    private void closeM() {
        invalidate();
        int dx = 0 - getScrollX();
        scroller.startScroll(getScrollX(), getScrollY(), dx, Math.abs(1000));
    }

    @Override
    public void computeScroll() {
        super.computeScroll();

        if (scroller.computeScrollOffset()) {
            int currX = scroller.getCurrX();
            scrollTo(currX, 0);
            invalidate();
        }
    }
}

 

以上是关于Android-自定义仿QQ列表Item滑动的主要内容,如果未能解决你的问题,请参考以下文章

Android仿QQ列表滑动

Android高级控件——自定义ListView高仿一个QQ可拖拽列表的实现

仿qq会话列表滑动效果

android 自定义View:仿QQ拖拽效果

android 自定义View:仿QQ拖拽效果

自定义ViewpagerIndicator (仿猫眼,添加边缘回弹滚动效果)