关闭

关于onTouchEvent跟OnClickListener冲突的问题

标签: androidonTouchEvenOnClickListener
1736人阅读 评论(0) 收藏 举报
分类:

最近在做一个app项目,自己学习android只有半年,做起来还是很吃力的。很多东西感觉有映像,真正用到的时候还是有很多细节不了解,又要查找资料、问大神什么的。算是自我鼓励吧,跟自己说加油!


说回正题,项目有个这样的需求。就像微信 “我” 那一栏,每项点击的时候背景改了,直到你松开手指背景才改回来并且跳到一个界面去。我按照自己的方法去做,遇到onTouchEvent跟OnClickListener冲突的问题。说白了就是只会触发onTouchEvent()方法,不会执行OnClickListener的onClick()方法。经过查找资料解决了顺便分享出来,希望大家遇到类似问题可以顺利解决。


上代码前先讲下逻辑,这样看起来比较方便。我在自定义控件类中覆写onTouchEvent()方法来跟换控件背景。点击控件时会触发MotionEvent.ACTION_DOWN事件,在这里将背景改为点击时的背景。松开手指时触发MotionEvent.ACTION_UP事件,在这里将背景改回来。最后在主界面中给组合控件设置点击监听(也就是设置OnClickListener),点击时跳到某个界面中


首先上MainActivity的代码,代码还算简单:

package com.example.test;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity implements OnClickListener{
private PersonalCustomView personal_edit_personaldata;  

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

personal_edit_personaldata = (PersonalCustomView) findViewById(R.id.personal_edit_personaldata);
personal_edit_personaldata.setOnClickListener(this);

}

@Override
public void onClick(View v) {

switch (v.getId()) {
//用户点击修改资料,跳刀修改资料界面
case R.id.personal_edit_personaldata:
Intent intent = new Intent(this, PersonalDataEditActivity.class);
startActivity(intent);

break;
}
}

接着上主界面的布局文件代码,也很简单,就是用到了自定义组合控件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:personal="http://schemas.android.com/apk/res/com.example.test"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <!-- 修改资料的布局 -->
    <com.example.test.PersonalCustomView
        android:id="@+id/personal_edit_personaldata"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        personal:personal_item_icon="@drawable/ic_launcher"
        personal:personal_item_text="修改资料" >
    </com.example.test.PersonalCustomView>


</LinearLayout>


代码很简单吧!


结下了就是自定义组合控件的代码。关于自定义组合控件这里就不说了。我有些过一篇关于自定义自定义组合控件的文章,有兴趣可以看一下<自定义组合控件>。

先上自定义组合控件的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/personal_root"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center_vertical"
    android:background="#ffffff"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/personal_item_icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="center"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="10dp"/>

    <TextView
        android:id="@+id/personal_item_text"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center_vertical"
        android:textSize="16sp" />
</LinearLayout>


自定义属性代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PersonalCustomView">
        <attr name="personal_item_icon" format="reference" />
        <attr name="personal_item_text" format="string" />
    </declare-styleable>
</resources>

 

接下来就是代码了,先上代码,在详解具体问题:

package com.example.test;

import com.example.test.R;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.View.OnTouchListener;

public class PersonalCustomView extends LinearLayout implements OnTouchListener {
private ImageView personal_item_icon;
private TextView personal_item_text;
private LinearLayout personal_root;

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();


switch (action) {
// 当用户点击了该自定义组合控件时,跟换背景
case MotionEvent.ACTION_DOWN:
personal_root.setBackgroundColor(Color.rgb(64, 161, 255));
break;
// 当用户松开手时将背景设置回原来的样子
case MotionEvent.ACTION_UP:
personal_root.setBackgroundColor(Color.rgb(255, 255, 255));
break;
}
return false;
}

public void initView(Context context) {
View.inflate(context, R.layout.customview_personal, this).setOnTouchListener(this); //.....
personal_item_icon = (ImageView) this
.findViewById(R.id.personal_item_icon);
personal_item_text = (TextView) this
.findViewById(R.id.personal_item_text);
personal_root = (LinearLayout) this.findViewById(R.id.personal_root);
}
public PersonalCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.PersonalCustomView);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.PersonalCustomView_personal_item_icon:
int resource = a.getResourceId(i, 0);
personal_item_icon.setImageResource(resource);
break;
case R.styleable.PersonalCustomView_personal_item_text:
// 默认颜色设置为黑色
String title = a.getString(i);
personal_item_text.setText(title);
break;
}
}
}
}


红色部分代码是问题的关键,点击事件触发顺序:

Touch事件的ACTION_DOWN ->  ACTION_UP  ->  OnClick/OnLongClick
onTouchEvent()方法中,如果事件返回true,就会截断事件的下传,通俗点之后的ACTION_UP以及OnClick/OnLongClick就不会在触发了。如果返回false,应该是可以解决问题的,但是经测试,上面的红色代码实现应有的功能。有几种方法可以解决问题。

1、而onTouchEvent()中执行super.onTouchEvent(event)可以解决问题。

@Override
public boolean onTouchEvent(MotionEvent event) {

super.onTouchEvent(event);
int action = event.getAction();


switch (action) {
// 当用户点击了该自定义组合控件时,跟换背景
case MotionEvent.ACTION_DOWN:
personal_root.setBackgroundColor(Color.rgb(64, 161, 255));
break;
// 当用户松开手时将背景设置回原来的样子
case MotionEvent.ACTION_UP:
personal_root.setBackgroundColor(Color.rgb(255, 255, 255));
break;
}
return false;
}

2、不用onTouchEvent(),而用onTouch()

@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
// 当用户点击了该自定义组合控件时,跟换背景
case MotionEvent.ACTION_DOWN:
personal_root.setBackgroundColor(Color.rgb(64, 161, 255));
break;

// 当用户松开手时将背景设置回原来的样子
case MotionEvent.ACTION_UP:
personal_root.setBackgroundColor(Color.rgb(255, 255, 255));
break;
}

return false;
}

3、自定义组合控件提供调用接口,在接口中跳转界面

类中添加代码:

private PersonalActionUpListener listener;
//点击松开的监听器
public interface PersonalActionUpListener{

//松开手指的回调方法
public void personalCallBack(View v);
}

//设置监听器
public void setListener(PersonalActionUpListener listener){
this.listener = listener;

}

然后onTouchEvent中调用回调:

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();


switch (action) {
// 当用户点击了该自定义组合控件时,跟换背景
case MotionEvent.ACTION_DOWN:
personal_root.setBackgroundColor(Color.rgb(64, 161, 255));
break;


// 当用户松开手时将背景设置回原来的样子

case MotionEvent.ACTION_UP:
personal_root.setBackgroundColor(Color.rgb(255, 255, 255));
listener.personalCallBack(this);
break;
}

return true;
}

最后在主界面中调用setListener()并实现PersonalActionUpListener接口:代码已经在上面给出


关于onTouchEvent跟OnClickListener冲突的问题就说到这里。

1
1

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18270次
    • 积分:337
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:17篇
    • 译文:0篇
    • 评论:0条
    文章分类