Home » Android » Android – automatic overlay touch down / highlighted imagebutton states

Android – automatic overlay touch down / highlighted imagebutton states

Posted by: admin May 14, 2020 Leave a comment

Questions:

Is it possible using an ImageButton to have touch down and highlighted states, without the need for 2 more image resources on Android (6 more, considering h/m/ldpi)? I’m basically looking for behavior similar to iOS where the OS can put an semi-alpha overlay on the touch down state of a button.

I’ve tried using setColorFilter(0xFF000000, Mode.MULTIPLY) in the onTouch listener, and the result was pretty close to what I was after – but I’m not sure the best way of the state handling to achieve this:

i.e.

  1. touchDown event -> Change color overlay.
  2. touchUp event -> remove color overlay, and perform button action.

Is there a better way… Or can someone help fill in the gaps?

I don’t want to use separate images for a couple of reasons – it’s an iPhone port for which I don’t have the appropriate assets yet, and would require more designer time considering I’ve got the low/medium/high creatives to consider.

Thanks!

How to&Answers:

If you are happy with the setColorFilter(0xFF000000, Mode.MULTIPLY) then how about making yourself a custom component that extends ImageButton?

Something like:

(Sorry I haven’t had a chance to test this)

package com.example;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;

public class IosImageButton extends ImageButton implements OnTouchListener
{

    public IosImageButton(final Context context, final AttributeSet attrs, final int defStyle)
    {
        super(context, attrs, defStyle);
        this.init();
    }

    public IosImageButton(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
        this.init();
    }

    public IosImageButton(final Context context)
    {
        super(context);
        this.init();
    }

    private void init()
    {
        super.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(final View view, final MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                // touchDown event -> Change color overlay. goes here
                // e.g. this.setColorFilter(0xFF000000, Mode.MULTIPLY);
                return true;

            case MotionEvent.ACTION_UP:
                // touchUp event -> remove color overlay, and perform button action.
                // e.g. this.setColorFilter(0xFF000000, Mode.MULTIPLY);
                return true;

            default:
                return false;
        }
    }
}

Then the view.xml

<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.IosImageButton 
        <!-- add standard ImageButton setting here -->
        />

</RelativeLayout>

Answer:

Do not use touch events to try to show the appropriate states on something like this. You will inevitably get it partially wrong. The framework does a lot of work to detect user intent (ex: the user touched down but then slid off his finger) taking into account things like slop etc.

For ImageButton, you can use the src attribute to show the icon and then use an appropriate StateListDrawable as the background.

I have created a quick project for you to see on Github

Note that the touch states are shown in the background, not the foreground. See the discussion on Google+ on why Android framework engineers think touch feedback should be behind, not in front. If you still want the drawable to be in front, see my post on my blog