1. 程式人生 > >View元件及UI介面控制方法

View元件及UI介面控制方法

View及ViewGroup類介紹

簡介

Android應用的所有UI元件都繼承了View類,View元件非常類似於Swing程式設計中的JPanel,它代表了一個空白的矩形區域,View元件沒有任何內容。對於Android應用的其它UI元件來說,它們都繼承了View元件,然後在View元件提供的空白區域上繪製外觀

Android採用了”組合器“設計模式來設計View和ViewGroup,ViewGroup作為View的重要子類,通用作為其它元件的容器使用

自定義元件的方法

當Android系統提供的UI元件不足以滿足專案需要時,開發者可以通過繼承View來派生自定義元件。在自定義元件時,通常被重寫的方法(實際開發中只重寫部分

)如下:

  • 構造器。重寫構造器是定製View的最基本方式,當Java程式碼建立一個View例項或根據XML佈局檔案載入並構建介面時將需要呼叫該構造器。
  • onFinishInflate()。當應用從XML佈局檔案載入該元件並利用它來構建介面之後,該方法就會被回撥
  • onMeasure(int, int)。該方法用來檢測View元件及它所包含的所有子元件的大小。
  • onLayout(boolean, int, int, int, int)。當該元件需要分配其子元件的位置、大小時,該方法就會被回撥
  • onSizeChanged(int, int, int, int)。當該元件的大小被改變時回撥該方法。
  • onDraw(Canvas)。當該元件將要繪製它的內容時回撥該方法進行繪製。
  • onKeyDown(int, KeyEvent)。當某個鍵被按下時觸發該方法。
  • onKeyUp(int, KeyEvent)。當鬆開某個鍵時觸發該方法。
  • onTrackballEvent(MotionEvent)。當發生軌跡球事件時觸發該方法
  • onTouchEvent(MotionEvent)。當發生觸控式螢幕事件時觸發該方法
  • onWindowFocusChanged(boolean)。當該元件得到、失去焦點時觸發該方法。
  • onAttachedToWindow()。當把該元件放入某個視窗時觸發該方法。
  • onDetachedFromWindow()
    。當把該元件從某個視窗上分離時觸發該方法。
  • onWindowVisibilityChanged(int)。當包含該元件的視窗的可見性發生變化時觸發該方法。

UI介面控制方法

Android推薦使用XML佈局檔案來定義使用者介面,而不是使用Java程式碼來開發使用者介面。Android中控制組件的方式有如下兩種:

  • 在XML佈局檔案中通過XML屬性進行控制。
  • 在Java程式程式碼中通過呼叫方法進行控制。

上述兩種方法控制Android使用者介面行為的本質是一樣的,通常情況下,控制UI元件的XML屬性還有對應的方法。下面就對這兩種方法進行簡單介紹:

使用XML佈局檔案控制UI介面

Android推薦使用XML佈局檔案來控制檢視,這樣不僅簡單、明瞭,而且可以將應用的檢視控制邏輯從Java程式碼中分離出來,更好地體現了MVC原則

當應用在res/layout目錄下定義一個主檔名任意的XML佈局檔案之後,R.java會自動收錄此佈局資源。

setContentView(R.layout.<資原始檔名字>) //在Activity中顯示該檢視

findViewById(R.id.<android.id屬性值>) //通過ID獲取UI元件,之後就可以通過程式碼來控制此UI元件的外觀行為了(如為UI元件繫結事件監聽器等)。

在程式碼中控制UI介面

如果希望程式碼中控制UI介面,我們可以完全拋棄XML佈局檔案 ,而將所有的UI元件都通過new關鍵字創建出來,然後以合適的方式”搭建“在一起即可。

public class CodeView extends Activity {
    //當第一次建立該Activity時回撥該方法
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //建立一個線性佈局管理器
        LinearLayout layout = new LinearLayout(this);
        //設定該Activity顯示layout
        super.setContentView(layout);
        layout.setOrientation(LinearLayout.VERTICAL);
        //建立一個TextView
        final TextView show = new TextView(this);
        //建立一個按鈕
        Button bn = new Button(this);
        bn.setText(R.string.ok);
        bn.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));
        //向Layout容器中新增TextView
        layout.addView(show);
        //向Layout容器中新增按鈕
        layout.addView(bn);
        //為按鈕繫結一個事件監聽器
        bn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                show.setText("Hello, Android, " + new java.util.Date());
            }
        });
    }
}

完全在程式碼中控制UI介面不僅不利於高層次的解耦,而且由於通過new關鍵字來建立UI元件,需要呼叫方法來設定UI元件的行為,因此程式碼也顯得十分臃腫。相反,如果通過XML檔案來控制UI介面,開發者只要在XML佈局檔案中使用標籤即可建立UI元件,而且只要配置簡單的屬性即可控制UI元件的行為,因此要簡單得多。

使用XML佈局檔案和Java程式碼混合控制UI介面

完全使用程式碼來控制UI介面不僅煩瑣,而且不利於解耦;而完全利用XML佈局檔案來控制UI介面雖然方便、便捷,但難免有失靈活

當混合使用XML佈局檔案和程式碼來控制UI介面時,習慣上把變化 小、行為比較固定的元件放在XML佈局檔案中管理而那些變化較多、行為控制比較複雜的元件則交給Java程式碼來管理

我們可以通過先在佈局檔案中定義一個簡單的線性佈局容器,然後在程式獲取該容器,並往該容器中新增元件。此程式的功能是週期性展示定義在drawable下面的圖片,展示中觸發切換的操作是點選當前圖片。具體程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<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_width="match_parent"
    android:layout_height="match_parent"
    tools:context="miss.picturewall.PictureWall">

    <LinearLayout
        android:id="@+id/root"
        android:layout_width="368dp"
        android:layout_height="495dp"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="8dp"></LinearLayout>
</android.support.constraint.ConstraintLayout>
public class PictureWall extends AppCompatActivity {
    //定義一個訪問圖片的陣列
    int[] images = new int[]{
            R.drawable.jiajia,
            R.drawable.jiajia1,
            R.drawable.jiajia2,
            R.drawable.jiajia3,
            R.drawable.jiajia4,
            R.drawable.jiajia5
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //獲取LinearLayout佈局容器
        LinearLayout main = (LinearLayout)findViewById(R.id.root);
        //程式建立ImageView元件
        final ImageView image = new ImageView(this);
        //將ImageView元件新增到LinearLayout佈局容器中
        main.addView(image);
        //初始化時顯示第一張圖片
        image.setImageResource(images[0]);
        image.setOnClickListener(new View.OnClickListener() {
            int currentImg = 0;
            @Override
            public void onClick(View v) {
                currentImg = (currentImg + 1) % images.length;
                //改變ImageView裡顯示的圖片
                image.setImageResource(images[currentImg]);
            }
        });
    }
}

自定義元件例項

一個小球跟隨手指的程式。主要有以下三個檔案

<?xml version="1.0" encoding="utf-8"?>
<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_width="match_parent"
    android:layout_height="match_parent"
    tools:context="miss.fingerball.CustomView">

    <LinearLayout
        android:id="@+id/root"
        android:layout_width="368dp"
        android:layout_height="495dp"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="8dp"
        tools:layout_editor_absoluteY="8dp"></LinearLayout>
</android.support.constraint.ConstraintLayout>
public class BallView extends View {
    public float currentX = 40;
    public float currentY = 50;
    public BallView(Context context) {
        super(context);
    }
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //建立畫筆
        Paint p = new Paint();
        //設定畫筆顏色
        p.setColor(Color.RED);
        //繪製一個小球
        canvas.drawCircle(currentX, currentY, 15, p);
    }
}
public class CustomView extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LinearLayout root = (LinearLayout)findViewById(R.id.root);
        //建立BallView元件
        final BallView ball = new BallView(this);
        //設定自定義元件的最小寬度、高度
        ball.setMinimumWidth(root.getWidth());
        ball.setMinimumHeight(root.getHeight());
        //為ball元件繫結Touch事件
        ball.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //修改ball元件的currentX、currentY兩個屬性
                ball.currentX = event.getX();
                ball.currentY = event.getY();
                //通知ball元件重繪
                ball.invalidate();
                return true;
            }
        });
        root.addView(ball);
    }
}

摘自《瘋狂Android講義》