Android中的获取控件矩阵gethitrect方法
2017-07-28 12:00
281 查看
原文地址:http://souly.cn/%E6%8A%80%E6%9C%AF%E5%8D%9A%E6%96%87/2015/07/31/Android%E4%B8%AD%E7%9A%84%E8%8E%B7%E5%8F%96%E6%8E%A7%E4%BB%B6%E7%9F%A9%E9%98%B5getHitRect%E6%96%B9%E6%B3%95/
public void getHitRect(Rect outRect)这个方法用来找到控件占据的矩形区域的矩形坐标。 参数outRect表示控件占据的矩形区域。
测试代码如下,根据代码可以很直观的知道这个函数的用法:
查看log如下:
这样我们就可以知道控件的顶点坐标了。
可以用类似的方法判断是否点击到该控件上boolean isHit = Trect.contains((int)event.getX(), (int)event.getY());
注意:getHitRect作为获取控件所在的矩阵范围函数,我们平常调用时候如果是在控件的监听器里调用就没事, 但是如果主动的在onCreate 或者 onResume中,拿到的矩阵坐标全是0.因为getHitRect方法不能直接在onCreate中调用 ,原因是该控件还未在这个界面框架中得以测量布局,不知道到底是多少,所以我们要寻找一个时机去做这件事,两个方法:
1.运用该控件执行post(就把下面的那个parent当成你要获取getHitRect的方法)
2.自定义该控件,覆写onDraw,调用getHitRect.
Android4.0设计规定的有效可触摸的UI元素标准是48dp,转化为一个物理尺寸约为9毫米。7~10毫米,这是一个用户手指能准确并且舒适触摸的区域。
如下图所示,你的UI元素可能小于48dp,图标仅有32dp,按钮仅有40dp,但是他们的实际可操作焦点区域最好都应达到48dp的大小。
![](https://raw.githubusercontent.com/mxn21/mxn21.github.io/master/public/img/img53.jpg)
为使小的UI区域获得良好的触摸交互,根据View的特性,目前碰到了两种情况:
1.如ImageView,设置其padding值,可触摸区域将向外扩展;
2.如Button,设置其padding值,可触摸区域不变,其内内容显示区域向内压缩;
情况1的控件,可直接设置其padding值达到目的,如 android:padding=”10dp”
情况2的控件,可使用TouchDelegate动态修改其触摸区域,达到扩大点击范围的效果.
这里大致说一下setTouchDelegate的作用:假设有两个View,分别是v1,v2,我们可以通过v1的setTouchDelegate(bounds, v2)来委派触摸事件, 其中bounds是一个Rect。v1中,落在这个范围的TouchEvent都会传给v2。
既然是这样,那我们可以通过设置某个view的parent的touchDelegate来达到扩大这个view触摸范围的目的。 关键是什么时候去执行parent.setTouchDelegate()方法呢?要设置这个委派,必须得知道当前view大小以及它在parent的位置。 而这些数据都是在onLayout才能确定(注:如果不是自定义View,只是在Activity中设置,请将这些操作置于onWindowFocusChanged()方法中)。
代码如下:
采取此种方法的两点注意:
1、若View的自定义触摸范围超出Parent的大小,则超出的那部分无效。 2、一个Parent只能设置一个View的TouchDelegate,设置多个时只有最后设置的生效。
若需要恢复该View的触摸范围:
使用TouchDelegate扩大View的触摸响应范围是一种比较灵活的方法,有时可与设置padding的方式结合使用。
注意:将此法应用在ListView的getView()中绘制每个ItemView时,则Delegate的设置将部分失效,原因是ListView的绘制较特殊,可能无法获取到部分还未绘制出的View的正确坐标。
getHitRect的作用和用法
public void getHitRect(Rect outRect)这个方法用来找到控件占据的矩形区域的矩形坐标。 参数outRect表示控件占据的矩形区域。测试代码如下,根据代码可以很直观的知道这个函数的用法:
public class MainActivity extends Activity { private TextView textView = null; private Button button = null; Rect Trect = new Rect(); Rect Brect = new Rect(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.tv01); button = (Button) findViewById(R.id.btn); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { textView.getHitRect(Trect); button.getHitRect(Brect); Log.e("TAG", "---------TextView_left-------" + String.valueOf(Trect.left)); Log.e("TAG", "---------TextView_top-------" + String.valueOf(Trect.top)); Log.e("TAG", "---------TextView_right-------" + String.valueOf(Trect.right)); Log.e("TAG", "---------TextView_bottom-------" + String.valueOf(Trect.bottom)); Log.e("TAG", "---------Button_left-------" + String.valueOf(Brect.left)); Log.e("TAG", "---------Button_top-------" + String.valueOf(Brect.top)); Log.e("TAG", "---------Button_right-------" + String.valueOf(Brect.right)); Log.e("TAG", "---------Button_bottom-------" + String.valueOf(Brect.bottom)); } }); } }
查看log如下:
06-17 18:07:55.534: E/hailong(5797): ---------TextView_left-------281 06-17 18:07:55.534: E/hailong(5797): ---------TextView_top-------475 06-17 18:07:55.534: E/hailong(5797): ---------TextView_right-------438 06-17 18:07:55.534: E/hailong(5797): ---------TextView_bottom-------513 06-17 18:07:55.534: E/hailong(5797): ---------Button_left-------281 06-17 18:07:55.534: E/hailong(5797): ---------Button_top-------513 06-17 18:07:55.534: E/hailong(5797): ---------Button_right-------439 06-17 18:07:55.534: E/hailong(5797): ---------Button_bottom-------609
这样我们就可以知道控件的顶点坐标了。
可以用类似的方法判断是否点击到该控件上boolean isHit = Trect.contains((int)event.getX(), (int)event.getY());
注意:getHitRect作为获取控件所在的矩阵范围函数,我们平常调用时候如果是在控件的监听器里调用就没事, 但是如果主动的在onCreate 或者 onResume中,拿到的矩阵坐标全是0.因为getHitRect方法不能直接在onCreate中调用 ,原因是该控件还未在这个界面框架中得以测量布局,不知道到底是多少,所以我们要寻找一个时机去做这件事,两个方法:
1.运用该控件执行post(就把下面的那个parent当成你要获取getHitRect的方法)
final View parent = (View) delegate.getParent(); parent.post( new Runnable() { // Post in the parent's message queue to make sure the parent // lays out its children before we call getHitRect() public void run() { final Rect r = new Rect(); delegate.getHitRect(r); r.top -= 4; r.bottom += 4; parent.setTouchDelegate( new TouchDelegate( r , delegate)); } });
2.自定义该控件,覆写onDraw,调用getHitRect.
扩大view点击范围
Android4.0设计规定的有效可触摸的UI元素标准是48dp,转化为一个物理尺寸约为9毫米。7~10毫米,这是一个用户手指能准确并且舒适触摸的区域。如下图所示,你的UI元素可能小于48dp,图标仅有32dp,按钮仅有40dp,但是他们的实际可操作焦点区域最好都应达到48dp的大小。
![](https://raw.githubusercontent.com/mxn21/mxn21.github.io/master/public/img/img53.jpg)
为使小的UI区域获得良好的触摸交互,根据View的特性,目前碰到了两种情况:
1.如ImageView,设置其padding值,可触摸区域将向外扩展;
2.如Button,设置其padding值,可触摸区域不变,其内内容显示区域向内压缩;
情况1的控件,可直接设置其padding值达到目的,如 android:padding=”10dp”
情况2的控件,可使用TouchDelegate动态修改其触摸区域,达到扩大点击范围的效果.
这里大致说一下setTouchDelegate的作用:假设有两个View,分别是v1,v2,我们可以通过v1的setTouchDelegate(bounds, v2)来委派触摸事件, 其中bounds是一个Rect。v1中,落在这个范围的TouchEvent都会传给v2。
既然是这样,那我们可以通过设置某个view的parent的touchDelegate来达到扩大这个view触摸范围的目的。 关键是什么时候去执行parent.setTouchDelegate()方法呢?要设置这个委派,必须得知道当前view大小以及它在parent的位置。 而这些数据都是在onLayout才能确定(注:如果不是自定义View,只是在Activity中设置,请将这些操作置于onWindowFocusChanged()方法中)。
代码如下:
/** * 扩大View的触摸和点击响应范围,最大不超过其父View范围 * * @param view * @param top * @param bottom * @param left * @param right */ public static void expandViewTouchDelegate(final View view, final int top, final int bottom, final int left, final int right) { ((View) view.getParent()).post(new Runnable() { @Override public void run() { Rect bounds = new Rect(); view.setEnabled(true); view.getHitRect(bounds); bounds.top -= top; bounds.bottom += bottom; bounds.left -= left; bounds.right += right; TouchDelegate touchDelegate = new TouchDelegate(bounds, view); if (View.class.isInstance(view.getParent())) { ((View) view.getParent()).setTouchDelegate(touchDelegate); } } }); }
采取此种方法的两点注意:
1、若View的自定义触摸范围超出Parent的大小,则超出的那部分无效。 2、一个Parent只能设置一个View的TouchDelegate,设置多个时只有最后设置的生效。
若需要恢复该View的触摸范围:
/** * 还原View的触摸和点击响应范围,最小不小于View自身范围 * * @param view */ public static void restoreViewTouchDelegate(final View view) { ((View) view.getParent()).post(new Runnable() { @Override public void run() { Rect bounds = new Rect(); bounds.setEmpty(); TouchDelegate touchDelegate = new TouchDelegate(bounds, view); if (View.class.isInstance(view.getParent())) { ((View) view.getParent()).setTouchDelegate(touchDelegate); } } }); }
使用TouchDelegate扩大View的触摸响应范围是一种比较灵活的方法,有时可与设置padding的方式结合使用。
注意:将此法应用在ListView的getView()中绘制每个ItemView时,则Delegate的设置将部分失效,原因是ListView的绘制较特殊,可能无法获取到部分还未绘制出的View的正确坐标。
相关文章推荐
- android 关于如何获取控件矩阵 getHitRect
- android 关于如何获取控件矩阵 getHitRect
- [Android]在游戏的SurfaceView中获取输入与使用EditText,Spinner等控件的方法
- android获取屏幕宽高与获取控件宽高 方法总结
- Android获取控件大小的方法
- Android 获取控件高度宽度三种方法,防止0的出现
- Android 获取控件高度宽度三种方法,防止0的出现~~~~赞
- Android编程获取控件宽和高的方法总结分析
- Android 获取控件高度宽度三种方法,防止0的出现
- Android 根据坐标获取控件方法
- Android 根据坐标获取控件方法
- Android学习 之 获取可视区域的Rect对象(顺带获取状态栏和标题栏高度的方法)
- Android在onCreate()方法中动态获取TextView控件的高度
- Android如何在onCreate()方法中获取控件的高度和宽度
- Android 获取控件高度宽度三种方法,防止0的出现,计算空间宽度,文字宽度
- Android获取控件大小的方法
- Android 获取控件高度宽度三种方法,防止0的出现
- android获取屏幕宽高与获取控件宽高 方法总结
- Android 获取控件高度宽度三种方法,防止0的出现
- android developer tips---干掉adb侵入者命令和activity中获取控件宽高方法