Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android button - How to set focusable to true and still accept onClick listener on first click?

Tags:

android

UPDATE

I've solved the clicking issue by removing the two focusable lines from the button style and using the onClick event handler to call requestFocusFromTouch();

Unfortunately I'm left with an issue that requestFocusFromTouch() focuses the wrong button. It always focuses the first button not the button I call the method on. Is this an android bug or expected behaviour and what I can I do for a work around?

The code now looks like this for the onClick event

public void onClick(View v) {
    switch (v.getId()) {
            case R.id.btn_home:
                Intent i = new Intent(this, QuizMenu.class);
                startActivity(i);
                v.requestFocusFromTouch();
            break;
            case R.id.btn_support:
                Intent i1 = new Intent(this, Support.class);
                startActivity(i1);
                v.requestFocusFromTouch();
                View btnSupport = findViewById(R.id.btn_support);
                btnSupport.setSelected(true);
                btnSupport.requestFocusFromTouch();
            break;
            // More buttons go here (if any) ...
    }
}

END OF UPDATE

I have an android button that has the following style

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MnuBtnStyle">
        <item name="android:ellipsize">marquee</item>
        <item name="android:scrollHorizontally">true</item>
        <item name="android:focusable">true</item>
        <item name="android:focusableInTouchMode">true</item>
        <item name="android:singleLine">true</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_marginTop">1dip</item> 
        <item name="android:layout_marginBottom">1dip</item>
        <item name="android:textSize">10dp</item>
        <item name="android:layout_weight">1</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>

I have an on click listener that looks like this

public void onClick(View v) {
    switch (v.getId()) {
            case R.id.btn_home:
                Intent i = new Intent(this, HomeScreen.class);
                startActivity(i);
            break;
            // More buttons go here ...
    }
}

I have an image on the button and the selector looks like this

<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
        android:drawable="@drawable/ic_tab_home_pressed" /> <!-- pressed -->
    <item android:state_focused="true"
        android:drawable="@drawable/ic_tab_home_pressed" /> <!-- pressed -->
    <item android:drawable="@drawable/ic_tab_home_unpressed" /> <!-- default/unchecked -->
</selector>

The layout that uses the button and the button looks like this

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="horizontal"
      android:id="@+id/top_menu_bar"
      android:layout_marginTop="2dip" 
      android:padding="0dip"
      android:background="@android:drawable/bottom_bar"
      android:layout_alignParentTop="true"
      android:gravity="top"
      android:layout_height="@dimen/menu_bar_height"
      android:layout_width="fill_parent">
      <Button
          android:id="@+id/btn_home"
          android:text="@string/btn_home"
          android:drawableTop="@drawable/home_button"
          style="@style/MnuBtnStyle"
      />
...

there are other buttons and this layout is acting as a top menu bar that is included in whatever layout needs it.

The onClick event for the button is only fired on second click of the button due to the focusable lines.

        <item name="android:focusable">true</item>
        <item name="android:focusableInTouchMode">true</item>

The first click sets focus on the button then the second click fires the onClick event listener I need to combine the two together so that the first click sets focus AND fires the onClick event listener. Can this be done?

If I remove the two focusable lines the buttons behave normally but I want to show that the button is focused and I want the scrolling text inside the button that <item name="android:ellipsize">marquee</item> gives me

Any ideas greatly appreciated

like image 577
jamesc Avatar asked Aug 07 '11 04:08

jamesc


2 Answers

you can do like this in onClick(View v):

.....
v.setFocusableInTouchMode(true);
v.requestFocus();
v.setFocusableInTouchMode(false);
.....//the others

so, v gets focus and you can do something in onClick() through setFocusableInTouchMode(false), it can accept onClick at first touch.

like image 85
puff Avatar answered Oct 31 '22 20:10

puff


You might need to use an OnFocusChangeListener and then check if the focus event happened when the screen was in touch mode: if it did then it was a user click, otherwise it was from the trackball/trackpad.

like image 5
Femi Avatar answered Oct 31 '22 21:10

Femi