1. 程式人生 > >android view層次與位置大小

android view層次與位置大小

1、改變層次

首先要明白,android的層次由擺放view的先後順序決定,也就是addView中的index,0表示最下面,越大越上面,不會超過容器的包含的View個數,(因為是陣列下標)。

1、所以需要第一種方法,是最原始的方法。將一個view remove掉然後再加入進來,因為越後面加入的view,在越下面。

如下程式碼展示瞭如何交換兩個ImageView的層次。

                int screen_w = getResources().getDisplayMetrics().widthPixels;
                int screen_h = getResources().getDisplayMetrics().heightPixels;
                mContent.removeAllViews();
                RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams();
                RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams();
                mExample1 = new ImageView(MainActivity.this);
                mExample2 = new ImageView(MainActivity.this);
                mExample1.setImageResource(R.drawable.example_h);
                mExample2.setImageResource(R.drawable.example_v);
                layout(layoutParams1, layoutParams2);
                if (mExample2OnTop) {
                    layoutParams1.width = screen_w / 4;
                    layoutParams1.height = screen_h / 4;

                    layoutParams2.width = screen_w;
                    layoutParams2.height = screen_h;

                    mExample1.setLayoutParams(layoutParams1);
                    mExample2.setLayoutParams(layoutParams2);

                    mContent.addView(mExample2);
                    mContent.addView(mExample1);

                    mExample2OnTop = false;
                } else {
                    layoutParams1.width = screen_w;
                    layoutParams1.height = screen_h;

                    layoutParams2.width = screen_w / 4;
                    layoutParams2.height = screen_h / 4;

                    mExample1.setLayoutParams(layoutParams1);
                    mExample2.setLayoutParams(layoutParams2);

                    mContent.addView(mExample1);
                    mContent.addView(mExample2);

                    mExample2OnTop = true;
                }

                mExample2.setOnClickListener(ImageSwitchListener);
                mExample1.setOnClickListener(ImageSwitchListener);
mContent為父容器,先用removeAllViews將所有view去除,然後使用addView將View再新增,注意在if和else裡面 新增兩個View的順序。layoutParam為位置view大小的方法,在實驗中,樓主遇到一個問題,就是重新新增後兩個View不能點選,換成Button發現不是狀態的問題,完全沒有點選效果,只有按Home鍵退出後,View才會響應OnClick事件,但是重新新增後又不能點選,重新New一個就OK了,懷疑是remove後是不是有些私有狀態不對了。只有OnResume之後,恢復了過來,樓主沒有深入研究,所以就新建了一下,重新設定引數。也算規避掉了,望知情人士提供線索。這種方法實際應用意義不大,又要重新new,又要remove和add。開銷蠻大的。 樓主後來想了下,可能後AttachWindow的原因比較大,onResume之後重新AttachWindow所以按鍵效果就出來了。 於是介紹下一種方法 bringToFront()
                int screen_w = getResources().getDisplayMetrics().widthPixels;
                int screen_h = getResources().getDisplayMetrics().heightPixels;
                RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams();
                RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams();
                layout(layoutParams1, layoutParams2);
                mContent.requestLayout();
                if (mExample2OnTop) {
                    layoutParams1.width = screen_w / 4;
                    layoutParams1.height = screen_h / 4;

                    layoutParams2.width = screen_w;
                    layoutParams2.height = screen_h;

                    mExample1.setLayoutParams(layoutParams1);
                    mExample2.setLayoutParams(layoutParams2);

                    mExample1.bringToFront();

                    mExample2OnTop = false;
                } else {
                    layoutParams1.width = screen_w;
                    layoutParams1.height = screen_h;

                    layoutParams2.width = screen_w / 4;
                    layoutParams2.height = screen_h / 4;

                    mExample1.setLayoutParams(layoutParams1);
                    mExample2.setLayoutParams(layoutParams2);

                    mExample2.bringToFront();

                    mExample2OnTop = true;
                }
bringToFront起到了相同的作用,因為bringToFront將view的index設定為最大,內部只是調整了view結構樹的層次,而不是remove和add。減小了開銷。是目前比較常用的方法 也許有人會用到,bringToFront之後再重新調整到原來位置,這裡提供一份程式碼。
private void moveToBack(View currentView) {
    ViewGroup viewGroup = ((ViewGroup) currentView.getParent());
    int index = viewGroup.indexOfChild(currentView);
    for(int i = 0; i<index; i++) {
        viewGroup.bringChildToFront(viewGroup.getChildAt(i));
    }
}

3、在android5.0 api引入一個setZ(float)的函式,也可以調整view的層次。聽說原理是相當於修改translationZ的屬性(就是在3.0還是4.0引入的RotateXY,ScaleXY,TranslationXY之類的屬性。)。全部程式碼不貼了,只看關鍵程式碼
                if (mExample2OnTop) {
                //                    mExample1.bringToFront();
                    mExample1.setZ(100.f);
                    mExample2.setZ(0.f);
                    mExample2OnTop = false;
                } else {
//                    mExample2.bringToFront();
                    mExample1.setZ(0.f);
                    mExample2.setZ(100.f);

                    mExample2OnTop = true;
                }
這個介面比較新。作用是體現出來了。但是副作用還不知道。

2、在程式碼中動態調整view的大小。 大部分情況下,View的大小在xml中已經定好了,不會在執行中動態調整,但是萬一遇到一些需求需要在執行中調整view的大小呢 這個比層次簡單,基本上就是修改LayoutParams

不過需要注意的是,需要注意到父容器是什麼型別的,FrameLayout,LinearLayout,RelativeLayout等,因為不同型別的LayoutParams是不同的

</pre><pre class="java" name="code">    private void layout(RelativeLayout.LayoutParams layoutParams1, RelativeLayout.LayoutParams layoutParams2) {
        layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
    }
請看,上面一些屬性是隻有RelativeLayout才有的。所以這就是為什麼要區分父容器型別的原因。

下面是如何修改View大小的程式碼

                    RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams();
                    RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams();
                    
                    layoutParams1.width = screen_w / 4;
                    layoutParams1.height = screen_h / 4;

                    layoutParams2.width = screen_w;
                    layoutParams2.height = screen_h;

                    mExample1.setLayoutParams(layoutParams1);
                    mExample2.setLayoutParams(layoutParams2);
這樣就好了,連invalidate或者requestLayout都不需要呼叫。因為內部自己會呼叫。 題外話,如果需要addView的話,那麼使用getLayoutParams是沒用的,因為這個你自己新建的一個View,沒有與父容器有任何關聯。所以LayoutParams也需要你自己建立。
        mExample1 = new Button(this);
        mExample2 = new Button(this);

        RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(screen_w, screen_h);
        RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(screen_w / 4, screen_h / 4);

        layout(layoutParams1, layoutParams2);

        mExample1.setLayoutParams(layoutParams1);
        mExample2.setLayoutParams(layoutParams2);

        mContent.addView(mExample1);
        mContent.addView(mExample2);

相關推薦

android view層次位置大小

1、改變層次 首先要明白,android的層次由擺放view的先後順序決定,也就是addView中的index,0表示最下面,越大越上面,不會超過容器的包含的View個數,(因為是陣列下標)。 1、所以需要第一種方法,是最原始的方法。將一個view remove掉然後再加入

android-View.postHandler.post的區別

View.postDelayed package android.view; public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility

android View.getLeft() View.getScrollX()

當呼叫一個View的 void scrollTo (int x, int y) 方法 移動view後:  View.getLeft() 獲取的值是沒有變化的,仍然是最開始的值:左邊相對於父控制元件的距離。 View.getScrollX()獲取的值則發生了變化:指呼叫的

Android自定義控制元件熱身——View的座標位置大小詳解

在自定義控制元件中我們經常會用到View位置的騰挪移動,今天就來和大家一塊揭開View座標位置的神祕面紗。 android中View的座標系統 :螢幕的左上角View繪製區是座標系統原點(0,0),原點向右延伸是X軸正方向,原點向下延伸是Y軸正方向。 螢幕高度=狀態列高

android ViewViewGroup研究

View 有一個屬性為 mParent(ViewParent型) View 有一個屬性為 mLayoutParams(ViewGroup.LayoutParams型) 無論是 mParent還是mLayoutParams 都是在系統在解析 XML 時自動進行初始化的. ViewGro

2、 Android viewviewgroup

Android的基本元件 1.1 Activity 1.1.1 Activity代表手機的一個螢幕 1.1.2 一個Android程式由多個Activity組成,即:一個Android程式由多屏內容組成 1.1.3 Activity相當於一個展板,本身沒有可

android進階4step1:Android動畫處理自定義View——SurfaceView

SurfaceView簡介 1、SurfaceView與View的區別 2、SurfaceView的具體使用場景 3、如何使用SurfaceView 一、SurfaceView與View的區別 1、不使用onDraw 2、非UI執行緒繪製 3、獨立

android進階4step1:Android動畫處理自定義View——自定義View

為什麼要自定義控制元件 特定的顯示風格 處理特有的使用者互動 優化我們的佈局 封裝等... 如何自定義控制元件 自定義屬性的宣告與獲取 測量onMeasure 繪製onDraw 狀態的儲存與恢復 步驟一、自定義屬性宣告與獲取

android進階4step1:Android動畫處理自定義View——轉場動畫

以下都需要執行在5.0以上 一、揭露動畫效果 參考:使用Circular Reveal為你的應用新增揭露動畫效果 最主要的類Circular Reveal 官方將這一動畫稱為揭露效果,它在官網中的描述是這樣的: 當您顯示或隱藏一組 UI 元素時,揭露動畫可為使用者提供視覺

Android Studio設定程式碼字型大小介面字型樣式

前言 使用android studio第一步肯定就是設定字型大小了,廢話不多說,直接上教程: 初始介面: 更改後介面: 目錄 更改程式碼字型大小 更改介面字型大小及樣

Android Framework 深入淺出-HAL, Binder, View System Native Service

     Android 的 HAL (硬體抽像層)是 Google 因應廠商“希望不公開原始碼”(就是為了避開linux kernel的GPL license的束縛)的要求下,所推出的新觀念。HAL 的目的是為了把 Android framework 與 Linux ke

Android 自定義View——分類流程

1.View 分類與流程 1.1View 分類 1.自定義ViewGroup 自定義ViewGroup一般是利用現有的元件根據特定的佈局方式來組成新的元件,大多繼承自ViewGroup或各種Layout,包含有子View。 ViewGroup 及它

快速理解android View的測量onMeasure()MeasureSpec

筆者之前有一篇文章已經使用onMeasure()解決了listview與scollview的顯示衝突問題,部落格地址如下: 在此就針對View的測量以及onMeasure()涉及的幾個問題做一個詳細解釋: 一、MeasureSpec的概念: MeasureSpe

Android同一裝置DPI數值大小顯示大小的關係

  今天在用genymotion模擬器時,發現在相同解析度(720*1280)下有不同的dpi,於是好奇地啟動了一下不同的dpi,竟然發現在相同解析度下dpi越大,顯示的內容越大,相同的內容竟然顯示不全了。這與window顯示解析度正好相反。 這是720*1

drawablemipmap的區別(android資原始檔放置位置

今天在網上瀏覽部落格,看到這一個問題,我們的圖片資源到底放在drawable還是mipmap目錄中,網上的爭議很大, 今天打算就我的觀點說一下這個問題,如果我的回答讓大神們有所質疑,希望多多提點。 首先我們應該知道他們的意義: 1.Drawable Android

android RadioButton 文字圖示的位置

<RadioButton android:id="@+id/button1" android:layout_width="fill_parent" android:layout_hei

Android View系統分析之三Activity的啟動顯示

前言在Android View系統分析之從setContentView說開來(一)與Android View系統分析之二View與ViewGroup中我們已經簡單介紹了一個Activity的UI內容與檢視樹的組成關係,即View與ViewGroup組成了Activity的視覺

Android View事件(四)】View滑動實現滑動的幾種方法

1 前言 在前面的幾篇文章,我向大家介紹的都是單一View事件,而在這篇文章中,我將向大家介紹連續的事件 —— 滑動。 在安卓裝置上滑動幾乎是應用的標配,由於安卓手機螢幕較小,為了給使用者呈現更多的內容,就需要使用滑動來隱藏和顯示一些內容。

Android下載檔案實際檔案大小不一致,開啟失敗

問題的解決辦法是:檔案請求地址的中文 檔名需要進行轉碼 UploadFile/從保護模式到段_20140103101409.pdf UploadFile/%E4%BB%8E%E4%BF%9D%E6%8A%A4%E6%A8%A1%E5%BC%8F%E5%88%B0%E6%