Whi*_*ear 10 android ontouchlistener android-button onclicklistener
执行以下操作后,我的按钮保持在突出显示状态时出现问题:
public class MainActivity extends AppCompatActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton button = (AppCompatButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Test", "calling onClick");
}
});
button.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
v.performClick();
Log.d("Test", "Performing click");
return true;
}
}
return false;
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
关于上面的代码,在使用它时,我希望按钮单击由触摸来处理,并且通过返回“ true”,处理应在touchListener处停止。
但这种情况并非如此。即使正在调用单击,按钮仍保持突出显示状态。
我得到的是:
Test - calling onClick
Test - Performing click
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我使用以下代码,则单击该按钮,并打印相同的内容,但该按钮最终不会停留在突出显示状态:
Test - calling onClick
Test - Performing click
Run Code Online (Sandbox Code Playgroud)
我对触摸事件的响应者链有些困惑。我的猜测是:
1)TouchListener
2)ClickListener
3)父视图
有人也可以确认吗?
ami*_*phy 10
这样的自定义不需要程序上的修改。您可以简单地在xml文件中进行操作。首先,完全删除setOnTouchListener您提供的方法onCreate。接下来,在res/color目录中定义选择器颜色,如下所示。(如果目录不存在,请创建它)
分辨率/颜色/button_tint_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#e0f47521" android:state_pressed="true" />
<item android:color="?attr/colorButtonNormal" android:state_pressed="false" />
</selector>
Run Code Online (Sandbox Code Playgroud)
现在,将其设置为按钮的app:backgroundTint属性:
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:backgroundTint="@color/button_tint_color" />
Run Code Online (Sandbox Code Playgroud)
从总体上看,触摸事件的流程从开始Activity,然后向下到布局(从父布局到子布局),然后到视图。(下图为LTR流程)
当触摸事件到达目标视图,该视图可以处理随后事件决定将它传递给现有的布局/活性或不(返回false的true在onTouch法)。(上图中的RTL流程)
现在,让我们看一下View的源代码,以更深入地了解触摸事件流。通过查看的实现dispatchTouchEvent,我们将看到,如果将设置OnTouchListener为视图,然后返回true其onTouch方法,onTouchEvent则不会调用该视图的。
public boolean dispatchTouchEvent(MotionEvent event) {
// removed lines for conciseness...
boolean result = false;
// removed lines for conciseness...
if (onFilterTouchEventForSecurity(event)) {
// removed lines for conciseness...
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) { // <== right here!
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
// removed lines for conciseness...
return result;
}
Run Code Online (Sandbox Code Playgroud)
现在,查看onTouchEvent事件操作为的方法MotionEvent.ACTION_UP。我们看到执行点击操作就在那里发生。所以,回到true在OnTouchListener的onTouch,因此没有要求的onTouchEvent,将导致不调用OnClickListener的onClick。
还有一个不调用的问题onTouchEvent,它与按下状态和您在问题中提到的有关。正如我们在下面的代码块中看到的那样,它在运行时有一个UnsetPressedState调用实例。不调用的结果是视图卡在了按下状态,并且其可绘制状态不变。 setPressed(false)setPressed(false)
public boolean onTouchEvent(MotionEvent event) {
// removed lines for conciseness...
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
// removed lines for conciseness...
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
// removed lines for conciseness...
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
// removed lines for conciseness...
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClickInternal();
}
}
}
if (mUnsetPressedState == null) {
mUnsetPressedState = new UnsetPressedState();
}
if (prepressed) {
postDelayed(mUnsetPressedState,
ViewConfiguration.getPressedStateDuration());
} else if (!post(mUnsetPressedState)) {
// If the post failed, unpress right now
mUnsetPressedState.run();
}
// removed lines for conciseness...
}
// removed lines for conciseness...
break;
// removed lines for conciseness...
}
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
private final class UnsetPressedState implements Runnable {
@Override
public void run() {
setPressed(false);
}
}
Run Code Online (Sandbox Code Playgroud)
关于以上描述,您可以通过调用setPressed(false)自己来更改事件动作为的可绘制状态来更改代码MotionEvent.ACTION_UP:
button.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
// v.invalidate();
v.setPressed(false);
v.performClick();
Log.d("Test", "Performing click");
return true;
}
}
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
274 次 |
| 最近记录: |