Làm cách nào để căn chỉnh các khung nhìn ở dưới cùng của màn hình?


636

Đây là mã bố trí của tôi;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView android:text="@string/welcome"
        android:id="@+id/TextView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </TextView>

    <LinearLayout android:id="@+id/LinearLayout"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="bottom">

            <EditText android:id="@+id/EditText"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
            </EditText>

            <Button android:text="@string/label_submit_button"
                android:id="@+id/Button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </Button>

    </LinearLayout>

</LinearLayout>

Những gì nó trông giống như ở bên trái và những gì tôi muốn nó trông giống như ở bên phải.

Bố cục Android - Thực tế (Trái) và Mong muốn (Phải)

Câu trả lời rõ ràng là đặt TextView thành fill_parent theo chiều cao, nhưng điều này khiến không còn chỗ cho nút hoặc trường nhập.

Về cơ bản, vấn đề là tôi muốn nút gửi và mục nhập văn bản có chiều cao cố định ở dưới cùng và chế độ xem văn bản để lấp đầy phần còn lại của không gian. Tương tự, trong bố cục tuyến tính ngang, tôi muốn nút gửi bao bọc nội dung của nó và cho mục nhập văn bản để lấp đầy phần còn lại của không gian.

Nếu mục đầu tiên trong bố cục tuyến tính được yêu cầu điền_parent thì nó thực hiện chính xác điều đó, không còn chỗ cho các mục khác. Làm cách nào để tôi có được một mục đầu tiên trong bố cục tuyến tính để lấp đầy tất cả không gian ngoài mức tối thiểu được yêu cầu bởi các mục còn lại trong bố cục?


Bố trí tương đối thực sự là câu trả lời:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView
        android:text="@string/welcome"
        android:id="@+id/TextView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true">
    </TextView>

    <RelativeLayout
        android:id="@+id/InnerRelativeLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" >

        <Button
            android:text="@string/label_submit_button"
            android:id="@+id/Button"
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </Button>

        <EditText
            android:id="@+id/EditText"
            android:layout_width="fill_parent"
            android:layout_toLeftOf="@id/Button"
            android:layout_height="wrap_content">
        </EditText>

    </RelativeLayout>

</RelativeLayout>

7
@oneself Paint;) Tôi đang sử dụng skin trên trình giả lập mặc dù lịch sự của Tea Vui Huang teavuihuang.com/android
gav

14
+1 để đăng XML bố cục đã giải quyết nó. Giúp tôi tìm ra những gì đã xảy ra với tôi.
Howler

Câu trả lời:


527

Cách hiện đại để làm điều này là có một ConstraintLayout và giới hạn phần dưới của khung nhìn xuống dưới cùng của ConstraintLayout vớiapp:layout_constraintBottom_toBottomOf="parent"

Ví dụ dưới đây tạo một FloatingActionButton sẽ được căn chỉnh đến cuối và cuối màn hình.

<android.support.constraint.ConstraintLayout
   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_height="match_parent"
   android:layout_width="match_parent">

<android.support.design.widget.FloatingActionButton
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"

    app:layout_constraintBottom_toBottomOf="parent"

    app:layout_constraintEnd_toEndOf="parent" />

</android.support.constraint.ConstraintLayout>

Để tham khảo, tôi sẽ giữ câu trả lời cũ của tôi.

Trước khi giới thiệu ConstraintLayout, câu trả lời là một bố cục tương đối .


Nếu bạn có bố cục tương đối lấp đầy toàn bộ màn hình, bạn sẽ có thể sử dụng android:layout_alignParentBottomđể di chuyển nút xuống phía dưới màn hình.

Nếu chế độ xem của bạn ở phía dưới không được hiển thị trong bố cục tương đối thì có thể bố cục ở trên sẽ chiếm hết không gian. Trong trường hợp này, bạn có thể đặt chế độ xem, ở dưới cùng, đầu tiên trong tệp bố cục của bạn và đặt phần còn lại của bố cục phía trên các chế độ xem với android:layout_above. Điều này cho phép chế độ xem dưới cùng chiếm nhiều không gian cần thiết và phần còn lại của bố cục có thể lấp đầy tất cả phần còn lại của màn hình.


5
FYI: sẽ không hoạt động trong ScrollView. Đây là vấn đề tôi đang phải đối mặt bây giờ. Xem stackoverflow.com/questions/3126347/ từ
IgorGanapolsky

6
Đó là ScrollViews chính xác và Bố cục tương đối không kết hợp tốt với nhau. Nếu bạn phải có nhiều nội dung để hiển thị mọi thứ trên một trang, chỉ cần sử dụng linearlayout và đặt ở chế độ xem dưới cùng cuối cùng. Nếu bạn muốn chế độ xem xuất hiện lần cuối trong cuộn xem trên màn hình nhỏ và ở cuối trang trên điện thoại lớn hơn, hãy cân nhắc sử dụng các tệp bố cục khác nhau và sử dụng vòng loại ressource để cho phép thiết bị chọn tệp bố cục chính xác.
Janusz

ok .. điểm của đoạn thứ hai của câu trả lời ở đây là gì? "Bạn nên tìm một bố cục bao phủ phía dưới màn hình trước"? Vậy chúng ta nên sử dụng layout_alignParentBottom bên trong layout? Chúng ta cần android:layout_abovegì?
eugene

Bạn cần những thứ ở trên nếu bạn muốn một cái gì đó giống như một thanh ở phía dưới và sau đó là linearLayout phía trên thanh này trải dài từ đỉnh màn hình đến thanh.
Janusz

1
Tôi đã đọc trong một trong "Android Weekly" that RelativeLayoutlà tiêu thụ bộ nhớ và nên tránh bất cứ khi nào có thể.
Tomasz Mularchot

153

Trong một ScrollViewđiều này không hoạt động, vì RelativeLayoutsau đó sẽ chồng chéo bất cứ điều gì ScrollViewở dưới cùng của trang.

Tôi đã sửa nó bằng cách kéo dài động FrameLayout:

<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    android:fillViewport="true">
    <LinearLayout 
        android:id="@+id/LinearLayout01"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical">

                <!-- content goes here -->

                <!-- stretching frame layout, using layout_weight -->
        <FrameLayout
            android:layout_width="match_parent" 
            android:layout_height="0dp"
            android:layout_weight="1">
        </FrameLayout>

                <!-- content fixated to the bottom of the screen -->
        <LinearLayout 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content"
            android:orientation="horizontal">
                                   <!-- your bottom content -->
        </LinearLayout>
    </LinearLayout>
</ScrollView>

1
điều này thật tuyệt - cũng vậy, đó là "xâm lấn tối thiểu" và trực quan hơn so với phương pháp RelativeLayout. Tôi sẽ cung cấp nhiều hơn một upvote nếu tôi có thể!
năm11

4
Tôi sử dụng giải pháp của bạn trong ứng dụng của mình, nhưng trong trường hợp của tôi, tôi muốn rằng khi bàn phím xuất hiện, các nút vẫn ở dưới cùng của màn hình (phía sau bàn phím) Có sự hờn dỗi nào cho điều đó? Thaks.
Yoann

1
@DoubleYo: trong tệp kê khai android: windowSoftInputMode = "điều chỉnhPan"
Kopfgeldjaeger

2
NẾU bạn muốn đáy được cố định vĩnh viễn để nó hiển thị tất cả thời gian điều này không hoạt động. Nếu không thì nó hoạt động.
K - Độc tính trong SO đang tăng lên.

72

Bạn có thể giữ bố cục tuyến tính ban đầu bằng cách lồng bố cục tương đối trong bố cục tuyến tính:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView android:text="welcome" 
        android:id="@+id/TextView" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
    </TextView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button android:text="submit" 
            android:id="@+id/Button" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true">
        </Button>
        <EditText android:id="@+id/EditText" 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/Button"
            android:layout_alignParentBottom="true">
        </EditText>
    </RelativeLayout>
</LinearLayout>

2
Đây là một cách tiếp cận lộn xộn ở chỗ nó không phải là mô-đun. Bạn không nên có bố cục chồng chéo. Thiết kế này sẽ không hoạt động ngay khi bạn muốn thay đổi nền của RelativeLayout hoặc muốn làm cho bất kỳ chế độ xem nào lớn hơn hoặc thêm lượt xem.
Patrick

42

Câu trả lời ở trên (của Janusz) là hoàn toàn chính xác, nhưng cá nhân tôi không cảm thấy dễ hiểu 100% với RelativeLayouts, vì vậy tôi thích giới thiệu một 'Trình xem' trống, TextView trống rỗng, như thế này:

<!-- filler -->
<TextView android:layout_height="0dip" 
          android:layout_width="fill_parent"
          android:layout_weight="1" />

trước phần tử nên ở dưới cùng của màn hình.


Điều này sẽ mở rộng đến trục x hoặc y. Cho 0dip cho chiều cao sẽ làm cho textview không có chiều cao nào? hoặc sẽ mở rộng nhiều như nó có thể giống như trục x?
Lukap

Điều này mở rộng theo chiều dọc vì chiều cao (trục dọc) được đặt thành 0 và trọng số là 1 (giả sử rằng các phần tử khác có trọng số bằng 0).
Timores

Trên trục x, nó sẽ là cha mẹ của nó (fill_parent)
Timores

Thay vì một textview tôi sẽ sử dụng một bố cục tuyến tính khác. Giao diện bố trí dường như ngụ ý nó có thể được sử dụng để lấp đầy không gian?
Đến vào

33

Bạn cũng có thể thực hiện việc này với linearLayout hoặc ScrollView. Đôi khi nó dễ thực hiện hơn RelativeLayout. Điều duy nhất bạn cần làm là thêm chế độ xem sau trước Chế độ xem bạn muốn căn chỉnh xuống cuối màn hình:

<View
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_weight="1" />

Điều này tạo ra một chế độ xem trống, lấp đầy không gian trống và đẩy các chế độ xem tiếp theo xuống dưới cùng của màn hình.


27

Điều này cũng hoạt động.

<LinearLayout 
    android:id="@+id/linearLayout4"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_below="@+id/linearLayout3"
    android:layout_centerHorizontal="true"
    android:orientation="horizontal" 
    android:gravity="bottom"
    android:layout_alignParentBottom="true"
    android:layout_marginTop="20dp"
>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" 

    />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" 


    />

</LinearLayout>

trọng lực = "đáy" để thả các phần tử tuyến tính vào đáy


12
android: layout_alignParentBottom = "true" không có tác dụng trừ khi linearLayout được lồng bên trong RelativeLayout.
Thomas Dignan

Một lời giải thích sẽ theo thứ tự (ví dụ: thay đổi thiết yếu, cách thức hoạt động, tại sao nó hoạt động, v.v.).
Peter Mortensen

26

1. Sử dụng ConstraintLayouttrong Bố cục gốc của bạn

Và thiết lập app:layout_constraintBottom_toBottomOf="parent"để cho phép Bố cục ở dưới cùng của màn hình:

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintBottom_toBottomOf="parent">
</LinearLayout>

2. Sử dụng FrameLayouttrong Bố cục gốc của bạn

Chỉ cần đặt android:layout_gravity="bottom"trong bố cục của bạn

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:orientation="horizontal">
</LinearLayout>

3. Sử dụng LinearLayouttrong Bố cục gốc của bạn ( android:orientation="vertical")

(1) Đặt bố cục android:layout_weight="1"trên đầu Bố cục của bạn

<TextView
    android:id="@+id/TextView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:text="welcome" />

(2) Đặt con LinearLayoutchoandroid:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom"

Thuộc tính chính là ndroid:gravity="bottom", hãy để con Xem ở dưới cùng của Bố cục.

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    android:orientation="horizontal">
</LinearLayout>

4. Sử dụng RelativeLayouttrong Bố cục gốc

Và thiết lập android:layout_alignParentBottom="true"để cho phép Bố cục ở dưới cùng của màn hình

<LinearLayout
    android:id="@+id/LinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:orientation="horizontal">
</LinearLayout>

Đầu ra

Nhập mô tả hình ảnh ở đây


20

Theo dõi giải pháp tao nhã của Timores , tôi đã phát hiện ra rằng những điều sau đây sẽ tạo ra một điền dọc trong một linearLayout dọc và một điền ngang trong một linearLayout ngang:

<Space
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" />

@sepehr Phải có một yếu tố khác trong trường hợp bạn tìm thấy giải pháp của tôi không hoạt động. Tôi chỉ thử giải pháp của mình trong một bố cục mảnh, và nó cũng hoạt động ở đó.
stevehs17

trọng lượng được hỗ trợ trong bố trí tuyến tính và @sepehr chúng sẽ hoạt động theo từng mảnh, hoạt động, thông báo, hộp thoại;)
Jan Rabe

16

Bạn thậm chí không cần phải lồng relativebố cục thứ hai bên trong cái thứ nhất. Chỉ cần sử dụng android:layout_alignParentBottom="true"trong NútChỉnh sửa .


Chỉ cần lưu ý rằng mặc dù điều này hoạt động với Nút và Chỉnh sửa, nhưng nếu bạn đã cố căn chỉnh TableLayout theo cách này thì nó sẽ không hoạt động. Bạn sẽ phải lồng nó vào bên trong RelativeLayout khác.

11

Nếu bạn không muốn thực hiện nhiều thay đổi, thì bạn có thể chỉ cần đặt:

android:layout_weight="1"

đối với TextView có ID như @+id/TextViewnghĩa là

<TextView android:text="@string/welcome" 
    android:id="@+id/TextView" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:layout_weight="1">
</TextView>

Hoặc thêm một linearLayout xung quanh với android: layout_ weight = "1" - điều này cũng hoạt động tốt trong ScrollView!
bk138

7

Tạo cả đầu trangchân trang , đây là một ví dụ:

Bố cục XML

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/backgroundcolor"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:background="#FF0000">
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_alignParentBottom="true"
        android:background="#FFFF00">
    </RelativeLayout>

</RelativeLayout>

Ảnh chụp màn hình

Nhập mô tả hình ảnh ở đây


4

Sử dụng mã dưới đây. Căn chỉnh nút để mông. Nó đang hoạt động.

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

    <Button
        android:id="@+id/btn_back"
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:text="Back" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.97"
        android:gravity="center"
        android:text="Payment Page" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Submit"/>
    </LinearLayout>

</LinearLayout>

3

Đối với trường hợp như thế này, luôn luôn sử dụng RelativeLayouts. Một linearLayout không dành cho việc sử dụng như vậy.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/db1_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- Place your layout here -->

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:orientation="horizontal"
        android:paddingLeft="20dp"
        android:paddingRight="20dp" >

        <Button
            android:id="@+id/setup_macroSavebtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Save" />

        <Button
            android:id="@+id/setup_macroCancelbtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Cancel" />

        </LinearLayout>

</RelativeLayout>

2

Sử dụng android:layout_alignParentBottom="true" trong của bạn <RelativeLayout>.

Điều này chắc chắn sẽ giúp.


1
Điều đó giả định rằng người dùng muốn sử dụng RelativeLayout.
IgorGanapolsky 22/03/2016

2

Trong trường hợp bạn có một hệ thống phân cấp như thế này:

<ScrollView> 
  |-- <RelativeLayout> 
    |-- <LinearLayout>

Đầu tiên, áp dụng android:fillViewport="true"cho ScrollViewvà sau đó áp dụng android:layout_alignParentBottom="true"cho LinearLayout.

Điều này làm việc cho tôi hoàn hảo.

<ScrollView
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:scrollbars="none"
    android:fillViewport="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/linearLayoutHorizontal"
            android:layout_alignParentBottom="true">
        </LinearLayout>
    </RelativeLayout>
</ScrollView>

2

Bạn chỉ có thể cung cấp cho chế độ xem con hàng đầu của bạn (TextView @ + id / TextView ) một thuộc tính : android:layout_weight="1".

Điều này sẽ buộc tất cả các yếu tố khác bên dưới nó xuống dưới cùng.


2

Điều này có thể được thực hiện với một bố cục tuyến tính quá.

Chỉ cần cung cấp Chiều cao = 0dp và weight = 1 cho bố cục ở trên và bố cục bạn muốn ở phía dưới. Chỉ cần viết chiều cao = bọc nội dung và không có trọng lượng.

Nó cung cấp nội dung bao cho bố cục (cái có chứa văn bản và nút chỉnh sửa của bạn) và sau đó cái có trọng lượng chiếm phần còn lại của bố cục.

Tôi tình cờ phát hiện ra điều này.


0

Tôi đã sử dụng giải pháp mà Janusz đã đăng, nhưng tôi đã thêm phần đệm vào Chế độ xem cuối cùng vì phần trên cùng của bố cục của tôi là ScrollView.

ScrollView sẽ bị ẩn một phần khi nó phát triển cùng với nội dung. Sử dụng android:paddingBottomtrên Chế độ xem cuối giúp hiển thị tất cả nội dung trong ScrollView.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.