onTouch和onClick没有正确触发

时间:2015-09-22 19:18:07

标签: android onclick

我有ReliveLayout和ImageView以及里面的TextView。

所以我有两个事件监听器:

  • onClick
  • onTouch

我正在使用9patch作为图片。当我使用onTouch事件onClick时根本没有触发,而onTouch也不是很好。如果我禁用onTouch并保留onClick,则会触发并更改活动。我想让onTouch和onClick一起工作。我想要:

  • 单击RelativeLayout时,它会显示所选按钮ImageView
  • 否则显示正常按钮ImageView
  • onClickListener更改活动。

继承我的代码:

StartBtn = (RelativeLayout) findViewById(R.id.StartBtn);
StartBtnImage = (ImageView) findViewById(R.id.StartBtnImage);
StartBtnText = (TextView) findViewById(R.id.StartBtnText);

StartBtn.setOnTouchListener(new TouchButton(StartBtnImage)); //Commenting this line makes the onClickListener work
StartBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        StartBtnImage.setImageResource(R.drawable.btn_selected);
        Log.d("ButtonClick", "Done");
        Intent myIntent = new Intent(MainMenu.this, Game.class);
        startActivity(myIntent);

    }
});

我的TouchButton课程:

public class TouchButton implements View.OnTouchListener {

    ImageView IV;

    public TouchButton(ImageView Image) {
        IV = Image;
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                IV.setImageResource(R.drawable.btn_selected);
                return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_OUTSIDE:
            default:
                IV.setImageResource(R.drawable.btn);
                return false;
        }
    }
}

这是我的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainMenu">

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/MainMenuBg"
    android:background="@drawable/main_menu_bg" />

<RelativeLayout
    android:layout_width="250dp"
    android:layout_height="75dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="130dp"
    android:id="@+id/StartBtn"
    android:clickable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/StartBtnImage"
        android:src="@drawable/btn" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Start"
        android:id="@+id/StartBtnText"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:singleLine="false"
        android:gravity="center|center_vertical|center_horizontal"
        android:textSize="50dp" />
</RelativeLayout>

我知道我不善于解释,所以这是一个视频: https://www.youtube.com/watch?v=PtdUsW-Dnqk

4 个答案:

答案 0 :(得分:2)

更新:由于您无法在单个视图see link上使用多个侦听器。 您可以在TouchButton.class中实现.setOnClickListener的行为。

public class TouchButton implements View.OnTouchListener {

ImageView IV;

public TouchButton(ImageView Image) {
    IV = Image;
}

public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            IV.setImageResource(R.drawable.btn_selected);
            return true;
        case MotionEvent.ACTION_UP:
            switch(v.getId()){
                case R.id.StartBtn:
                   IV.setImageResource(R.drawable.btn_selected);
                   Log.d("ButtonClick", "Done");
                   Intent myIntent = new Intent(MainMenu.this, Game.class);
                   startActivity(myIntent);
                   break;
             return true;
        case MotionEvent.ACTION_OUTSIDE:
        default:
            IV.setImageResource(R.drawable.btn);
            return false;
    }
  }
}

答案 1 :(得分:2)

是的,您可以在一个视图上使用多个侦听器(如果不可能,则会出现问题)。

基本上,视图的触摸事件会在点击事件之前触发。 如果触摸侦听器消耗事件(从onTouch返回true ),则不会调用单击侦听器。 如果从onTouch侦听器返回true,则不消耗事件(返回false ),并且将像onClick侦听器一样调用任何基础侦听器。

这是一个附加到单个视图(按钮)的两个侦听器的示例:

    btnStart = (Button) findViewById(R.id.btn_start);

    btnStart.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.d("stack", "TOUCH EVENT");
            return false;
        }
    });

    btnStart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("stack", "CLICK EVENT");
            Toast.makeText(getApplicationContext(), "start game...", Toast.LENGTH_LONG).show();
        }
    });

和布局,一个简单的按钮:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<Button
    android:id="@+id/btn_start"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="start btn"/>
</RelativeLayout>

在日志中,当您触摸按钮时,您将看到在点击事件之前写入的触摸事件,因为onTouch侦听器不会消耗该事件(返回false)并首先被调用。

我建议您阅读有关Android中触摸传播的文档,并在Dave Smith上查看有关此主题的video

最后你应该看一下xml中的小部件状态,以便在点击或关注时更改它们的外观......看看there

希望它会有所帮助。

答案 2 :(得分:0)

这是我的代码,我希望这可以解决您的问题 ` public boolean onTouch(View v,MotionEvent event){

                int index = event.getActionIndex();
                int action = event.getActionMasked();
                int pointerId = event.getPointerId(index);
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        if (mVelocityTracker == null) {
                            // Retrieve a new VelocityTracker object to watch the
                            // velocity of a motion.
                            mVelocityTracker = VelocityTracker.obtain();
                            //getrawX, getrawY
                            startX = event.getRawX();
                            startY = event.getRawY();
                            // Add a user's movement to the tracker.
                            mVelocityTracker.addMovement(event);
                        } else {
                            // Reset the velocity tracker back to its initial state.
                            mVelocityTracker.clear();
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        mVelocityTracker.addMovement(event);
                        mVelocityTracker.computeCurrentVelocity(1000);
                        velocityX = mVelocityTracker.getXVelocity(pointerId);
                        velocityY = mVelocityTracker.getXVelocity(pointerId);
                        diffX = event.getRawX() - startX;
                        diffY = event.getRawY() - startY;
                        if(Math.abs(diffX)> 10) {
                            startX = event.getRawX();
                            if (diffX < 0 && velocityX != 0) {
                                swipeLeft(diffX, velocityX);
                            } else {
                                swipeRight(diffX, velocityX);
                            }
                        }
                        if(Math.abs(diffY)> 10) {
                            startY = event.getRawY();
                            if (diffY < 0 && velocityY != 0) {
                                swipeTop(diffY, velocityY);
                            } else {
                                swipeBottom(Math.abs(diffY) / velocityY);
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if(distanceX == 0){
                            Intent intent = new Intent(context, MainActivity.class);
                            intent.putExtra("SET_ID", listSet.get(getAdapterPosition()).getId());
                            itemView.getContext().startActivity(intent);
                            break;
                        }
                    case MotionEvent.ACTION_CANCEL:
                        checkDis();
                        // Return a VelocityTracker object back to be re-used by others.
                        try {
                            mVelocityTracker.recycle();
                            mVelocityTracker = null;
                        }catch (Exception e){
                            Log.d("exeption", e.getMessage());
                        }
                        break;
                }
                return true;
            }
        });
    }
    // check action up then cancel
    //purpose: scroll to initalize status if the behind layout not been opened
    private void checkDis(){
        if(distanceX<=0 && distanceX > -200){
            scrollView(cvSetItem, 0,(long) Math.abs(distanceX)*600/150);
            distanceX = 0;
        }

    }
    private void scrollView( View v, float toX, long duration){
            // do something
    }
    private void swipeLeft(float diff, float velo) {
        distanceX += diff;
        Log.d("distance left", " " + distanceX);
        if(distanceX>-200 && distanceX <0) {
            scrollView(cvSetItem,distanceX, (long) (diff/velo));
        }else {
            distanceX = -200;
            scrollView(cvSetItem,distanceX, 0);
        }
    }
    private void swipeRight(float diff, float velo) {
        Log.d("distance right", " " + distanceX);
        distanceX+=diff;
        if(distanceX<0){
            scrollView(cvSetItem,distanceX, (long) Math.abs(diff/velo));
        }else {
            distanceX =0;
        }
    }

    private void swipeTop(float diffY, float velo) {

    }
    private void swipeBottom(float duration) {

    }`

答案 3 :(得分:0)

只需设置

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

您的touchListenerclickListener都可以正常工作