Android View各种尺寸位置相关的方法探究

  本来想做一个View间的碰撞检测之类的。

  动手做了才发现不是想象的那么简单。

  首先,写好了碰撞检测的工具类如下:

 

package com.mengdd.utils;

import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.View;

public class Collision2DUtils {

    public static boolean isPointInRect(int x, int y, Rect rect) {
        boolean isIn = false;

        isIn = rect.contains(x, y);

        return isIn;
    }

    public static boolean isPointInRectF(float x, float y, RectF rectF) {
        boolean isIn = false;

        isIn = rectF.contains(x, y);

        return isIn;
    }

    public static boolean isPointInView(float x, float y, View view) {
        if (null == view) {
            throw new IllegalArgumentException("view is null!");
        }

        boolean isIn = false;

        int top = view.getTop();
        int left = view.getLeft();
        int right = view.getRight();
        int bottom = view.getBottom();
        int width = view.getWidth();
        int height = view.getHeight();

        if (x >= left && x <= right && y >= top && y <= bottom) {
            isIn = true;
        }
        Log.i("View", ", x: " + x + ", left: " + left + ", right: " + right
                + ", y: " + y + ", top: " + top + ", bottom: " + bottom
                + ", width: " + width + ", height: " + height + ", result: "
                + isIn);
        return isIn;

    }
}


  三个方法,分别用于判断点是否在一个矩形中(整形,浮点型),还有判断一个点是否在一个View显示的范围中。

  然后测试了一下前两个方法,因为矩形对象都是自己直接用数字构建的,所以没有问题。

 

测试判断点是否在View中的方法

  思路是:在布局中写两个TextView,在Activity中重写onTouchEvent方法,判断点击的点是否在View中。

 

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (MotionEvent.ACTION_DOWN == event.getAction()) {
            float x = event.getX();
            float y = event.getY();

            detectCollision(x, y);

        }
        return super.onTouchEvent(event);
    }

 

  其中判断的方法:

  结果显示在另一个TextView里

    private void detectCollision(float x, float y) {

        boolean result1 = Collision2DUtils.isPointInView(x, y, block1);

        boolean result2 = Collision2DUtils.isPointInView(x, y, block2);

        mResult1.setText("result1: " + result1 + ", result2: " + result2);
    }

 

 

  一试就发现问题了:判断结果并不对

 

判断错误的原因:

  onTouchEvent()回调中获取的坐标值,是点击位置,是在绝对坐标中的。

  碰撞检测方法中View的getTop()getBottom()getLeft()getRight()获取的都是当前View相对于它的父类容器的顶部、底部、左边和右边的位置。

  因为一个是绝对位置一个是相对位置,所以无法比较。

  当然也有可以比较的情况,就是这个View的父类充满了整个屏幕,然后窗口的设置是无标题并且全屏的。

  在onCreate()方法中添加如下语句设置无标题全屏

 

requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

 


 

那如何获取View的绝对位置呢?

  逐一看了看View中与位置相关的几个get方法:

 

getTranslationX()

getTranslationY()

getLocalVisibleRect(Rect r)

getGlobalVisibleRect(Rect r)

getGlobalVisibleRect(Rect r, Point globalOffset)

getLocationInWindow(int[] location)

getLocationOnScreen(int[] location)

 

  完整Demo如下:

  布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".CollisionDetectionActivity" >

    <TextView
        android:id="@+id/touch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/result1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#FFBBBBFF"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/block1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/touch"
        android:background="#FFFFBBFF"
        android:padding="10dp"
        android:text="Touch Block1"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/block2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/block1"
        android:background="#FFBBFFBB"
        android:padding="10dp"
        android:text="Touch Block2"
        android:textSize="20sp" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/result1"
        android:layout_below="@id/block2" 
        android:id="@+id/myScrollView">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/info1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/info2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:textSize="20sp" />
        </LinearLayout>
    </ScrollView>

</RelativeLayout>
activity_collision_detection.xml

相关文章:

  • 2021-11-17
  • 2022-12-23
  • 2021-08-19
  • 2021-11-01
  • 2022-12-23
  • 2021-08-11
  • 2021-12-17
  • 2021-07-31
猜你喜欢
  • 2021-11-17
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-05-19
相关资源
相似解决方案