Android中重溫自定義控件04----onLayout設置子佈局的位置

一般在繼承 ViewGroup 的時候,重寫 onLayout 方法,設置子佈局的位置
這個例子是設置 offsetLayout 子佈局的位置
效果圖如下:


實現步驟:
1.自定義控件 OffsetLayout

package com.zhh.android;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;

/**
 * onLayout 設置子佈局的位置
 * Created by 16838 on 2019/6/1.
 */

public class OffsetLayout extends AbsoluteLayout {


    private int mOffsetHorizontal = 0; // 水平方向的偏移量
    private int mOffsetVertical = 0; // 垂直方向的偏移量

    public OffsetLayout(Context context) {
        super(context);
    }

    public OffsetLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // 重寫onLayout方法,意在調整下級視圖的方位
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i); // 獲得第i個子視圖
            if (child.getVisibility() != GONE) {
                // 計算子視圖的左邊偏移數值
                int new_left = (r - 1) / 2 - child.getMeasuredWidth() / 2 + mOffsetHorizontal;
                // 計算子視圖的上方偏移數值
                int new_top = (b - t) / 2 - child.getMeasuredHeight() / 2 + mOffsetVertical;
                // 根據最新的上下左右四周邊界,重新放置該子視圖
                child.layout(new_left, new_top,
                        new_left + child.getMeasuredWidth(), new_top + child.getMeasuredHeight());
            }
        }
    }

    // 設置水平方向上的偏移量
    public void setOffsetHorizontal(int offset) {
        mOffsetHorizontal = offset;
        mOffsetVertical = 0;
        // 請求重新佈局,此時會觸發onLayout方法
        requestLayout();
    }

    // 設置垂直方向上的偏移量
    public void setOffsetVertical(int offset) {
        mOffsetHorizontal = 0;
        mOffsetVertical = offset;
        // 請求重新佈局,此時會觸發onLayout方法
        requestLayout();
    }
}

2.在佈局文件 activity_main.xml 中引用 OffsetLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp" >

        <TextView
            android:id="@+id/tv_offset"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:gravity="center"
            android:text="偏移大小:"
            android:textColor="#000"
            android:textSize="17sp" />

        <Spinner
            android:id="@+id/sp_offset"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toRightOf="@+id/tv_offset"
            android:gravity="left|center"
            android:spinnerMode="dialog" />
    </RelativeLayout>

    <com.zhh.android.OffsetLayout
        android:id="@+id/offsetLayout"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="#00ff00" >

        <View
            android:layout_width="200dp"
            android:layout_height="100dp"
            android:background="#000000" />
    </com.zhh.android.OffsetLayout>

</LinearLayout>

3.在 MainActivity 設置  OffsetLayout 的位置

package com.zhh.android;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

/**
 *  onLayout 設置子佈局的位置
 */
public class MainActivity extends Activity {
//  展示偏移的數組
    private String[] descArray = {"無偏移", "向左偏移50", "向右偏移50", "向上偏移50", "向下偏移50"};
//  設置實際偏移的數組
    private int[] offsetArray = {0, -50, 50, -50, 50};

//  自定義的佈局,設置其子佈局的位置
    private OffsetLayout offsetLayout; // 聲明一個偏移佈局對象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 從佈局文件中獲取名叫ol_content的偏移佈局
        offsetLayout = findViewById(R.id.offsetLayout);
        initOffsetSpinner();
    }

    // 初始化偏移大小的下拉框
    private void initOffsetSpinner() {
        Spinner sp_offset = findViewById(R.id.sp_offset);
//      綁定適配器
        ArrayAdapter<String> offsetAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_expandable_list_item_1, descArray);
        sp_offset.setAdapter(offsetAdapter);
//      條目監聽事件
        sp_offset.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                int offset = dip2px(MainActivity.this, offsetArray[position]);
                if (position == 0 || position == 1 || position == 2) {
                    // 設置偏移佈局在水平方向上的偏移量
                    offsetLayout.setOffsetHorizontal(offset);
                } else if (position == 3 || position == 4) {
                    // 設置偏移佈局在垂直方向上的偏移量
                    offsetLayout.setOffsetVertical(offset);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

    }


    // 根據手機的分辨率從 dp 的單位 轉成爲 px(像素)
    public static int dip2px(Context context, float dpValue) {
        // 獲取當前手機的像素密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f); // 四捨五入取整
    }



}

源碼下載:
TestCustom ---- app4
https://download.csdn.net/download/zhaihaohao1/11224806​​​​​​​​​​​​​​

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章