Java 自定义视图 ... 覆盖 onTouchEvent 但不覆盖 performClick
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27462468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom view ... overrides onTouchEvent but not performClick
提问by peter.petrov
I get this warning (from the question title) in a custom Android view I am developing.
我在我正在开发的自定义 Android 视图中收到此警告(来自问题标题)。
Why do I get warned? What's the logic behind it i.e. why is it a good
practice to also override performClick
when you override onTouchEvent
?
为什么我会收到警告?它背后的逻辑是什么,即为什么在您覆盖时
也覆盖是一个好习惯?performClick
onTouchEvent
回答by Jawad Zeb
This warning tells you to override performClick
此警告告诉您覆盖 performClick
@Override
public boolean performClick() {
// Calls the super implementation, which generates an AccessibilityEvent
// and calls the onClick() listener on the view, if any
super.performClick();
// Handle the action for the custom click here
return true;
}
But it is not compulsory. As I have created a custom knobView and it is working quite good where I am also facing this warning.
但这不是强制性的。因为我已经创建了一个自定义的旋钮视图并且它在我也面临这个警告的地方工作得很好。
回答by Abandoned Cart
The onTouchEvent
is not called by some Accessibility services, as explained by clicking the "more..." link in the warning details.
该onTouchEvent
不会被一些辅助服务调用,如通过点击报警细节“更多...”链接解释。
It recommends that you override performClick
for your desired action, or at least override it alongside your onTouchEvent
.
它建议您覆盖performClick
所需的操作,或者至少覆盖它与您的onTouchEvent
.
If your code is more fitting for the touch event, you can use something similar to:
如果您的代码更适合触摸事件,您可以使用类似于以下内容的内容:
@Override
public boolean performClick() {
if (actionNotAlreadyExecuted) {
MotionEvent myEvent = MotionEvent.obtain(long downTime, long eventTime, int action, float x, float y, int metaState);
onTouch(myView, myEvent);
}
return true; // register it has been handled
}
More information on accessing touch events through code is available at trigger ontouch event programmatically
有关通过代码访问触摸事件的更多信息,请参见以编程方式触发 ontouch 事件
回答by Suragch
What's the purpose?
目的是什么?
In some of the other answers you can see ways to make the warning go away, but it is important to understand why the system wants you to override performClick()
in the first place.
在其他一些答案中,您可以看到使警告消失的方法,但重要的是要了解系统首先要您覆盖的原因performClick()
。
There are millions of blind people in the world. Maybe you don't normally think about them much, but you should. They use Android, too. "How?" you might ask. One important way is through the TalkBackapp. It is a screen reader that gives audio feedback. You can turn it on in your phone by going to Settings > Accessibility > TalkBack. Go through the tutorial there. It is really interesting. Now try to use your app with your eyes closed. You'll probably find that your app is extremely annoying at best and completely broken at worst. That's a fail for you and a quick uninstall by anyone's who's visually impaired.
世界上有数以百万计的盲人。也许您通常不会考虑太多,但您应该考虑。他们也使用安卓。“如何?” 你可能会问。一种重要的方式是通过TalkBack应用程序。它是一个提供音频反馈的屏幕阅读器。您可以通过转到“设置”>“辅助功能”>“TalkBack”在手机中打开它。通过那里的教程。这真的很有趣。现在尝试闭上眼睛使用您的应用程序。您可能会发现您的应用充其量是非常烦人的,最坏的情况是完全损坏。这对您来说是失败的,任何有视力障碍的人都可以快速卸载。
Watch this excellent video by Google for an introduction into making your app accessible.
观看 Google 制作的这段精彩视频,了解如何让您的应用易于访问。
How to override performClick()
如何覆盖 performClick()
Let's look at a example custom view to see how overriding performClick()
actually works. We'll make a simple missile launching app. The custom view will be the button to fire it.
让我们看一个示例自定义视图,看看覆盖performClick()
实际上是如何工作的。我们将制作一个简单的导弹发射应用程序。自定义视图将是触发它的按钮。
It sounds a lot better with TalkBack enabled, but animated gifs don't allow audio, so you will just have to try it yourself.
启用 TalkBack 听起来好多了,但动画 gif 不允许音频,所以你只需要自己尝试。
Code
代码
activity_main.xml
活动_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<net.example.customviewaccessibility.CustomView
android:layout_width="200dp"
android:layout_height="200dp"
android:contentDescription="Activate missile launch"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Notice that I set the contentDescription
. This allows TalkBack to read out what the custom view is when the user feels over it.
请注意,我设置了contentDescription
. 这允许 TalkBack 在用户感觉到自定义视图时读出它是什么。
CustomView.java
自定义视图.java
public class CustomView extends View {
private final static int NORMAL_COLOR = Color.BLUE;
private final static int PRESSED_COLOR = Color.RED;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setBackgroundColor(NORMAL_COLOR);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setBackgroundColor(PRESSED_COLOR);
return true;
case MotionEvent.ACTION_UP:
setBackgroundColor(NORMAL_COLOR);
// For this particular app we want the main work to happen
// on ACTION_UP rather than ACTION_DOWN. So this is where
// we will call performClick().
performClick();
return true;
}
return false;
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
@Override
public boolean performClick() {
super.performClick();
launchMissile();
return true;
}
private void launchMissile() {
Toast.makeText(getContext(), "Missile launched", Toast.LENGTH_SHORT).show();
}
}
Notes
笔记
- The documentationalso uses an
mDownTouch
variable which appears to be used to filter out extra touch up events, but since it isn't well explained or strictly necessary for our app, I left it out. If you make a real missile launcher app, I suggest you look more into this. - The primary method that launches the missile (
launchMissile()
) is just called fromperformClick()
. Be careful not to call it twice if you also have it inonTouchEvent
. You will need to decide exactly how and when to call your business logic method depending on the specifics of your custom view. Don't override
performClick()
and then do nothing with it just to get rid of the warning. If you want to ignore the millions of blind people in the world, then you can suppress the warning. At least that way you are honest about your heartlessness.@SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { ... }
- 该文档还使用了一个
mDownTouch
变量,该变量似乎用于过滤掉额外的修饰事件,但由于它没有得到很好的解释或对我们的应用程序来说是绝对必要的,因此我将其排除在外。如果你制作一个真正的导弹发射器应用程序,我建议你多看看这个。 - 发射导弹 (
launchMissile()
)的主要方法只是从 调用performClick()
。如果您也有它,请注意不要两次调用它onTouchEvent
。您需要根据自定义视图的具体情况准确决定调用业务逻辑方法的方式和时间。 不要
performClick()
为了摆脱警告而覆盖,然后什么都不做。如果你想忽略世界上数百万的盲人,那么你可以压制警告。至少这样你就可以诚实地对待自己的无情。@SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { ... }