<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android動態改變布局

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

          

      其實是一個軟件的登錄界面,初始是第一個圖的樣子,當軟鍵盤彈出后變為第二個圖的樣子,因為登錄界面有用戶名、密碼、登錄按鈕,不這樣的話軟鍵盤彈出后會遮住登錄按鈕(其實之前的實現放到了ScrollView里面,監聽軟鍵盤彈出后滾動到底部,軟鍵盤隱藏后滾動到頂部,也是可以的)。

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

      先來看一下布局文件

      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/root"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:padding="20dp"
          tools:context="${packageName}.${activityClass}" >
      
          <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 {
      
          private View root; // 最外層布局
          private View logo; // Logo圖標
          private View label; // Logo附近的文字
      
          private int rootBottom = Integer.MIN_VALUE;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              root = findViewById(R.id.root);
              logo = findViewById(R.id.logo);
              label = findViewById(R.id.label);
              root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
      
                  @Override
                  public void onGlobalLayout() {
                      Rect r = new Rect();
                      root.getGlobalVisibleRect(r);
                      // 進入Activity時會布局,第一次調用onGlobalLayout,先記錄開始軟鍵盤沒有彈出時底部的位置
                      if (rootBottom == Integer.MIN_VALUE) {
                          rootBottom = r.bottom;
                          return;
                      }
                      // adjustResize,軟鍵盤彈出后高度會變小
                      if (r.bottom < rootBottom) {
                          RelativeLayout.LayoutParams lp = (LayoutParams) logo.getLayoutParams();
                          // 如果Logo不是水平居中,說明是因為接下來的改變Logo大小位置導致的再次布局,忽略掉,否則無限循環
                          if (lp.getRules()[RelativeLayout.CENTER_HORIZONTAL] != 0) {
                              // Logo顯示到左上角
                              lp.addRule(RelativeLayout.CENTER_HORIZONTAL, 0); // 取消水平居中
                              lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT); // 左對齊
      
                              // 縮小Logo為1/2
                              int height = logo.getHeight(); // getMeasuredHeight()
                              int width = logo.getWidth();
                              lp.width = width / 2;
                              lp.height = height / 2;
                              logo.setLayoutParams(lp);
      
                              // Logo下的文字
                              RelativeLayout.LayoutParams labelParams = (LayoutParams) label.getLayoutParams();
                              labelParams.addRule(RelativeLayout.CENTER_HORIZONTAL, 0); // 取消水平居中
                              labelParams.addRule(RelativeLayout.BELOW, 0); // 取消顯示到logo的下方
                              labelParams.addRule(RelativeLayout.RIGHT_OF, R.id.logo); // 顯示到Logo的右方
                              labelParams.addRule(RelativeLayout.CENTER_VERTICAL); // 垂直居中
                              label.setLayoutParams(labelParams);
                          }
                      } else { // 軟鍵盤收起或初始化時
                          RelativeLayout.LayoutParams lp = (LayoutParams) logo.getLayoutParams();
                          // 如果沒有水平居中,說明是軟鍵盤收起,否則是開始時的初始化或者因為此處if條件里的語句修改控件導致的再次布局,忽略掉,否則無限循環
                          if (lp.getRules()[RelativeLayout.CENTER_HORIZONTAL] == 0) {
                              // 居中Logo
                              lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
                              lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
      
                              // 還原Logo為原來大小
                              int height = logo.getHeight();
                              int width = logo.getWidth();
                              lp.width = width * 2;
                              lp.height = height * 2;
                              logo.setLayoutParams(lp);
      
                              // Logo下的文字
                              RelativeLayout.LayoutParams labelParams = (LayoutParams) label.getLayoutParams();
                              labelParams.addRule(RelativeLayout.CENTER_HORIZONTAL); // 設置水平居中
                              labelParams.addRule(RelativeLayout.BELOW, R.id.logo); // 設置顯示到Logo下面
                              labelParams.addRule(RelativeLayout.RIGHT_OF, 0); // 取消顯示到Logo右面
                              labelParams.addRule(RelativeLayout.CENTER_VERTICAL, 0); // 取消垂直居中
                              label.setLayoutParams(labelParams);
                          }
                      }
                  }
              });
          }
      }

      當Activity啟動時也會進行Layout,此時用rootBottom記錄了初始時最外層布局底部的位置,此后當軟鍵盤彈出時,布局被壓縮,再次獲取同一個View底部的位置,如果比rootBottom小說明軟鍵盤彈出了,如果大于或等于rootBottom說明軟鍵盤隱藏了。

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

      1. Activity啟動時會進行Layout,此時會調用onGlobalLayout,而且一般會調用兩次,這樣第二次時會進入else語句,要注意過濾
      2. 軟鍵盤彈出或隱藏時進入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) {
          mRules[verb] = TRUE;
          mInitialRules[verb] = TRUE;
          mRulesChanged = true;
      }
      
      public void addRule(int verb, int anchor) {
          mRules[verb] = anchor;
          mInitialRules[verb] = anchor;
          mRulesChanged = true;
      }

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

      public void removeRule(int verb) {
          mRules[verb] = 0;
          mInitialRules[verb] = 0;
          mRulesChanged = true;
       }

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

      posted @ 2014-07-11 09:17  AngelDevil  閱讀(42570)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 日本福利一区二区精品| 国产三级国产精品国产专区 | 欧美无人区码suv| 国产真人做受视频在线观看| 九九热爱视频精品| 欧洲码亚洲码的区别入口| 亚洲性猛交xxxx| 国产精品亚洲综合网一区| 欧美丰满熟妇xxxx性| 欧美性群另类交| 亚洲精品国产av成拍色拍个| 国产精品 无码专区| 成人无码午夜在线观看| 天堂网亚洲综合在线| 欧美丰满熟妇性xxxx| 精品国产精品午夜福利| 挺进粗大尤物人妻中文字幕| 高潮精品熟妇一区二区三区| 亚洲国产精品成人av网| 国产亚洲精品成人av久| 国内极度色诱视频网站| 少妇xxxxx性开放| 国产区成人精品视频| 久久久这里只有精品10| 欧美性猛交xxxx免费看| 久久精品国产亚洲av热一区 | 亚洲综合久久精品国产高清| 日本真人做爰免费视频120秒| 亚洲av天堂天天天堂色| 精品人妻日韩中文字幕| 国产精品三级中文字幕| 免费国产拍久久受拍久久| 欧美一级高清片久久99| 成人午夜视频在线| 成年女人免费视频播放体验区| 久久综合国产精品一区二区| 大陆精大陆国产国语精品| 亚洲综合在线日韩av| 亚洲av无码一区二区三区网站| 野花香视频在线观看免费高清版| 久久精品日日躁夜夜躁|