Tworzenie LinearLayout działa jak Button


100

Mam LinearLayoutże mam stylem wyglądać jak buttoni zawiera kilka elementów text / ImageView. Chciałbym, żeby cały LinearLayoutakt wyglądał jak a button, w szczególności aby nadać mu stany zdefiniowane w a, aby po naciśnięciu miał inne tło.

Czy jest lepszy sposób niż ImageButtoncałkowite określenie rozmiaru całego układu i pozycjonowanie?


W przypadku, gdy ktoś szuka sposobu, aby podświetlić TableRow (która jest dziedziczona z LinearLayout) na prasie (jak przycisk), patrz stackoverflow.com/a/8204768/427545
Lekensteyn

1
jeśli ktoś chce uzyskać pełne rozwiązanie, sprawdź to repozytorium: github.com/shamanland/AndroidLayoutSelector jest niestandardowy klikalny / checkable LinearLayoutjak aToggleButton
Oleksii K.

Odpowiedzi:


154

Właśnie napotkałem ten problem. Musisz ustawić LinearLayout tak, aby był klikalny. Możesz to zrobić w XML za pomocą

android:clickable="true"

Lub w kodzie z

yourLinearLayout.setClickable(true);

Twoje zdrowie!


2
Odpowiedź poniżej jest znacznie lepsza!
Zach Sperske,

2
Ponadto, jeśli masz element „klikalny” jako element podrzędny, nie zapomnij go dodać android:clickable="false", aby zapobiec blokowaniu kliknięć.
TheKalpit

nie jest to konieczne, wystarczyło mi dodanie odbiornika kliknięć, a jeśli nie chcesz odbiornika kliknięć, dlaczego miałbyś chcieć, aby coś było klikalne?
hmac

158

Jeśli chcesz dodać domyślne zachowanie systemu Android w tle, aby Layoutdziałał jak „klikalny” View, ustaw na docelowym Layout:

API 11+ (czysty Android):

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

API 7+ (biblioteka wsparcia Android + AppCompat):

android:background="?attr/selectableItemBackground"

Dowolny interfejs API:

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

Odpowiedzi powyżej są nadal prawdziwe, ale nie pomogły mi po prostu dodać domyślny stan wciśniętego i zwolnionego interfejsu użytkownika (jak ListViewna przykład).


+1 dla ciebie, to świetnie, jeśli chcesz uzyskać informacje zwrotne od interfejsu użytkownika, ale chcesz samodzielnie obsługiwać logikę kliknięcia (i nie być zmuszanym do określania metody onClickX, której wymaga android: klikalne)
Rick Barkhouse

2
Działa to również w przypadku zmarszczek Material Design. Najlepsza odpowiedź.
Miro Markaravanes

3
Dobry! Po naciśnięciu zmienia kolor na pomarańczowy / żółty jako efekt wytłoczenia. Chcę zmienić kolor na zielony. Jak to zrobić?
Han Whiteking,

@HanWhiteking czy się dowiedziałeś?
Jacob Sánchez

16

Użyłem pierwszej i drugiej odpowiedzi. Ale mój układ liniowy zawiera obrazy i tekst z kolorem tła, więc musiałem zmienić „tło” na „pierwszy plan”

układ liniowy

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

9

Najpierw będziesz chciał, aby selektor definiował różne stany. Na przykład w pliku 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>

Nie próbowałem tego, ale prawdopodobnie możesz ustawić android: background LinearLayout na ten selektor i ustawić android: klikalne na true i zadziała.

Jeśli tak się nie stanie, możesz przełączyć się na używanie RelativeLayout i ustawić pierwszy element jako przycisk z tym selektorem jako tłem i fill_parent dla jego szerokości i wysokości układu. W takim przypadku użyj zwykłego przycisku i ustaw android: background na swój selektor. Nie musisz umieszczać tekstu na swoim przycisku.


Tak, głosuję za użyciem rzeczywistego Button. Możesz nadpisać, onDraw(Canvas)aby zrobić wszystko, czego potrzebujesz (np. Narysować obrazy lub tekst w przycisku).
Dave,

1
Dzięki! Ustawienie tła LinearLayout działa i reaguje na zdarzenia dotykowe, prawie - jeśli bezpośrednio naciśnę LinearLayout, jego stan jest aktualizowany. Jeśli naciśnę wewnątrz TextView, zdarzenie touch nie wydaje się nadawać do LinearLayout. Masz jakiś pomysł, jak wykonać test trafień układu?
Jason Prado,

Wypróbuj android: clickable = "false" w TextView. Nie próbowałem tego, ale nie miałem problemu z klikaniem przez TextViews. Może dlatego, że Twój TextView ma tło.
Tenfour04,

To załatwiło sprawę, chociaż nie wydaje dźwięku kliknięcia. Czy jest sposób, aby to zrobić?
Steven

@Steven Właśnie zobaczyłem twój stary komentarz, przepraszam. Myślę, że dźwięk kliknięcia jest powiązany z przypisaniem onClickListener. Miałem coś z onTouchListener i nie kliknęło, dopóki nie dodałem również onClickListener (z pustą metodą onClick).
Tenfour04

7

W aplikacji, w której pracuję, muszę dynamicznie utworzyć LinearLayout. W tym przypadku polecenie

ll.setClickable(true);

nie działa tak, jak powinien. Chociaż mogę coś przeoczyć, udało mi się wykorzystać setOnTouchListener, aby uzyskać ten sam wynik i przesyłam kod na wypadek, gdyby ktoś miał takie same potrzeby.

Poniższy kod tworzy LinearLayout z dwoma tekstami i zaokrąglonymi rogami, zmieniając kolor po naciśnięciu.

Najpierw utwórz dwa pliki xml w folderze do rysowania, jeden dla normalnego, a drugi dla wciśniętego stanu linearlayout.

XML stanu normalnego (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>

Stan wciśnięty xml (drawable / rounded_edges_pressed.xml). Jedyną różnicą jest kolor ...

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

Następnie poniższy kod wykonuje zadanie

Zmienna globalna:

public int layoutpressed = -1;

W 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

Po prostu ustaw te atrybuty

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

5

Po prostu dodaj tło attr / selectableItemBackground do układu liniowego, a także spraw, aby ten układ liniowy był klikalny

przykład:

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

To sprawia, że ​​linearlayout działa jak przycisk po naciśnięciu. :)


1

Było to pomocne, ale jeśli chcesz umieścić kolor tła i sprawić, by układ liniowy był klikalny, tak jak element listy. Ustaw tło z preferowanym kolorem i ustaw kolor pierwszego planu na? Android: attr / selectableItemBackground, ustaw fokus na true i klikalny true

przykładowy kod

   <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

Poprzednie odpowiedzi dotyczyły tego, jak ustawić domyślne tło w pliku xml. Tutaj to samo w kodzie:

linearLayout1.setBackgroundResource(android.R.drawable.list_selector_background);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.