105
votes

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?

10
In case someone is looking for a way to highlight a TableRow (which is inherited from a LinearLayout) on press (like a Button), see stackoverflow.com/a/8204768/427545 - Lekensteyn
if somebody wants to get full solution, check this repository: github.com/shamanland/AndroidLayoutSelector there is custom clickable/checkable LinearLayout like a ToggleButton - Oleksii K.

10 Answers

161
votes

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).

159
votes

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);

Cheers!

16
votes

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"
9
votes

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.

7
votes

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;
                }
  });           
6
votes

Just set these attributes

<LinearLayout 
    ...
    android:background="@android:drawable/btn_default" 
    android:clickable="true"
    android:focusable="true"
    android:onClick="onClick"
    >
...
</LinearLayout>
5
votes

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. :)

1
votes

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"
        />
0
votes

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);
0
votes

Just Use This:

android:foreground="?attr/selectableItemBackground"