一般在繼承 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