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.