Android实现滑动的四种方式

Posted 我想月薪过万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实现滑动的四种方式相关的知识,希望对你有一定的参考价值。

效果展示

android自定义View开发,实现布局的滑动是必不可少的一项手艺。下面我为大家准备了五种移动布局的方法:

  1. layout 法  CoordinatorLayout原理的简析
  2. LayoutParams 法 CoordinatorLayout原理的简析
  3. scrollTo/scrollBy
  4. Scroller 类
  5. ViewDragHelper 类 : ViewDragHelper 类

activity_main.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.wust.SelfCoordinator.CanDragView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#f00"/>
        <TextView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#0f0"
            android:layout_marginTop="200dp"/>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>


</LinearLayout>

这里面存在 CoordinatorLayout 这个布局,是因为我准备写 CoordinatorLayout 布局的教程的,Android滑动方式只是个小插曲,所以,布局文件可以不用按照我的写,仅供参考。

1、layout 法

自定义View的 java 代码


package com.wust.SelfCoordinator;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * ClassName: CanDragView <br/>
 * Description: <br/>
 * date: 2021/6/29 9:45<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 */
public class CanDragView extends View {

    int startX;
    int startY;

    public CanDragView(Context context) {
        this(context,null);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            {
                startX =(int) event.getX();
                startY =(int) event.getY();
            }
                break;
            case MotionEvent.ACTION_MOVE:
            {
                int endX = (int) event.getX();
                int endY = (int) event.getY();
                int moveX = endX - startX;
                int moveY = endY - startY;
                System.out.println("moveX ->" + moveX + "moveY ->" + moveY);
                //移动布局的关键性代码
                layout(getLeft()+moveX,getTop()+moveY,getRight()+moveX,getBottom()+moveY);
            }
                break;
        }
        return true;
    }


}

2、LayoutParams 法

package com.wust.SelfCoordinator;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
 * ClassName: CanDragView <br/>
 * Description: <br/>
 * date: 2021/6/29 9:45<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 */
public class CanDragView extends View {

    int startX;
    int startY;

    public CanDragView(Context context) {
        this(context,null);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            {
                startX =(int) event.getX();
                startY =(int) event.getY();
            }
                break;
            case MotionEvent.ACTION_MOVE:
            {
                int endX = (int) event.getX();
                int endY = (int) event.getY();
                int moveX = endX - startX;
                int moveY = endY - startY;
                System.out.println("moveX ->" + moveX + "moveY ->" + moveY);
                //移动布局的关键性代码,如果布局已经在 xml 文件中存在,你直接用 getLayoutParams() 获取参数信息就可以了,不要在重新 new
                CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) getLayoutParams();
                params.leftMargin = getLeft()+moveX;
                params.topMargin = getTop()+moveY;
                setLayoutParams(params);
            }
                break;
        }
        return true;
    }


}

3、scrollTo/scrollBy

package com.wust.SelfCoordinator;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
 * ClassName: CanDragView <br/>
 * Description: <br/>
 * date: 2021/6/29 9:45<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 */
@SuppressLint("AppCompatCustomView")
public class CanDragView extends TextView {

    int startX;
    int startY;

    public CanDragView(Context context) {
        this(context,null);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            {
                startX =(int) event.getX();
                startY =(int) event.getY();
            }
                break;
            case MotionEvent.ACTION_MOVE:
            {
                int endX = (int) event.getX();
                int endY = (int) event.getY();
                int moveX = endX - startX;
                int moveY = endY - startY;
                System.out.println("moveX ->" + moveX + "moveY ->" + moveY);
                //移动布局的关键性代码,scrollTo/scrollBy 移动的是 View中的内容 ViewGroup中的子View
                scrollTo(-(getLeft()+moveX),-(getTop()+moveY));
                invalidate();
            }
                break;
        }
        return true;
    }


}

需要注意的两点:

  1. 这个方法移动的 布局 的内容,不是自己
  2. 得加负号,大家自己尝试一下就明白了

Scroller 类

原理大家可以参考这篇文章 : Scroller与computeScroll处理滑动

package com.wust.SelfCoordinator;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

/**
 * ClassName: CanDragView <br/>
 * Description: <br/>
 * date: 2021/6/29 9:45<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 */
@SuppressLint("AppCompatCustomView")
public class CanDragView extends TextView {

    int startX;
    int startY;
    private Scroller scroller;
    private int moveX;
    private int moveY;

    public CanDragView(Context context) {
        this(context,null);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CanDragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //第一步:创建 scroller 对象
        scroller = new Scroller(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            {
                startX =(int) event.getX();
                startY =(int) event.getY();
            }
                break;
            case MotionEvent.ACTION_MOVE:
            {
                int endX = (int) event.getX();
                int endY = (int) event.getY();
                moveX = endX - startX;
                moveY = endY - startY;
                System.out.println("moveX ->" + moveX + "moveY ->" + moveY);
                //移动布局的关键性代码,scrollTo/scrollBy 移动的是 View中的内容 ViewGroup中的子View
                //第二步:开始滚动
                scroller.startScroll(getLeft(),getTop(), moveX, moveY);
                //这个不能少,因为这个会调用 computeScroll()
                invalidate();
            }
                break;
        }
        return true;
    }

    @Override
    public void computeScroll() {
        //第三步:编写 computeScroll,反复矫正
        if (scroller.computeScrollOffset()){
            scrollTo(getLeft()+moveX,getTop()+moveY);
            invalidate();
        }
        super.computeScroll();
    }
}

这个方法也是移动内容,和 scrollTo / scrollBy 一样。

ViewDragHelper 类

大家参考链接自行尝试。 

以上是关于Android实现滑动的四种方式的主要内容,如果未能解决你的问题,请参考以下文章

Android自己定义控件:进度条的四种实现方式

Android自定义控件:进度条的四种实现方式

Android 阴影背景的四种实现方式

android线程间通信的四种实现方式

Android使用ViewDragHelper实现侧滑菜单

Android 数据的四种存储方式