16

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

jamesc
  • 12,423
  • 15
  • 74
  • 113

3 Answers3

8

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.

agold
  • 6,140
  • 9
  • 38
  • 54
puff
  • 81
  • 1
  • 1
5

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.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • Great idea, thank you. Just don't seem able to check for isInTouchMode. I'm getting compilation errors – jamesc Aug 07 '11 at 10:52
  • I finally got everything hooked up but the solution has undesired effects. I get millions of clicks! The onFocusedCange event gets called millions of times. I could add a flag to only call the code to start the activity once but I really need a better solution as this event could be quite costly in performance terms. Any ideas? – jamesc Aug 07 '11 at 13:32
  • Not really: as you've observed the problem is that the first touch puts it in touch mode AND focuses it. If it wasn't focusable it would put it in touch mode and click immediately, but the focus requirement requires the extra step. You might need the flag. – Femi Aug 07 '11 at 18:18
0

You can use onTouch. This way you can handle all clicks without having to set OnFocusChangeListener.

WWJD
  • 1,104
  • 4
  • 12
  • 31