Android動態改變布局

2021-07-05 12:13:11 字數 3870 閱讀 2664

遇到這麼個需求,先看圖:

其實是乙個軟體的登入介面,初始是第乙個圖的樣子,當軟鍵盤彈出後變為第二個圖的樣子,因為登入介面有使用者名稱、密碼、登入按鈕,不這樣的話軟鍵盤彈出後會遮住登入按鈕(其實之前的實現放到了scrollview裡面,監聽軟鍵盤彈出後滾動到底部,軟鍵盤隱藏後滾動到頂部,也是可以的)。

最簡單的方法就是多加幾個冗餘的view,根據軟鍵盤的狀態隱藏不需要的view,顯示需要的view,但這樣感覺太挫了,然後就想起了前兩年研究的relativelayout布局,relativelayout中子控制項的布局都是相對位置,只需要在軟鍵盤彈出隱藏時改變應用的位置規則就行了。

先來看一下布局檔案

<

relativelayout

xmlns:android

=""xmlns:tools

=""android:id

="@+id/root"

android:layout_width

="match_parent"

android:layout_height

="match_parent"

android:padding

="20dp"

tools:context

="$.$"

>

<

relativelayout

android:id

="@+id/container"

android:layout_width

="match_parent"

android:layout_height

="wrap_content"

android:layout_alignparenttop

="true"

>

<

imageview

android:id

="@+id/logo"

android:layout_width

="150dp"

android:layout_height

="150dp"

android:layout_centerhorizontal

="true"

android:scaletype

="centercrop"

android:src

="@drawable/ic_launcher"

tools:ignore

="contentdescription"

/>

<

textview

android:id

="@+id/label"

android:layout_width

="wrap_content"

android:layout_height

="wrap_content"

android:layout_below

="@id/logo"

android:layout_centerhorizontal

="true"

android:layout_marginleft

="10dp"

android:layout_margintop

="10dp"

android:text

="@string/hello_world"

android:textsize

="20sp"

/>

relativelayout

>

<

edittext

android:id

="@+id/input"

android:layout_width

="match_parent"

android:layout_height

="wrap_content"

android:layout_below

="@id/container"

android:layout_margin

="16dp"

android:hint

="input sth."

tools:ignore

="hardcodedtext"

/>

relativelayout

>

軟鍵盤的彈出隱藏用ongloballayoutlistener監聽實現,對activity應用android:windowsoftinputmode="statehidden|adjustresize",這樣開始時軟鍵盤不顯示,當軟鍵盤彈出時布局被resize。

接下來是**,所有的**都在這裡了

public

class mainactivity extends

activity

//adjustresize,軟鍵盤彈出後高度會變小

if (r.bottom

} else }}

});}

}

當activity啟動時也會進行layout,此時用rootbottom記錄了初始時最外層布局底部的位置,此後當軟鍵盤彈出時,布局被壓縮,再次獲取同乙個view底部的位置,如果比rootbottom**明軟鍵盤彈出了,如果大於或等於rootbottom說明軟鍵盤隱藏了。

所有的**都在上面,也有詳細注釋,有兩點需要注意一下:

activity啟動時會進行layout,此時會呼叫ongloballayout,而且一般會呼叫兩次,這樣第二次時會進入else語句,要注意過濾

軟鍵盤彈出或隱藏時進入ongloballayout,此時根據需要縮放logo的大小,並改變logo和label的位置,這些操作會引起再次ongloballayout,需要將之後的ongloballayout過濾掉,不然就無限迴圈了。

可以看到上面**中的過濾條件,以else語句中的為例,activity啟動時會進入else,此時logo是水平居中狀態,會跳過else裡面的if語句,這樣就處理掉了第一種情況。

當因為軟鍵盤收起進入else時,logo已經因為if語句塊變為了顯示在左上角,所以會進入else中的if語句,重新改變logo為水平居中,由於修改了logo的大小和位置,會導致再次進入ongloballayout,仍是進入else,但此時已經設定logo為水平居中了,不會再次進入else中的if語句,這樣通過乙個條件判斷就處理了上面提到的兩點注意事項。

關於addrule

relativelayout中每乙個子控制項所應用的規則都是通過陣列儲存的,如下所示:

public

static

final

int true = -1;

public

void addrule(int

verb)

public

void addrule(int verb, int

anchor)

以某一規則的索引為下標,值就是規則對應的anchor,如果是相對於另乙個子控制項,值就是另乙個子控制項的id,如果是相對于父控制項,值就是`true`,即-1,如果沒有應用某一規則值就是0,可以看到,removerule就是把相應位置的值改為了0:

public

void removerule(int

verb)

removeruleapi 17才加的方法,為了在api 17前也能使用,可以使用它的等價方法,像上面的例子中的一樣,使用addrule(verb, 0)

Android動態改變布局

遇到這麼個需求,先看圖 其實是乙個軟體的登入介面,初始是第乙個圖的樣子,當軟鍵盤彈出後變為第二個圖的樣子,因為登入介面有使用者名稱 密碼 登入按鈕,不這樣的話軟鍵盤彈出後會遮住登入按鈕 其實之前的實現放到了scrollview裡面,監聽軟鍵盤彈出後滾動到底部,軟鍵盤隱藏後滾動到頂部,也是可以的 最簡...

Android動態改變布局

遇到這麼個需求,先看圖 其實是乙個軟體的登入介面,初始是第乙個圖的樣子,當軟鍵盤彈出後變為第二個圖的樣子,因為登入介面有使用者名稱 密碼 登入按鈕,不這樣的話軟鍵盤彈出後會遮住登入按鈕 其實之前的實現放到了scrollview裡面,監聽軟鍵盤彈出後滾動到底部,軟鍵盤隱藏後滾動到頂部,也是可以的 最簡...

Android 動態布局

android 動態布局 絕對布局 absolutelayout abslayout new absolutelayout this setcontentview abslayout button btn1 new button this btn1.settext this is a button ...