Search code examples
androidandroid-touch-event

onKeyUp/onKeyDown doesn't work in Anroid after overriding?


I tried to rewrite these three methods in order to print out the log on the console, but after running the program, I found that there is only a log about method onTouchEvent() after clicking the button. The other two methods:onKeyDown()andonKeyUp() don't seem to work. I am a newcomer to Android, I am very grateful for any help. Does this mean that onKeyDown()andonKeyUp() are override incorrectly? The following is the MyButton class:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;


import androidx.appcompat.widget.AppCompatButton;

public class MyButton extends AppCompatButton {

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private static String TAG = "TAG_";

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        super.onKeyDown(keyCode, event);
        Log.i(TAG, "onKeyDown is been called");
        return true;
    }


    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        super.onKeyUp(keyCode, event);

        Log.i(TAG, "onKeyUp is been called");
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        Log.i(TAG, "onTouchEvent is been called");
        return true;

    }
}

Here are activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

    <com.example.learncallback.MyButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"/>
</RelativeLayout>

Solution

  • A KeyEvent is a signal from an IME or a physical keyboard to a view. If you want to handle touch events, you should override onTouchEvent(MotionEvent) - which you already did - to receive touch information.

    I assume you want to track whether the view is being touched or not. For that you need to parse the MotionEvent passed to onTouchEvent because the framework will call this method whenever a touch event occurs on that view (as long as the parent doesn't intercept it using onInterceptTouchEvent).

    React to touch events in onTouchEvent using:

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                // View being pressed down on
            case MotionEvent.ACTION_MOVE:
                // View being pressed down on
            case MotionEvent.ACTION_UP:
                // View not touched anymore
            // ...
        }
        return true;
    }
    

    Note that you will receive touch events other that MotionEvent.ACTION_DOWN only if you return true from the initial call to onTouchEvent.