110

I have a LinearLayout that I've styled to look like a button, and it contains a few text/ImageView elements. I would like to make the whole LinearLayout act like a button, in particular to give it states that are defined in a so it has a different background when it is pressed.

Is there a better way than making an ImageButton the size of the whole Layout and positioning absolutely?

Hello World
  • 2,764
  • 1
  • 11
  • 23
Jason Prado
  • 1,504
  • 2
  • 12
  • 21
  • In case someone is looking for a way to highlight a TableRow (which is inherited from a LinearLayout) on press (like a Button), see http://stackoverflow.com/a/8204768/427545 – Lekensteyn Apr 05 '12 at 20:32
  • 1
    if somebody wants to get full solution, check this repository: https://github.com/shamanland/AndroidLayoutSelector there is custom clickable/checkable ```LinearLayout``` like a ```ToggleButton``` – Oleksii K. Oct 17 '13 at 12:19

10 Answers10

163

If you want add the Android default background behavior to make a Layout acts like a "clikable" View, set on the targeted Layout:

API 11+ (Pure Android):

android:background="?android:attr/selectableItemBackground"

API 7+ (Android + AppCompat Support Library):

android:background="?attr/selectableItemBackground"

Any API:

android:background="@android:drawable/list_selector_background"

Answers above still true but didn't help me for just add the default pressed and released UI state (like in a ListView for instance).

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
FabiF
  • 2,796
  • 2
  • 18
  • 27
163

I ran into this problem just now. You'll have to set the LinearLayout to clickable. You can either do this in the XML with

android:clickable="true"

Or in code with

yourLinearLayout.setClickable(true);
starball
  • 20,030
  • 7
  • 43
  • 238
Rockmaninoff
  • 3,573
  • 5
  • 34
  • 35
  • 2
    The answer below is much better! – Zach Sperske Aug 11 '15 at 11:31
  • 3
    Also, if you have a "clickable" element as its child, don't forget to add `android:clickable="false"` to it to prevent it from blocking click events. – TheKalpit Mar 04 '17 at 12:19
  • not necessary, adding a click listener was enough for me and if you don't want a click listener why would you want something to be clickable? – hmac May 10 '18 at 10:31
16

I used the first and second answer. But my linearlayout has images and text with background color, so i had to change "background" to "foreground"

linearlayout

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Roman
  • 318
  • 2
  • 8
9

First you'll want a selector to define the different states. For example, in an XML file:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/button_pressed"
          android:state_pressed="true" />
    <item android:drawable="@drawable/button_focused"
          android:state_focused="true" />
    <item android:drawable="@drawable/button_normal" />
</selector>

I haven't tried it, but you can possibly set the LinearLayout's android:background to this selector, and set android:clickable to true and it'll work.

If it doesn't, you could switch to using a RelativeLayout, and make the first element a button with this selector as the background and fill_parent for its layout width and height. In this case, just use a regular Button and set android:background to your selector. You don't have to put text on your button.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • Yeah, I vote for using an actual `Button`. You can override `onDraw(Canvas)` to do whatever special things you need (i.e., draw images or text within the button). – Dave Apr 05 '11 at 03:15
  • 1
    Thanks! Setting the background of the LinearLayout works and it responds to touch events, almost– if I press the LinearLayout directly, its state is updated. If I press the TextView inside it, the touch event doesn't seem to make it up to the LinearLayout. Any idea how to make the Layout hit-test? – Jason Prado Apr 05 '11 at 18:37
  • Try android:clickable="false" on the TextView. Haven't tried this, but I haven't had a problem with clicking through TextViews. Maybe it's because your TextView has a background. – Tenfour04 Apr 07 '11 at 11:37
  • This did the trick, although it doesn't make the click sound. Is there a way to get it to do that? – Steven Nov 08 '13 at 19:53
  • @Steven Just saw your old comment, sorry. I think the click sound is tied to having an onClickListener assigned. I had something with an onTouchListener and it wouldn't click until I also added an onClickListener (with an empty onClick method). – Tenfour04 Jun 24 '14 at 12:39
7

In the application I am working I need to create a LinearLayout dynamically. In this case the command

ll.setClickable(true);

is not working as supposed to do. Although I may miss something, I managed to exploit setOnTouchListener to get the same result and I submit the code in case anyone has the same needs.

The following code creates a LinearLayout with two textviews and round corners, changing color when pressed.

First, create two xml files in drawable folder, one for normal and one for pressed linearlayout state.

Normal state xml (drawable/rounded_edges_normal.xml)

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />
            <corners android:radius="7dp" />
            <padding android:left="5dip" android:top="5dip" android:right="5dip" android:bottom="5dip" />
        </shape>
    </item>
    <item android:bottom="3px">
        <shape android:shape="rectangle">
            <solid android:color="#F1F1F1" />
            <corners android:radius="7dp" />
        </shape>
    </item>
</layer-list>

Pressed state xml (drawable/rounded_edges_pressed.xml). The only difference is in the color...

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />
            <corners android:radius="7dp" />
            <padding android:left="5dip" android:top="5dip" android:right="5dip" android:bottom="5dip" />
        </shape>
    </item>
    <item android:bottom="3px">
        <shape android:shape="rectangle">
            <solid android:color="#add8e6" />
            <corners android:radius="7dp" />
        </shape>
    </item>
</layer-list>

Then the following code does the job

Global variable:

public int layoutpressed = -1;

In onCreate():

// Create some textviews to put into the linear layout...
TextView tv1 = new TextView(this);
TextView tv2 = new TextView(this);
tv1.setText("First Line");
tv2.setText("Second Line");

// LinearLayout definition and some layout properties...
final LinearLayout ll = new LinearLayout(context);
ll.setOrientation(LinearLayout.VERTICAL);

// it is supposed that the linear layout will be in a table.
// if this is not the case for you change next line appropriately...
ll.setLayoutParams(new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

ll.setBackgroundResource(R.drawable.rounded_edges_normal);
ll.addView(tv1);
ll.addView(tv2);
ll.setPadding(10, 10, 10, 10);
// Now define the three button cases
ll.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View arg0, MotionEvent arg1) {
                if (arg1.getAction()==MotionEvent.ACTION_DOWN){
                        ll.setBackgroundResource(R.drawable.rounded_edges_pressed);
                        ll.setPadding(10, 10, 10, 10);
                        layoutpressed = arg0.getId();
                }
                else if (arg1.getAction()== MotionEvent.ACTION_UP){
                        ll.setBackgroundResource(R.drawable.rounded_edges_normal);
                        ll.setPadding(10, 10, 10, 10);
                        if(layoutpressed == arg0.getId()){
                            //  ...........................................................................
                            // Code to execute when LinearLayout is pressed...
                            //  ........................................................................... 
                     }
          }
          else{
                ll.setBackgroundResource(R.drawable.rounded_edges_showtmimata);
                ll.setPadding(10, 10, 10, 10);
                layoutpressed = -1;
          }
          return true;
                }
  });           
ᴛʜᴇᴘᴀᴛᴇʟ
  • 4,466
  • 5
  • 39
  • 73
Epaminondas
  • 818
  • 9
  • 14
6

Just set these attributes

<LinearLayout 
    ...
    android:background="@android:drawable/btn_default" 
    android:clickable="true"
    android:focusable="true"
    android:onClick="onClick"
    >
...
</LinearLayout>
Daniel De León
  • 13,196
  • 5
  • 87
  • 72
5

Just add background attr/selectableItemBackground to linear layout and also make that linearlayout clickable

example :

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linear1"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true">

That's make linearlayout act like button when it pressed. :)

Exel Staderlin
  • 535
  • 7
  • 10
3

Just Use This:

android:foreground="?attr/selectableItemBackground"
Iman Marashi
  • 5,593
  • 38
  • 51
1

This was helpful but if you want to put a background color and make linear layout clickable like the list item. Set the background with your preferred color and set foreground color to ?android:attr/selectableItemBackground, set focusable true, and clickable true

sample code

   <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:background="#FF0"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
         android:paddingTop="10dp"
        android:onClick="onClickMethod"
        android:clickable="true"
        android:focusable="true"
        android:foreground="?android:attr/selectableItemBackground"
        />
Jebjosh
  • 83
  • 8
0

Previous aswers was about how to set default background in xml file. Here same thing in code:

linearLayout1.setBackgroundResource(android.R.drawable.list_selector_background);
yuliskov
  • 1,379
  • 15
  • 16