Fare in modo che un LinearLayout si comporti come un pulsante


100

Ho un LinearLayoutche ho disegnato per assomigliare a buttone contiene alcuni elementi di testo / ImageView. Vorrei che il tutto LinearLayoutagisse come una button, in particolare per dargli degli stati che sono definiti in a in modo che abbia uno sfondo diverso quando viene premuto.

Esiste un modo migliore che rendere ImageButtonassolutamente la dimensione dell'intero Layout e posizionamento?


Nel caso in cui qualcuno è alla ricerca di un modo per evidenziare un TableRow (che viene ereditato da un LinearLayout) sulla stampa (come un pulsante), vedi stackoverflow.com/a/8204768/427545
Lekensteyn

1
se qualcuno vuole ottenere una soluzione completa, controlla questo repository: github.com/shamanland/AndroidLayoutSelector c'è un clic / controllabile personalizzato LinearLayoutcome unToggleButton
Oleksii K.

Risposte:


154

Mi sono imbattuto in questo problema proprio ora. Dovrai impostare LinearLayout su cliccabile. Puoi farlo nell'XML con

android:clickable="true"

O in codice con

yourLinearLayout.setClickable(true);

Saluti!


2
La risposta di seguito è molto migliore!
Zach Sperske

2
Inoltre, se hai un elemento "cliccabile" come elemento secondario, non dimenticare di aggiungerlo android:clickable="false"per evitare che blocchi gli eventi di clic.
TheKalpit

non è necessario, l'aggiunta di un listener di clic è stato sufficiente per me e se non vuoi un listener di clic perché vorresti che qualcosa fosse cliccabile?
hmac

158

Se desideri aggiungere il comportamento di sfondo predefinito di Android per fare in modo Layoutche un "clikable" si comporti come un "clikable" View, imposta sul target Layout:

API 11+ (Android puro):

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

API 7+ (Android + AppCompat Support Library):

android:background="?attr/selectableItemBackground"

Qualsiasi API:

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

Le risposte di cui sopra sono ancora vere, ma non mi hanno aiutato ad aggiungere semplicemente lo stato dell'interfaccia utente premuto e rilasciato predefinito (come ListViewad esempio).


+1 per te, questo è ottimo se vuoi il feedback tattile dell'interfaccia utente, ma vuoi gestire da solo la logica dei clic (e non essere costretto a specificare un metodo onClickX, che è ciò che richiede Android: cliccabile)
Rick Barkhouse

2
Funziona anche con le increspature del design dei materiali. Migliore risposta.
Miro Markaravanes

3
Buona! Quando viene premuto, risulta di colore arancione / giallo come effetto premuto. Voglio cambiare il colore in verde. Come farlo?
Han Whiteking,

@HanWhiteking l'hai scoperto?
Jacob Sánchez

16

Ho usato la prima e la seconda risposta. Ma il mio layout lineare ha immagini e testo con colore di sfondo, quindi ho dovuto cambiare "sfondo" in "primo piano"

linearlayout

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

9

Per prima cosa vorrai un selettore per definire i diversi stati. Ad esempio, in un file XML:

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

Non l'ho provato, ma puoi eventualmente impostare android: background di LinearLayout su questo selettore e impostare android: clickable su true e funzionerà.

In caso contrario, puoi passare all'utilizzo di un RelativeLayout e rendere il primo elemento un pulsante con questo selettore come sfondo e fill_parent per la larghezza e l'altezza del layout. In questo caso, usa un normale pulsante e imposta android: background sul tuo selettore. Non devi inserire del testo sul tuo pulsante.


Sì, voto per l'utilizzo di un reale Button. Puoi eseguire l'override onDraw(Canvas)per fare qualsiasi cosa speciale di cui hai bisogno (ad esempio, disegnare immagini o testo all'interno del pulsante).
Dave

1
Grazie! L'impostazione dello sfondo del LinearLayout funziona e risponde agli eventi di tocco, quasi– se premo direttamente LinearLayout, il suo stato viene aggiornato. Se premo il TextView al suo interno, l'evento touch non sembra compensare il LinearLayout. Qualche idea su come eseguire l'hit-test del layout?
Jason Prado

Prova android: clickable = "false" su TextView. Non l'ho provato, ma non ho avuto problemi a fare clic su TextViews. Forse è perché il tuo TextView ha uno sfondo.
Tenfour04

Questo ha funzionato, anche se non fa il suono del clic. C'è un modo per convincerlo a farlo?
Steven

@Steven Ho appena visto il tuo vecchio commento, mi dispiace. Penso che il suono del clic sia legato all'assegnazione di un onClickListener. Avevo qualcosa con un onTouchListener e non sarebbe scattato fino a quando non avessi aggiunto anche un onClickListener (con un metodo onClick vuoto).
Tenfour04

7

Nell'applicazione su cui sto lavorando ho bisogno di creare dinamicamente un LinearLayout. In questo caso il comando

ll.setClickable(true);

non funziona come dovrebbe. Nonostante mi possa sfuggire qualcosa, sono riuscito a sfruttare setOnTouchListener per ottenere lo stesso risultato e invio il codice nel caso qualcuno avesse le stesse esigenze.

Il codice seguente crea un LinearLayout con due visualizzazioni di testo e angoli arrotondati, che cambiano colore quando viene premuto.

Innanzitutto, crea due file xml nella cartella disegnabile, uno per lo stato normale e uno per lo stato di layout lineare premuto.

Stato normale xml (drawable / round_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>

Stato premuto xml (drawable / round_edges_pressed.xml). L'unica differenza è nel colore ...

<?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>

Quindi il codice seguente fa il lavoro

Variabile globale:

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

Basta impostare questi attributi

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

5

Basta aggiungere lo sfondo attr / selectableItemBackground al layout lineare e rendere anche quel layout lineare cliccabile

esempio :

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

Questo fa sì che il layout lineare si comporti come un pulsante quando viene premuto. :)


1

Questo è stato utile, ma se vuoi mettere un colore di sfondo e rendere il layout lineare cliccabile come l'elemento dell'elenco. Imposta lo sfondo con il tuo colore preferito e imposta il colore di primo piano su? Android: attr / selectableItemBackground, imposta focusable true e clickable true

codice di esempio

   <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

Le risposte precedenti riguardavano come impostare lo sfondo predefinito nel file xml. Qui la stessa cosa nel codice:

linearLayout1.setBackgroundResource(android.R.drawable.list_selector_background);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.