Układy w widokach

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak korzystać z układów w funkcji Utwórz

Układ określa strukturę interfejsu użytkownika aplikacji, np. aktywność. Wszystkie elementy w układ jest oparty na hierarchii View i ViewGroup obiektów. View zwykle rysuje coś, co użytkownik widzi wchodzą w interakcję z reklamą. ViewGroup to niewidoczny kontener, który określa struktura układu dla View i innych elementów ViewGroup jak na ilustracji 1.

Rysunek 1. Grafika przedstawiająca hierarchię widoków, która definiuje układ interfejsu.

Obiekty View są często nazywane widżetami i mogą być jednym z wiele podklas, takich jak Button lub TextView. Obiekty ViewGroup są zwykle nazywane układami i mogą być jednym z nich różne typy o różnej strukturze układu, np. LinearLayout lub ConstraintLayout

Układ możesz zadeklarować na 2 sposoby:

  • Deklarowanie elementów interfejsu w pliku XML. Android zapewnia prosty kod XML słownik, który odpowiada klasom i podklasom (View), np. widżetów i układów. Możesz też użyć narzędzia Android Studio, Edytor układów do tworzenia kodu XML. układ za pomocą interfejsu typu „przeciągnij i upuść”.

  • Twórz instancje elementów układu w czasie działania. Aplikacja może tworzyć View i ViewGroup obiektów i manipuluj nimi w sposób zautomatyzowany.

Zadeklarowanie interfejsu w formacie XML pozwala oddzielić sposób prezentacji aplikacji od który kontroluje jego działanie. Użycie plików XML ułatwia też udostępnić różne układy do różnych rozmiarów i orientacji ekranu. To jest omówiono szerzej tutaj: Obsługuj różne ekrany .

Platforma Androida zapewnia elastyczność – możesz korzystać z jednego lub obu do tworzenia interfejsu aplikacji. Możesz na przykład zadeklarować, domyślnych układach w pliku XML, a następnie modyfikować je w czasie działania.

Zapisz kod XML

Korzystając ze słownika XML na Androida, możesz szybko projektować układy interfejsu zawarte w nich elementy ekranu, tak samo jak w przypadku tworzenia stron internetowych w języku HTML z serią zagnieżdżonych elementów.

Każdy plik układu musi zawierać dokładnie jeden element główny, który musi być tagiem Obiekt View lub ViewGroup. Po zdefiniowaniu poziomu głównego , możesz dodać do niego dodatkowe obiekty układu lub widżety jako elementy podrzędne stopniowo twórz hierarchię View, która definiuje układ. Dla: Oto układ XML, w którym pionowa wartość LinearLayout pozwala zawierają TextView i Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

Po zadeklarowaniu układu w pliku XML zapisz plik z atrybutem .xml rozszerzenie w projekcie res/layout/ w projekcie na Androida w celu poprawnej kompilacji.

Więcej informacji na temat składni pliku XML układu znajdziesz tutaj Zasób układu.

Wczytaj zasób XML

Podczas kompilowania aplikacji każdy plik układu XML jest kompilowany w View zasób. Wczytaj zasób szablonu do pliku Activity.onCreate() implementacji wywołania zwrotnego. Aby to zrobić, zadzwoń pod numer setContentView(), przekazując je do zasobu układu w formularzu: R.layout.layout_file_name Na przykład, jeśli plik XML układ został zapisany jako main_layout.xml, wczytaj go na swoim Activity w następujący sposób:

Kotlin

fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

Java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

Platforma Androida wywołuje metodę wywołania zwrotnego onCreate() w Activity po uruchomieniu Activity. Więcej informacje o cyklach życia działań, zobacz Wprowadzenie do aktywności.

Atrybuty

Każdy obiekt View i ViewGroup obsługuje własne różne atrybuty XML. Niektóre atrybuty są charakterystyczne dla atrybutu View obiektu. Na przykład TextView obsługuje textSize . Te atrybuty są jednak również dziedziczone przez dowolne View które rozszerzają tę klasę. Niektóre są wspólne dla wszystkich: View ponieważ są one dziedziczone z klasy głównej View, takiej jak atrybut id. Inne atrybuty są uznawane za układ parametrów, które opisują określone orientacje układu. obiektu View zdefiniowanego przez jego obiekt nadrzędny ViewGroup obiekt.

ID

Z dowolnym obiektem View może być powiązany identyfikator całkowity w celu jednoznacznie identyfikują View w drzewie. Gdy aplikacja jest jest skompilowany, identyfikator ten jest przywoływany w postaci liczby całkowitej, ale identyfikator jest zwykle przypisywany w pliku XML układu jako ciąg znaków w atrybucie id. To jest Atrybut XML wspólny dla wszystkich obiektów View, który jest definiowany przez klucz View zajęcia. Bardzo często go używasz. Składnia identyfikatora wewnątrz tagu Tag XML wygląda tak:

android:id="@+id/my_button"

Symbol at (@) na początku ciągu oznacza, że: Parser XML analizuje i rozwija resztę ciągu znaków identyfikatora, identyfikując go jako zasobu identyfikatora. Symbol plusa (+) oznacza, że jest to nowa nazwa zasobu. które należy utworzyć i dodać do zasobów w R.java .

Platforma Androida udostępnia też wiele innych zasobów związanych z identyfikatorem. Gdy odwołujesz się do identyfikatora zasobu Androida, nie potrzebujesz symbolu plusa, ale musisz dodać Przestrzeń nazw pakietu android w ten sposób:

android:id="@android:id/empty"

Przestrzeń nazw pakietu android wskazuje, że odwołujesz się identyfikator z klasy zasobów android.R, a nie lokalnego w ramach klasy zasobów.

Aby tworzyć widoki i odwołać się do nich z aplikacji, możesz użyć wspólnej w następujący sposób:

  1. Zdefiniuj widok w pliku układu i przypisz mu unikalny identyfikator, na przykład następujący przykład:
    <Button android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/my_button_text"/>
    
  2. utworzyć instancję obiektu widoku i przechwycić ją z układu, zwykle w onCreate() zgodnie z poniższym przykładem:

    Kotlin

    val myButton: Button = findViewById(R.id.my_button)
    

    Java

    Button myButton = (Button) findViewById(R.id.my_button);
    

Definiowanie identyfikatorów obiektów widoku jest ważne przy tworzeniu RelativeLayout W układzie względnym widoki równorzędne mogą definiować swój układ względem innego widoku równorzędnego, do którego odwołuje się unikalny identyfikator.

Identyfikator nie musi być unikalny w całym drzewie, ale musi tylko w obrębie objętej wyszukiwaniem. Często składa się z całej więc postaraj się, by była unikalna, gdy tylko jest to możliwe.

Parametry układu

Definicja atrybutów układu XML o nazwie layout_something dla parametrów układu View, które są odpowiednie dla parametru ViewGroup, w których się znajduje.

Każda klasa ViewGroup implementuje zagnieżdżoną klasę, która rozszerza ViewGroup.LayoutParams Ta podklasa zawiera typy właściwości, które definiują rozmiar i pozycję każdej z nich widoku podrzędnego, odpowiednio do danej grupy. Jak widać na ilustracji 2, wydawca nadrzędny grupa widoków definiuje parametry układu dla każdego widoku podrzędnego, w tym widoku podrzędnego grupę widoków.

Rysunek 2. Wizualizacja hierarchii widoków z układem powiązane z każdym widokiem.

Każda podklasa LayoutParams ma własną składnię ustawień . Każdy element podrzędny musi definiować element LayoutParams, który jest odpowiednie dla jej elementu nadrzędnego, choć może również definiować inne LayoutParams dla własnych dzieci.

Wszystkie grupy widoków danych uwzględniają szerokość i wysokość za pomocą parametru layout_width i layout_height, a każdy widok jest wymagany do ich zdefiniowania. Wiele LayoutParams mają opcjonalne marginesy i obramowania.

Możesz podać szerokość i wysokość z dokładnym pomiarem, ale nie musi często robią to samo. Częściej używa się jednej z tych stałych do ustawiania wartości parametru szerokość lub wysokość:

  • wrap_content: informuje widok, aby zmienić rozmiar na wymiarów wymaganych przez jej treść.
  • match_parent: informuje, że widok ma być tak duży jak jego element nadrzędny zezwala na dostęp do wybranych grup.

Ogólnie nie zalecamy określania szerokości i wysokości układu za pomocą bezwzględne jednostki, takie jak piksele. Lepszym podejściem jest stosowanie pomiarów względnych, takie jak jednostki pikseli niezależne od gęstości (dp), wrap_content lub match_parent, ponieważ pomaga w prawidłowym wyświetlaniu aplikacji na różnych rozmiarów ekranów urządzeń. Akceptowane typy pomiarów są zdefiniowane w Zasób układu.

Pozycja układu

Widok ma prostokątną geometrię. Ma lokalizację, wyrażoną jako parę współrzędne left i top oraz dwa wymiary, wyrażone jako szerokości i wysokości. Jednostką lokalizacji i wymiarów jest piksel.

Aby pobrać lokalizację widoku, wywołaj te metody getLeft() oraz getTop() Pierwszy zwraca współrzędną lewą (x) prostokąta reprezentującego widoku. Ten drugi zwraca współrzędną górną (y) prostokąta reprezentujący widok. Te metody zwracają lokalizację widoku w odniesieniu do jego elementu nadrzędnego. Jeśli na przykład getLeft() zwraca wartość 20, oznacza to, że para klucz-wartość znajduje się 20 pikseli na prawo od lewej krawędzi elementu nadrzędnego.

Istnieją też wygodne metody, które pozwalają uniknąć zbędnych obliczeń: mianowicie getRight() oraz getBottom() Te metody zwracają współrzędne prawej i dolnej krawędzi reprezentujący widok. Na przykład dzwonienie pod numer getRight() to podobnie do tego obliczenia: getLeft() + getWidth().

Rozmiar, dopełnienie i marginesy

Rozmiar widoku jest wyrażony za pomocą szerokości i wysokości. Widok składa się z 2 par szerokości i wysokości.

Pierwsza para ma nazwę mierzona szerokość i mierz wzrost. Te wymiary określają, jak duży widok w elemencie nadrzędnym. Wymiary zmierzone możesz uzyskać, wywołując getMeasuredWidth() oraz getMeasuredHeight()

Druga para ma nazwy width i height. Czasami szerokość rysunku i wysokość rysowania. Wymiary te definiują rzeczywisty rozmiar widoku na ekranie, w czasie rysowania i po układzie. Te mogą, ale nie muszą, różnić się od zmierzonej szerokości i wysokości. Ty może uzyskać szerokość i wysokość, wywołując getWidth() oraz getHeight()

Przy pomiarze wymiarów widok uwzględnia jego dopełnienie. Dopełnienie jest wyrażony w pikselach dla lewej, górnej, prawej i dolnej części widoku. Możesz użyć dopełnienia, aby odsunąć zawartość widoku o określoną liczbę pikseli. Na przykład dwukrotne dopełnienie po lewej stronie przesuwa treść widoku o dwa piksele. na prawo od lewej krawędzi. Dopełnienie możesz ustawić za pomocą setPadding(int, int, int, int) i wysyłanie do niej zapytań za pomocą wywołania getPaddingLeft(), getPaddingTop(), getPaddingRight(), oraz getPaddingBottom().

Chociaż widok może definiować dopełnienie, nie obsługuje on marginesów. Pamiętaj jednak: grupy widoków danych obsługują marginesy. Zobacz ViewGroup i ViewGroup.MarginLayoutParams .

Więcej informacji o wymiarach znajdziesz w artykule Wymiar.

Oprócz automatycznego ustawiania marginesów i dopełnienia, w układach XML, jak widać w tym przykładzie:

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
      <TextView android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:padding="8dp"
                android:text="Hello, I am a TextView" />
      <Button android:id="@+id/button"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginTop="16dp"
              android:paddingBottom="4dp"
              android:paddingEnd="8dp"
              android:paddingStart="8dp"
              android:paddingTop="4dp"
              android:text="Hello, I am a Button" />
  </LinearLayout>
  

W poprzednim przykładzie widać zastosowane marginesy i dopełnienie. TextView ma równomierne marginesy i dopełnienie dookoła. Button pokazuje, jak stosować je niezależnie w krawędzie.

Popularne układy

Każda podklasa klasy ViewGroup zapewnia unikalny sposób wyświetlanie zagnieżdżonych widoków. Najbardziej elastyczny typ układu, który zapewnia najlepsze narzędzia do utrzymywania płytkiej hierarchii układu ConstraintLayout

Oto kilka popularnych typów układów wbudowanych w Androida. platformy.

Tworzenie układu liniowego

Umieszcza elementy podrzędne w jednym poziomym lub pionowym wierszu i tworzy pasek przewijania, jeśli okno jest dłuższe niż długość ekranu.

Tworzenie aplikacji internetowych w WebView

Wyświetla strony internetowe.

Tworzenie list dynamicznych

Jeśli zawartość układu jest dynamiczna lub nie została wcześniej określona, możesz należy użyć funkcji RecyclerView lub podklasa AdapterView Zwykle lepszą opcją jest RecyclerView, ponieważ wykorzystuje pamięć skuteczniej niż AdapterView.

Typowe układy dostępne w RecyclerView i AdapterView obejmują:

Lista

Wyświetla przewijaną listę z jedną kolumną.

Siatka

Wyświetla przewijaną siatkę kolumn i wierszy.

RecyclerView daje więcej możliwości opcję utwórz niestandardową menedżer układu.

Wypełnianie widoku adaptera danymi

Możesz uzupełnić AdapterView na przykład ListView lub GridView według powiązanie instancji AdapterView z Adapter, który pobiera dane ze źródła zewnętrznego i tworzy View reprezentujących każdy wpis danych.

Android oferuje kilka podklasy klasy Adapter, które są przydatne do pobierania różnych rodzajów danych i tworzenia widoków AdapterView Dwie najpopularniejsze adaptery to:

ArrayAdapter
Użyj tego adaptera, gdy źródłem danych jest tablica. Domyślnie Funkcja ArrayAdapter tworzy widok każdego elementu tablicy przez wywołanie toString() przy każdym elemencie, a jego zawartość umieść w elemencie TextView.

Jeśli na przykład masz tablicę ciągów tekstowych, którą chcesz wyświetlić w ListView, zainicjuj nowe ArrayAdapter przy użyciu konstruktora do określania układu każdego ciągu znaków i tablicy ciągu:

Kotlin

    val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
    

Java

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, myStringArray);
    

Argumenty tego konstruktora są następujące:

  • Twoja aplikacja Context
  • Układ zawierający TextView dla każdego ciągu w parametrze tablica
  • Tablica ciągu

Następnie zadzwoń setAdapter() na urządzeniu ListView:

Kotlin

    val listView: ListView = findViewById(R.id.listview)
    listView.adapter = adapter
    

Java

    ListView listView = (ListView) findViewById(R.id.listview);
    listView.setAdapter(adapter);
    

Aby dostosować wygląd każdego elementu, możesz zastąpić toString() dla obiektów w tablicy. Lub, aby utworzyć wyświetlenia każdego elementu, który nie jest TextView – jeśli na przykład chcesz dodać atrybut ImageView dla każdego elementu tablicy – rozszerz klasę ArrayAdapter i zastąpić getView() aby zwracać wybrany typ widoku dla każdego elementu.

SimpleCursorAdapter
Używaj tej przejściówki, jeśli dane pochodzą z usługi Cursor Jeśli używasz elementu SimpleCursorAdapter, określ układ, który ma być używany poszczególne wiersze w tabeli Cursor i które kolumny w tabeli Cursor, który chcesz wstawić do widoków wybranego układu. Jeśli na przykład chcesz utworzyć listę imion i nazwisk osób oraz numerów telefonów możesz wykonać zapytanie, które zwróci liczbę Cursor zawierające po jednym wierszu na każdą osobę i kolumnach na imiona i nazwiska oraz numery. Ty a następnie utwórz tablicę ciągu znaków określającą, które kolumny z Cursor, które chcesz uwzględnić w układzie dla każdego wyniku, i liczbę całkowitą. tablica określająca odpowiednie widoki, które każda kolumna musi być umieszczone:

Kotlin

    val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME,
                              ContactsContract.CommonDataKinds.Phone.NUMBER)
    val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
    

Java

    String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                            ContactsContract.CommonDataKinds.Phone.NUMBER};
    int[] toViews = {R.id.display_name, R.id.phone_number};
    

Podczas tworzenia instancji SimpleCursorAdapter przekazuj parametr do użycia w poszczególnych wynikach, element Cursor zawierający i te dwie tablice:

Kotlin

    val adapter = SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0)
    val listView = getListView()
    listView.adapter = adapter
    

Java

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
    ListView listView = getListView();
    listView.setAdapter(adapter);
    

Następnie SimpleCursorAdapter tworzy widok dla każdego wiersza w Cursor przy użyciu podanego układu, wstawiając każdy z nich fromColumns element do odpowiadającego mu elementu toViews widok.

Jeśli w trakcie użytkowania aplikacji zmienisz dane źródłowe, zostanie odczytany przez adapter, wywołaj notifyDataSetChanged() Informuje to załączony widok, że dane zostały zmienione i są odświeżane.

Obsługa zdarzeń kliknięcia

Możesz odpowiadać na zdarzenia kliknięcia każdego elementu w AdapterView przez wdrożenie AdapterView.OnItemClickListener za pomocą prostego interfejsu online. Na przykład:

Kotlin

listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
    // Do something in response to the click.
}

Java

// Create a message handling object as an anonymous class.
private OnItemClickListener messageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click.
    }
};

listView.setOnItemClickListener(messageClickedHandler);

Dodatkowe materiały

Zobacz, jak są używane układy w Słonecznik aplikację demonstracyjną na GitHubie.