安卓作业----慕课移动互联网作业9利用ViewDragHelper实现qq消息栏侧滑删除效果

此博客利用ViewDragHelper实现qq消息栏侧滑删除效果,同时这也是中国大学慕课移动终端应用开发的网课作业9,我会持续更新我的作业,如果有需要关注一下吧

说明

1.由于涉及到没有学过的内容,自学的时候参考了此篇博文菜鸟教程,并在原基础上做了优化,并补充了几乎每个新知识的注释。

2.粘贴的时候注意包的正确导入,Message实体类不要和安卓的消息类混淆

3.注意修改布局文件item.xml上ViewGroup的包名,android studio不会主动报错,但是要修改,不然无法通过编译

4.还有其他注意点我想到了再补充……嘿嘿

哦对了,作业8太简单我就不写了

效果图

在这里插入图片描述

代码部分

代码分成四个部分,第一部分是消息实体类Message.java,第二部分是ListView的子布局,涉及到item.xml布局文件和TranslationLayout.java自定义布局,第三部分是适配器MessageAdapter.java,第四部分是主界面MainActivity.java和activity_main.xml主布局文件。以下是具体内容:

Message.java
/**
 * 消息实体类
 * */
public class Message {
    private String name;    //姓名
    private String content; //内容
    private String date;    //日期
    private int img;        //头像id资源

    public Message() {
    }

    public Message(String name, String content) {
        this.name = name;
        this.content = content;
        this.date = "6:00 am";
        this.img = R.drawable.boy;
    }

    public Message(String name, String content, String date, int img) {
        this.name = name;
        this.content = content;
        this.date = date;
        this.img = img;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public int getImg() {
        return img;
    }

    public void setImg(int img) {
        this.img = img;
    }
}
item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.course9.mylayout.TranslationLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:paddingLeft="5dp"
        android:background="#DCF5F1">

        <ImageView
            android:id="@+id/image"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/boy"
            />

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/image"
            android:layout_alignBottom="@+id/image"
            android:layout_toRightOf="@+id/image"
            android:layout_marginLeft="15dp"
            tools:ignore="RtlHardcoded">

            <TextView
                android:id="@+id/name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="大青儿"
                android:textSize="25dp"
                android:textColor="#F1A46C"
                />

            <TextView
                android:id="@+id/content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingTop="2dp"
                android:text="早上好铁子"
                android:textSize="15dp"
                android:textColor="#222121"
                android:layout_alignParentBottom="true"
                />

            <TextView
                android:id="@+id/time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="6:00 am"
                android:textSize="19sp"
                android:textColor="#FF7F7F80"
                android:layout_alignParentRight="true"
                android:padding="10dp"
                android:paddingRight="20dp"
                />
        </RelativeLayout>

    </RelativeLayout>

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/to_top"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:text="置顶"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:gravity="center"
            android:background="#FFC6C6CC"/>
        <TextView
            android:id="@+id/have_read"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:text="已读"
            android:gravity="center"
            android:background="#FFFD9C01"/>
        <TextView
            android:id="@+id/delete"
            android:layout_width="66.5dp"
            android:layout_height="match_parent"
            android:textColor="#FFF"
            android:textSize="17sp"
            android:text="删除"
            android:gravity="center"
            android:background="#FFFD3A30" />
    </LinearLayout>


</com.example.course9.mylayout.TranslationLayout>
TranslationLayout.java

此为自定义布局,这一部分是本博客的重中之重,几乎每一处的代码我都写有注释,李姐万岁

import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.customview.widget.ViewDragHelper;

public class TranslationLayout extends LinearLayout {
    private ViewDragHelper mViewDragHelper;//定义mViewDragHelper

    public boolean directionFlag = true;//移动方向的标志,true为左,false为右

    private int screenWidth;//屏幕的宽度
    private Context mContext;//上下文对象

    private View firstView;//第一个view对象
    private View secondView;//第二个view对象

    private int secondViewWidth;//第二个view的长度

    private final String TAG = "TranslationLayoutTAG";//logcat的标记

    public TranslationLayout(Context context) {
        super(context);
        this.mContext = context;
        init();
    }

    public TranslationLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        init();
    }

    public TranslationLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        init();
    }

    //初始化方法
    private void init(){
        mViewDragHelper = ViewDragHelper.create(this,new MyCallBack());
        //获取屏幕的长度
        WindowManager wm=(WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        screenWidth = outMetrics.widthPixels;
    }

    //在第一次渲染结束的时候,获取两个子View
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        firstView = getChildAt(0);//获取第一个子view,一开始显示的那个
        secondView = getChildAt(1);//获取第二个view,后面隐藏的,侧滑之后才能看见
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取第二个view的长度
        secondViewWidth = secondView.getMeasuredWidth();
    }

    //在onInterceptTouchEvent中授权mViewDragHelper.shouldInterceptTouchEvent(ev)
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    //在onTouchEvent中授权 mViewDragHelper.processTouchEvent(event);
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 处理相应的TouchEvent的时候要将结果返回为true,消费本次事件
        //否则将无法使用ViewDragHelper处理相应的拖拽事件
        mViewDragHelper.processTouchEvent(event);
        return true;
    }

    //重写的ViewGroup的方法,主要是用于ViewGroup中更新相应View
    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    //内部类
    private class MyCallBack extends ViewDragHelper.Callback{
        private int left;

        //必须实现此方法,也只有在这个方法返回true的时候下面的方法才会生效
        @Override
        public boolean tryCaptureView(@NonNull View child, int pointerId) {
            return true;
        }

        /**
         * 当状态改变的时候回调,返回相应的状态(这里有三种状态)
         *         STATE_IDLE 闲置状态
         *         STATE_DRAGGING 正在拖动
         *         STATE_SETTLING 放置到某个位置
         * */
        @Override
        public void onViewDragStateChanged(int state) {
            super.onViewDragStateChanged(state);
        }

        /**
         * 位置发生改变的时候回调
         *             参数1:你当前拖动的这个View
         *             参数2:距离左边的距离
         *             参数3:距离上边的距离
         *             参数4:x轴的变化量
         *             参数5:y轴的变化量
         * */
        @Override
        public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            //如果第一个view被拖动,第二个view(被隐藏那个)也跟着移动
            if (changedView == firstView){
                secondView.offsetLeftAndRight(dx);
            }else {//如果移动的是第二个,第一个view也跟着移动
                firstView.offsetLeftAndRight(dx);
            }
            this.left = left;
            //更新ui
            invalidate();
        }

        /**
         * 在该方法中对child移动的水平边界进行控制,left表示即将移动到的位置。
         * */
        @Override
        public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
            return Math.min(Math.max(-secondViewWidth, left), 0);//使其不能向右滑动;
        }

        /**
         * 垂直边界进行控制
         * */
        @Override
        public int getViewVerticalDragRange(View child) {
            return 0;
        }

        //停止拖拽的时候
        @Override
        public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);

            Log.d(TAG,"firstView.getRight():"+firstView.getRight());
            //getRight()方法返回的是组件右边到屏幕左边的距离
            //触发左移的条件是移动超过50dp并且方向向左
            if(firstView.getRight()<(screenWidth-50)&&directionFlag){
                //将第一个View向左移动第二个view宽度
                mViewDragHelper.smoothSlideViewTo(firstView,-secondViewWidth, 0);
                //更新ui
                ViewCompat.postInvalidateOnAnimation(TranslationLayout.this);
                //方向设置为右边
                directionFlag = false;
            } else {//方向为右边或者移动小于50dp
                //将第一个View移动回去
                mViewDragHelper.smoothSlideViewTo(firstView, 0, 0);
                //更新ui
                ViewCompat.postInvalidateOnAnimation(TranslationLayout.this);
                //方向设置为左边
                directionFlag = true;
            }
        }
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/my_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none">
    </ListView>
</LinearLayout>
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ListView;

import com.example.course9.adapter.MessageAdapter;
import com.example.course9.model.Message;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private ListView mListView;//定义ListView
    private ArrayList<Message> mMessages;

    private void init(){
        mListView = findViewById(R.id.my_list_view);
        mMessages = new ArrayList<>();
        //放入数据
        Message message1 = new Message("大青儿","今天早上我这好像下雪了,你那边呢");
        Message message2 = new Message("小钱","和平精英,速速上线,快快快!!!");
        Message message3 = new Message("小谢","科目三好难啊,感觉比考研还难咋办啊铁子");
        Message message4 = new Message("小王","明天出来搓一顿啊");
        Message message5 = new Message("特朗普","我比任何人都要懂安卓,我知道");
        Message message6 = new Message("老妈","今天天气好冷,你要多穿一点衣服");
        mMessages.add(message1);
        mMessages.add(message2);
        mMessages.add(message3);
        mMessages.add(message4);
        mMessages.add(message5);
        mMessages.add(message6);

        MessageAdapter adapter = new MessageAdapter(this,mMessages);
        mListView.setAdapter(adapter);
    }

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

图片资源

图片资源来自阿里巴巴矢量图标库

boy.png,放入drawable文件夹中
在这里插入图片描述

最后

码字不易,如有帮助,点赞关注分享给个好评哦亲

发布了35 篇原创文章 · 获赞 67 · 访问量 6133

猜你喜欢

转载自blog.csdn.net/baidu_41860619/article/details/105164147