View体系与自定义View(二)—— View的滑动

当点击事件传到View时,系统会记下触摸点的坐标,手指移动时系统记下移动后触摸的坐标并计算出偏移量,通过偏移量来修改View的坐标。实现View滑动有很多中方法,主要有:layout(...)offsetLeftAndRight(...)offsetTopAndBottom(...)LayoutParams、动画、scrollTo(x, y)scrollBy(dx, dy),以及Scroller

1 layout(...)方法

View进行绘制的时候会调用onLayout()方法来设置显示的位置,因此可以通过修改Viewlefttoprightbottom4 种属性来控制View的坐标。

首先自定义一个View,在onTouchEvent()方法中获取触摸点的坐标,代码如下所示:

public class CustomView extends View {
   

  private int lastX;
  private int lastY;

  public CustomView(@NonNull @NotNull Context context) {
   
    super(context);
  }

  public CustomView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
   
    super(context, attrs);
  }

  public CustomView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
   
    super(context, attrs, defStyleAttr);
  }

  // 1. 在onTouchEvent()方法中获取触摸点的坐标
  @Override
  public boolean onTouchEvent(MotionEvent event) {
   
    // 2. 获取触摸点的横、纵坐标	
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()) {
   
      case MotionEvent.ACTION_DOWN:
        lastX = x;
        lastY = y;
        break;
      case MotionEvent.ACTION_MOVE:
        // 3. 计算偏移量
        int offsetX = x - lastX;
        int offsetY = y - lastY;
        // 4. layout()方法重新放置这个自定义View的位置
        // 5. 每次移动时都会调用layout()方法来对屏幕重新布局,从而达到移动View的效果
        layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
        break;
    }
    return true;
  }
}

在布局中引用自定义View

<RelativeLayout 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"
    tools:context=".MainActivity">

    <com.example.myapplication.CustomView
        android:id="@+id/custom_view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="50dp"
        android:background="@android:color/holo_red_dark" />

</RelativeLayout>

2 offsetLeftAndRight(...)offsetTopAndBottom(...)

这两种方法和layout()方法的效果差不多,其使用方式也差不多,将ACTION_MOVE中的代码替代如下:

case MotionEvent.ACTION_MOVE:
		// 1. 计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
		// 2. 对left和right进行偏移
    offsetLeftAndRight(offsetX);
		// 3. 对top和bottom进行偏移
    offsetTopAndBottom(offsetY);
    break;

3 LauyoutParams(改变布局参数)

LayoutParams主要保存了一个View的布局参数,因此可以通过LayoutParams来改变View的布局参数,从而达到改变View位置的效果,ACTION_MOVE中:

case MotionEvent.ACTION_MOVE:
    int offsetX = x - lastX;
    int offsetY = y - lastY;
		// 1. 取决于父控件,如果是RelativeLayout,那就是RelativeLayout.LayoutParams
    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
    layoutParams.leftMargin = getLeft() + offsetX;
    layoutParams.topMargin = getTop() + offsetY;
    setLayoutParams(layoutParams);
    break;

4 动画

可以采用View动画来移动,在res目录新建anim文件夹并创建translate.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">
    <translate
        android:fromXDelta="0"
        android:toXDelta="300" />
</set>

Java代码中调用:

findViewById(R.id.button).setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));

运行程序,设置的按钮会向右移动300像素,然后又回到原来的位置。如果想要停留在当前位置,需要加上android:fillAfter="true"

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值