Android
layouter
Sök…
Introduktion
En layout definierar den visuella strukturen för ett användargränssnitt, till exempel en aktivitet eller widget.
En layout deklareras i XML, inklusive skärmelement som kommer att visas i den. Koden kan läggas till i applikationen för att ändra tillståndet för skärmobjekt vid körning, inklusive de som deklareras i XML.
Syntax
- android: gravitation = "top | botten | vänster | höger | center_vertical | fill_vertical | center_horizontal | fill_horizontal | center | fyllning | clip_vertical | clip_horizontal | start | end"
- android: layout_gravity = "top | botten | vänster | höger | center_vertical | fill_vertical | center_horizontal | fill_horizontal | center | fyllning | clip_vertical | clip_horizontal | start | end"
Anmärkningar
LayoutParams och Layout_ Attribut
Effektpåverkan från att använda RelativeLayouts nära toppen av din visningshierarki
Som förklarats i denna artikel om prestanda i Android kräver en RelativeLayout
två layoutpass för att kunna visas korrekt. För komplexa visningshierarkier kan detta ha en betydande inverkan på prestandan. Nesting RelativeLayouts
gör detta problem ännu värre, eftersom varje RelativeLayout
får antalet layoutpasseringar att öka.
Linear
LinearLayout är en ViewGroup
som ordnar sina barn i en enda kolumn eller en enda rad. Orienteringen kan ställas in genom att anropa metoden setOrientation()
eller använda xml-attributet android:orientation
.
- Vertikal orientering :
android:orientation="vertical"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@android:string/cancel" />
</LinearLayout>
Här är en skärmdump hur detta kommer att se ut:
Horisontell orientering :
android:orientation="horizontal"
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/app_name" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@android:string/cancel" />
LinearLayout
stöder också att tilldela en vikt till enskilda barn med attributet android:layout_weight
.
RelativeLayout
RelativeLayout
är en ViewGroup
som visar ViewGroup
i relativa positioner. Som standard ritas alla barnvyer uppe till vänster i layouten, så du måste definiera positionen för varje vy med hjälp av de olika layoutegenskaper som finns tillgängliga från RelativeLayout.LayoutParams
. Värdet för varje layoutegenskap är antingen en boolesisk för att möjliggöra en layoutposition i förhållande till överordnade RelativeLayout eller ett ID som refererar till en annan vy i den layout som vyn ska placeras mot.
Exempel:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:src="@mipmap/ic_launcher" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_toRightOf="@+id/imageView"
android:layout_toEndOf="@+id/imageView"
android:hint="@string/hint" />
</RelativeLayout>
Här är en skärmdump hur detta kommer att se ut:
Gravitet och layout tyngdkraft
android: layout_gravity
-
android:layout_gravity
används för att ställa in positionen för ett element i dess överordnade (t.ex. ett barnView
inuti enLayout
). - Stöds av LinearLayout och FrameLayout
android: gravitation
-
android:gravity
används för att ställa in innehållets placering i ett element (t.ex. en text i enTextView
).
<?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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="left"
android:gravity="center_vertical">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimary"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimary"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimary"
android:gravity="right"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center_vertical">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorAccent"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorAccent"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorAccent"
android:gravity="right"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="right"
android:gravity="center_vertical">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimaryDark"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimaryDark"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimaryDark"
android:gravity="right"/>
</LinearLayout>
</LinearLayout>
Vilket görs enligt följande:
Rutnätslayout
GridLayout, som namnet antyder är en layout som används för att ordna Visningar i ett rutnät. En GridLayout delar upp sig i kolumner och rader. Som du kan se i exemplet nedan anges mängden kolumner och / eller rader av egenskaperna columnCount
och rowCount
. Om du lägger till vyer i denna layout läggs den första vyn till den första kolumnen, den andra vyn i den andra kolumnen och den tredje vyn i den första kolumnen i den andra raden.
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:columnCount="2"
android:rowCount="2">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
</GridLayout>
Procentlayouter
Procent Support Library ger PercentFrameLayout
och PercentRelativeLayout
, två ViewGroups som ger ett enkelt sätt att ange Visa dimensioner och marginaler i termer av en procentandel av den totala storleken.
Du kan använda Procent Support Library genom att lägga till följande i dina beroenden.
compile 'com.android.support:percent:25.3.1'
Om du ville visa en vy som fyller skärmen horisontellt men bara halva skärmen vertikalt skulle du göra följande.
<android.support.percent.PercentFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
app:layout_widthPercent="100%"
app:layout_heightPercent="50%"
android:background="@android:color/black" />
<android.support.percent.PercentFrameLayout>
Du kan också definiera procentsatserna i en separat XML-fil med kod som:
<fraction name="margin_start_percent">25%</fraction>
Och hänvisa till dem i dina layouter med @fraction/margin_start_percent
.
De innehåller också möjligheten att ställa in ett anpassat bildförhållande via app:layout_aspectRatio
.
Detta gör att du bara kan ställa in en enda dimension, till exempel bara bredden, och höjden bestäms automatiskt baserat på det bildförhållande du har definierat, oavsett om det är 4: 3 eller 16: 9 eller till och med en kvadrat 1: 1 sidförhållande.
Till exempel:
<ImageView
app:layout_widthPercent="100%"
app:layout_aspectRatio="178%"
android:scaleType="centerCrop"
android:src="@drawable/header_background"/>
FrameLayout
FrameLayout
är utformad för att blockera ett område på skärmen för att visa ett enda objekt. Du kan dock lägga till flera barn till en FrameLayout och kontrollera deras position inom FrameLayout genom att tilldela allvar till varje barn med attributet Android: layout_gravity .
Vanligtvis används FrameLayout
för att hålla en enskild barnvy. Vanliga fall skapar platshållare för att blåsa upp Fragments
i Activity
, överlappa vyer eller tillämpa förgrunden till vyerna.
Exempel:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/nougat"
android:scaleType="fitCenter"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
<TextView
android:text="FrameLayout Example"
android:textSize="30sp"
android:textStyle="bold"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:gravity="center"/>
</FrameLayout>
Det kommer att se ut så här:
CoordinatorLayout
CoordinatorLayout
är en behållare som liknar FrameLayout
men med extra kapacitet kallas den superdrivna FrameLayout
i den officiella dokumentationen.
Genom att ansluta en CoordinatorLayout.Behavior
till ett direkt barn av CoordinatorLayout kan du fånga beröringshändelser, fönsterinsatser, mätning, layout och kapslad rullning.
För att kunna använda den måste du först lägga till ett beroende för supportbiblioteket i din gradle-fil:
compile 'com.android.support:design:25.3.1'
Numret på den senaste versionen av biblioteket kan hittas här
Ett praktiskt fall med CoordinatorLayout
är att skapa en vy med en FloatingActionButton
. I detta specifika fall kommer vi att skapa en RecyclerView
med en SwipeRefreshLayout
och en FloatingActionButton
ovanpå. Så här kan du göra det:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coord_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/recycler_view"/>
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:color="@color/colorAccent"
android:src="@mipmap/ic_add_white"
android:layout_gravity="end|bottom"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
Lägg märke till hur FloatingActionButton är förankrat i CoordinatorLayout med app:layout_anchor="@id/coord_layout"
KoordinatorLayout Rullningsbeteende
En bifogad CoordinatorLayout
kan användas för att uppnå rullningseffekter för materialdesign när du använder inre layouter som stöder kapslad rullning, till exempel NestedScrollView
eller RecyclerView
.
För detta exempel:
-
app:layout_scrollFlags="scroll|enterAlways"
används i verktygsfältets egenskaper -
app:layout_behavior="@string/appbar_scrolling_view_behavior"
används i ViewPager-egenskaperna - En RecyclerView används i ViewPager-fragmenten
Här är layout-xml-filen som används i en aktivitet:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="6dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways"
/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
app:tabMode="fixed"
android:layout_below="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:elevation="0dp"
app:tabTextColor="#d3d3d3"
android:minHeight="?attr/actionBarSize"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_below="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
Resultat:
Visa vikt
Ett av de mest använda attributen för LinearLayout är vikten av sina barnvyer. Vikt definierar hur mycket utrymme en vy kommer att förbrukas jämfört med andra vyer inom en LinearLayout.
Vikt används när du vill ge specifikt skärmutrymme till en komponent jämfört med en annan.
Viktiga egenskaper :
weightSum
är den totala summan av vikterna för alla barnvyer. Om du inte angerweightSum
kommer systemet att beräkna summan av alla vikterna på egen hand.layout_weight
anger mängden utrymme ur den totala viktsumman som widgeten kommer att uppta.
Koda:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="4">
<EditText
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Type Your Text Here" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text1" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text1" />
</LinearLayout>
Utgången är:
Även om enhetens storlek är större tar EditText 2/4 av skärmens utrymme. Därför ses appens utseende konsekvent på alla skärmar.
Obs: Här layout_width
hålls 0dp
som widgeten utrymmet delas horisontellt. Om widgets ska justeras vertikalt kommer layout_height
att ställas in på 0dp
. Detta görs för att öka effektiviteten för koden eftersom systemet under körning inte kommer att försöka beräkna bredden respektive höjden eftersom det hanteras av vikten. Om du istället använde wrap_content
skulle systemet försöka beräkna bredden / höjden först innan du använder wrap_content
som orsakar en annan beräkningscykel.
Skapa LinearLayout programmatiskt
Hierarki
- LinearLayout(horizontal)
- ImageView
- LinearLayout(vertical)
- TextView
- TextView
Koda
LinearLayout rootView = new LinearLayout(context);
rootView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
rootView.setOrientation(LinearLayout.HORIZONTAL);
// for imageview
ImageView imageView = new ImageView(context);
// for horizontal linearlayout
LinearLayout linearLayout2 = new LinearLayout(context);
linearLayout2.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
linearLayout2.setOrientation(LinearLayout.VERTICAL);
TextView tv1 = new TextView(context);
TextView tv2 = new TextView(context);
// add 2 textview to horizontal linearlayout
linearLayout2.addView(tv1);
linearLayout2.addView(tv2);
// finally, add imageview and horizontal linearlayout to vertical linearlayout (rootView)
rootView.addView(imageView);
rootView.addView(linearLayout2);
LayoutParams
Varje enskild ViewGroup
(t.ex. LinearLayout
, RelativeLayout
, CoordinatorLayout
, etc.) måste lagra information om sina barns egenskaper. Om hur barnen läggs ut i ViewGroup
. Denna information lagras i objekt i en omslagsklass ViewGroup.LayoutParams
.
För att inkludera parametrar som är specifika för en viss ViewGroups
använder ViewGroups
underklasser i klassen ViewGroup.LayoutParams
.
T.ex.
-
LinearLayout
det ärLinearLayout.LayoutParams
-
RelativeLayout
det ärRelativeLayout.LayoutParams
-
CoordinatorLayout
det ärCoordinatorLayout.LayoutParams
- ...
De flesta av ViewGroups
återanvänder förmågan att sätta margins
för sina barn, så att de inte underklasserar ViewGroup.LayoutParams
direkt, men de underklasserar ViewGroup.MarginLayoutParams
istället (som i sig är en underklass för ViewGroup.LayoutParams
).
LayoutParams
i xml
LayoutParams
objekt skapas baserat på den uppblåsta layout- xml
filen.
<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:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="right"
android:gravity="bottom"
android:text="Example text"
android:textColor="@android:color/holo_green_dark"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_green_dark"
android:scaleType="centerInside"
android:src="@drawable/example"/>
</LinearLayout>
Alla parametrar som börjar med layout_
anger hur den bifogade layouten ska fungera. När layouten blåses upp lindas dessa parametrar i ett korrekt LayoutParams
objekt, som senare kommer att användas av Layout
att korrekt placera en viss View
i ViewGroup
. Andra egenskaper hos en View
är direkt View
relaterade och bearbetas av View
själv.
För TextView
:
-
layout_width
,layout_height
ochlayout_gravity
lagras i ettLinearLayout.LayoutParams
objekt och används avLinearLayout
-
gravity
,text
ochtextColor
kommer att användas avTextView
själv
För ImageView
:
-
layout_width
,layout_height
ochlayout_weight
lagras i ettLinearLayout.LayoutParams
objekt och används avLinearLayout
-
background
,scaleType
ochsrc
kommer att användas avImageView
själv
LayoutParams
objekt
getLayoutParams
är en View's
metod som gör det möjligt att hämta ett aktuellt LayoutParams
objekt.
Eftersom LayoutParams
objektet är direkt relaterad till den omslutande ViewGroup
kommer denna metod returnerar en icke-noll-värde endast när View
är ansluten till ViewGroup
. Du måste tänka på att detta objekt kanske inte är närvarande hela tiden. Särskilt bör du inte vara beroende av att ha den i View's
konstruktör.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupView(context);
}
private void setupView(Context context) {
if (getLayoutParams().height == 50){ // DO NOT DO THIS!
// This might produce NullPointerException
doSomething();
}
}
//...
}
Om du vill vara beroende av att ha LayoutParams
objekt, bör du använda onAttachedToWindow
metoden istället.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getLayoutParams().height == 50) { // getLayoutParams() will NOT return null here
doSomething();
}
}
//...
}
Casting LayoutParams
objekt
Du kanske behöver använda funktioner som är specifika för en viss ViewGroup
(t.ex. kan du programmatiskt ändra regler för en RelativeLayout
). För detta ändamål måste du veta hur du kastar ViewGroup.LayoutParams
objektet ViewGroup.LayoutParams
.
Det här kan vara lite förvirrande när du får ett LayoutParams
objekt för en View
som faktiskt är en annan ViewGroup
.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/outer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/inner_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="right"/>
</LinearLayout>
VIKTIGT: Typen av LayoutParams
objekt är direkt relaterad till typen av ENCLOSING ViewGroup
.
Felaktig gjutning :
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) innerLayout.getLayoutParams();
// INCORRECT! This will produce ClassCastException
Rätt gjutning :
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
LinearLayout.LayoutParams par = (LinearLayout.LayoutParams) innerLayout.getLayoutParams();
// CORRECT! the enclosing layout is a LinearLayout