Android 百分比布局揭秘
来源:互联网 发布:win10网络受限怎么办 编辑:程序博客网 时间:2024/05/16 13:43
这是一个百分比布局实例,github 地址是 android-percent-support-lib-sample
下面是自己参考其代码,实现的一个简易百分比布局,没有什么实际作用,只是在理解google官方如何实现。
步骤如下(下面源码版本是2.3):
1、任意继承一个容器如LinearLayout,ReleativeLayout或FrameLayout。
2、重写generateLayoutParams方法,布局被解析时会被调用,需要返回一个LayoutParams对象。
话说此方法是在LayoutInflater类的inflate方法中调用,也就是通过setContentView传进去的布局,最终调用PhoneWindow的installDecor方法,继而调用LayoutInflater类的inflate方法。
private LayoutInflater mLayoutInflater;private void installDecor() {if (mDecor == null) {mDecor = generateDecor();mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);mDecor.setIsRootNamespace(true);}if (mContentParent == null) {mContentParent = generateLayout(mDecor);}}protected ViewGroup generateLayout(DecorView decor) {int layoutResource;View in = mLayoutInflater.inflate(layoutResource, null);decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));//id为content的viewViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);return contentParent;}
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { View result = root; try { int type; final String name = parser.getName(); if (TAG_MERGE.equals(name)) { if (root == null || !attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } rInflate(parser, root, attrs, false); } else { View temp; if (TAG_1995.equals(name)) { temp = new BlinkLayout(mContext, attrs); } else { temp = createViewFromTag(root, name, attrs); } ViewGroup.LayoutParams params = null; if (root != null) { // Create layout params that match root, if supplied params = root.generateLayoutParams(attrs); if (!attachToRoot) { temp.setLayoutParams(params); } } // Inflate all children under temp rInflate(parser, temp, attrs, true); // We are supposed to attach all the views we found (int temp)to root. Do that now. if (root != null && attachToRoot) { root.addView(temp, params); } if (root == null || !attachToRoot) { result = temp; } } } finally { } return result; } }
3、自定义LayoutParams类继承自LinearLayout.LayoutParams,通过AttributeSet类获取布局里面定义的属性值并解析。
<declare-styleable name="ParcentLayout"> <attr name="parcentWidth" format="float" /> <attr name="parcentHeight" format="float" /> <attr name="parcentTextSize" format="string" /> </declare-styleable>
4、重写onMeasure计算布局的尺寸,循环view获取自定义的LayoutParams对象,重新给view设置高度和宽度。
5、如果是TextView,适配字体大小。
public class PercentLinearLayout extends LinearLayout {private static final String REGEX_PERCENT = "^(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)%([s]?[wh]?)$";public PercentLinearLayout(Context context) {super(context);}public PercentLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}private static final String TAG = "PercentLinearLayout";@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);int tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,heightMode);int widthSize = View.MeasureSpec.getSize(widthMeasureSpec);int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);int tmpWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize,widthMode);// 处理ScrollViewif (heightMode == MeasureSpec.UNSPECIFIED && getParent() != null&& (getParent() instanceof ScrollView)) {int baseHeight = 0;Context context = getContext();if (context instanceof Activity) {Activity act = (Activity) context;//获取 PhoneWindow类中DecorView(继承FrameLayout)的根View的高度int measuredHeight = act.findViewById(android.R.id.content).getMeasuredHeight();baseHeight = measuredHeight;} else {baseHeight = getScreenHeight();}tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(baseHeight,heightMode);}int width = View.MeasureSpec.getSize(tmpWidthMeasureSpec);int height = View.MeasureSpec.getSize(tmpHeightMeasureSpec); Log.d(TAG, "width = " + width + " , height = " + height);//获取子View并设置其宽度和高度int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View view = getChildAt(i);LayoutParams params = (LayoutParams) view.getLayoutParams();float widthp = 0;float heightp = 0;if (params instanceof PercentLinearLayout.LayoutParams) {widthp = params.w;heightp = params.h;}if (widthp != 0) {params.width = (int) (width * widthp);}if (heightp != 0) {params.height = (int) (height * heightp);}//设置文字大小if (params.hasParcentTextSize) {supportTextSize(width,height,view,params.parcentTextSize);}} super.onMeasure(widthMeasureSpec, heightMeasureSpec);}/** * 该方法在LayoutInflater类的inflate方法中调用 */@Overridepublic android.widget.LinearLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {Log.i(TAG, "generateLayoutParams method execute ... ");return new PercentLinearLayout.LayoutParams(getContext(), attrs);}public static class LayoutParams extends LinearLayout.LayoutParams {public float h;public float w;public String parcentTextSize ;public boolean hasParcentTextSize=false;public LayoutParams(Context context, AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ParcentLayout);w = a.getFloat(R.styleable.ParcentLayout_parcentWidth, -1);h = a.getFloat(R.styleable.ParcentLayout_parcentHeight, -1);parcentTextSize = a.getString(R.styleable.ParcentLayout_parcentTextSize);if (w < 0) {w = 0;}if (w > 1) {w = 1;}h = h < 0 ? 0 : h;h = h > 1 ? 1 : h;if (!TextUtils.isEmpty(parcentTextSize)) {hasParcentTextSize = true;}a.recycle();}}/** * 设置文字大小 * @param widthHint 宽度 * @param heightHint 高度 * @param view * @param percentStr 百分比字符串(20%w) */private void supportTextSize(int widthHint, int heightHint, View view,String percentStr) {Pattern p = Pattern.compile(REGEX_PERCENT);Matcher matcher = p.matcher(percentStr);if (!matcher.matches()) {throw new RuntimeException("the value of layout_xxxPercent invalid! ==>" + percentStr);}int len = percentStr.length();// extract the float valueString floatVal = matcher.group(1);float percent = Float.parseFloat(floatVal) / 100f;int base = 0;if (percentStr.endsWith("w")) {base = view.getMeasuredWidth();} else if (percentStr.endsWith("h")) {base = view.getMeasuredHeight();}float textSize = (int) (base * percent);System.out.println("ss "+textSize);// Button 和 EditText 是TextView的子类if (view instanceof TextView) {((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);}}private int getScreenHeight() {WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(outMetrics);return outMetrics.heightPixels;}}
<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" > <com.example.zzl.viewgroup.PercentLinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="0dp" android:layout_height="0dp" android:background="#ff44aacc" android:gravity="center" android:text="width:55%,height:5%,ts:60%h" android:textColor="#ffffff" app:parcentHeight="0.05" app:parcentTextSize="60%h" app:parcentWidth="0.55" /> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="20dip" android:background="#ff99aacc" android:gravity="center" android:text="width:75%,height:20%,ts:40%h" android:textColor="#ffffff" app:parcentHeight="0.1" app:parcentTextSize="40%h" app:parcentWidth="0.75" /> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="20dip" android:background="#ff4455cc" android:gravity="center" android:text="width:90%,height:30%,ts:20%h" android:textColor="#ffffff" app:parcentHeight="0.2" app:parcentTextSize="20%h" app:parcentWidth="0.9" /> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="20dip" android:background="#ff44aa77" android:gravity="center" android:text="width:100%,height:40%,ts:10%h" android:textColor="#ffffff" app:parcentHeight="0.4" app:parcentTextSize="10%h" app:parcentWidth="1" /> </com.example.zzl.viewgroup.PercentLinearLayout></ScrollView>
0 0
- Android 百分比布局揭秘
- Android 支持百分比布局
- Android支持百分比布局
- Android百分比布局初探
- Android百分比布局:PercentRelativeLayout
- Android百分比布局:PercentFrameLayout
- Android 百分比布局
- android 百分比layout布局
- Android百分比布局
- android 百分比布局
- Android 百分比布局库
- Android 自定义百分比布局
- Android百分比布局
- android中的百分比布局
- Android百分比布局:PercentFrameLayout
- Android百分比布局:PercentRelativeLayout
- android百分比布局
- Android中的百分比布局
- VC CArray
- Activiti学习——整合ActivitiModeler到项目中
- Android HandlerThread 完全解析
- 树莓派下的基本命令和安装MySQL vim等
- Android NDK(二)最最简单的方法利用NDK实现MP3录音
- Android 百分比布局揭秘
- JZOJ1241. Number
- 获取系统的默认编码
- 同余与乘法逆元
- JAVA 的垃圾回收机制
- 6个Java项目UML反向工程工具
- HTTP请求和响应
- Java程序员修炼之道 之 Logging(2/3) - 怎么写Log
- 编译链接基本素养笔记(一)ELF文件结构