仅为 TextView 复合可绘制对象实现 onClick
Posted
技术标签:
【中文标题】仅为 TextView 复合可绘制对象实现 onClick【英文标题】:Implement onClick only for a TextView compound drawable 【发布时间】:2012-05-26 19:51:35 【问题描述】:我需要在左侧有一些带有可绘制对象的文本,并且我想在用户单击/触摸图像时执行一些代码(只有图像,而不是文本),所以我使用了 LinearLayout em> 带有一个 TextView 和一个 ImageView ,可点击并启动 onClick 事件。 XML 解析器建议我用带有 compound drawable 的 TextView 替换它,这样可以用更少的 XML 行来绘制相同的东西。 . 我的问题是“我可以指定我只想在 TextView 的可绘制对象上而不是在 TextView 本身上处理 onClick 事件吗?我已经看到了一些解决方案涉及编写自己的 TextView 扩展,但我只对能够在布局资源中执行此操作感兴趣,如果可能的话,否则我将保留以下 XML代码:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:layout_
android:layout_
android:gravity="bottom"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/home_feedback_title"
android:textColor="@android:color/primary_text_dark"
android:textStyle="bold"
android:paddingBottom="4dp"/>
<ImageView
android:layout_
android:layout_
android:src="@drawable/action_feedback"
android:clickable="true"
android:onClick="onClickFeedback"
android:contentDescription="@string/action_feedback_description"/>
</LinearLayout>
【问题讨论】:
【参考方案1】:它非常简单。假设您在 TextView 'txtview' 的左侧有一个可绘制对象。下面就可以解决问题了。
TextView txtview = (TextView) findViewById(R.id.txtview);
txtview.setOnTouchListener(new OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
if(event.getAction() == MotionEvent.ACTION_UP)
if(event.getRawX() <= txtview.getTotalPaddingLeft())
// your action for drawable click event
return true;
return true;
);
如果您想要正确的可绘制对象,请将 if 语句更改为:
if(event.getRawX() >= txtview.getRight() - txtview.getTotalPaddingRight())
同样,您可以对所有复合可绘制对象执行此操作。
txtview.getTotalPaddingTop();
txtview.getTotalPaddingBottom();
此方法调用返回该侧的所有填充,包括任何可绘制对象。您甚至可以将它用于 TextView、Button 等。
点击here来自android开发者网站的参考。
【讨论】:
【参考方案2】:你可以去任何一种方式。使用复合可绘制对象更快,因为它旨在进行优化。它使用更少的内存,因为您将 3 个视图减少到 1 个,并且布局更快,因为您失去了 1 个深度。
如果我是你,我会考虑退后一步,看看文本和图像都拦截触摸以执行任何操作是否可能是一件好事。一般来说,触摸区域越大,越容易按压。有些用户实际上可能更倾向于触摸文本而不是图像。
最后,如果您采用合并 2 的路线,您可能需要考虑使用 Button
而不是 TextView
。您可以设置按钮的样式,使其周围没有矩形。他们称之为无边框按钮。这很好,因为您会获得视觉反馈,即您单击了一个可操作的项目,而 ImageView
或 TextView
通常是不可操作的。
How to Create Borderless Buttons in Android
【讨论】:
【参考方案3】:@Vishnuvathsan 的答案几乎是完美的,但getRaw()
返回触摸点的绝对 x 位置。如果 textview 不在视图的左边缘,则应使用getLocationOnScreen
与 textview 的绝对位置进行比较。下面的代码是一个检查左侧可绘制点击和右侧可绘制点击的示例。
textView.setOnTouchListener(new OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
if (event.getAction() == MotionEvent.ACTION_UP)
int[] textLocation = new int[2];
textView.getLocationOnScreen(textLocation);
if (event.getRawX() <= textLocation[0] + textView.getTotalPaddingLeft())
// Left drawable was tapped
return true;
if (event.getRawX() >= textLocation[0] + textView.getWidth() - textView.getTotalPaddingRight())
// Right drawable was tapped
return true;
return true;
);
【讨论】:
【参考方案4】:final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_DOWN = 3;
这个点击监听器正在进入触摸监听器
if (event.getAction() == MotionEvent.ACTION_DOWN)
if (event.getAction() == MotionEvent.ACTION_DOWN)
if (event.getX() >= (tvFollow.getTop() - tvFollow.getCompoundDrawables()[DRAWABLE_TOP].getBounds().width()))
// your action here
return true;
【讨论】:
【参考方案5】:由于 getRaw() 和 getRight() 都返回整个屏幕坐标,如果您的视图不在屏幕的左边缘,这将不起作用。无论布局位置如何,以下解决方案都可以在任何地方使用。这是用于右侧可绘制触摸。
textView.setOnTouchListener(OnTouchListener _, event ->
if (event.action == MotionEvent.ACTION_UP)
if (event.x >= textView.width - textView.totalPaddingEnd)
<!---DO YOUR ACTIONS HERE--->
return@OnTouchListener true
true
)
PS:Kotlin 代码
【讨论】:
以上是关于仅为 TextView 复合可绘制对象实现 onClick的主要内容,如果未能解决你的问题,请参考以下文章