android-percent-support-lib-sample
来源:互联网 发布:淘宝会员名有什么用处 编辑:程序博客网 时间:2024/06/05 05:14
我们做Android开发,经常会遇到适配的问题!同一个界面,在不同的分辨率的手机上会有不同的显示效果。
为了解决这个问题,我们在标明控件的高宽的时候。通常会用到dp作为单位。dp*density(像素密度)/160=px;这就保证了
用dp确定高宽的控件在不同的分辨率的手机上我固定的大小。在合适大小的手机屏幕上,当然没问题。但是如果手机屏幕过
大或者过小都会有些不合适。现在github上发现一个开源项目:android-percent-support-lib-sample。定义了两个新的控件:
PercentRelativeLayout,和PercentFrameLayout。能够在通过设置子控件的高宽的百分比。来使得子控件在不同分辨率的手机上保持
相对大小。提供了一个很好的解决适配问题的思路!
下面介绍一下他们的用法:
<com.wang.percentlayout.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:wang="http://schemas.android.com/apk/res/com.wang.percentlayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.wang.percentlayout.MainActivity" > <TextView android:id="@+id/tv_left" android:layout_width="0dp" android:layout_height="0dp" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:background="#44ff0000" android:text="width:30%,height:30%" android:gravity="center" wang:layout_widthPercent="30%" wang:layout_heightPercent="30%"/> <TextView android:id="@+id/tv_below" android:layout_width="0dp" android:layout_height="0dp" android:layout_below="@id/tv_left" android:layout_alignParentLeft="true" android:background="#440ff000" android:text="width:40%,height:50%" android:gravity="center" wang:layout_widthPercent="40%" wang:layout_heightPercent="50%"/> <TextView android:id="@+id/tv_right" android:layout_width="0dp" android:layout_height="0dp" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:background="#4400ff00" android:gravity="center" android:text="width:70%,height:20%" wang:layout_widthPercent="70%" wang:layout_heightPercent="20%"/> <TextView android:id="@+id/tv_below_right" android:layout_width="0dp" android:layout_height="0dp" android:layout_below="@id/tv_right" android:layout_alignParentRight="true" android:background="#44000ff0" android:text="width:20%,height:60%" android:gravity="center" wang:layout_widthPercent="20%" wang:layout_heightPercent="60%"/> <TextView android:id="@+id/tv_bottom" android:layout_width="0dp" android:layout_height="0dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:background="#770000ff" android:gravity="center" android:text="width:100%,height:20%" wang:layout_widthPercent="100%" wang:layout_heightPercent="20%"/></com.wang.percentlayout.PercentRelativeLayout>
效果图
那么PercentRelativieLayout相对RelativeLayout又多做了哪些工作呢?
我们看一下源码:
/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.wang.percentlayout;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.ViewGroup;import android.widget.RelativeLayout;/** * Subclass of {@link RelativeLayout} that supports percentage based dimensions and * margins. * * You can specify dimension or a margin of child by using attributes with "Percent" suffix. Follow * this example: * * <pre class="prettyprint"> * <android.support.percent.PercentRelativeLayout * 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"/> * <ImageView * app:layout_widthPercent="50%" * app:layout_heightPercent="50%" * app:layout_marginTopPercent="25%" * app:layout_marginLeftPercent="25%"/> * </android.support.percent.PercentFrameLayout/> * </pre> * * The attributes that you can use are: * <ul> * <li>{@code layout_widthPercent} * <li>{@code layout_heightPercent} * <li>{@code layout_marginPercent} * <li>{@code layout_marginLeftPercent} * <li>{@code layout_marginTopPercent} * <li>{@code layout_marginRightPercent} * <li>{@code layout_marginBottomPercent} * <li>{@code layout_marginStartPercent} * <li>{@code layout_marginEndPercent} * </ul> * * It is not necessary to specify {@code layout_width/height} if you specify {@code * layout_widthPercent.} However, if you want the view to be able to take up more space than what * percentage value permits, you can add {@code layout_width/height="wrap_content"}. In that case * if the percentage size is too small for the View's content, it will be resized using * {@code wrap_content} rule. */public class PercentRelativeLayout extends RelativeLayout { private final PercentLayoutHelper mHelper = new PercentLayoutHelper(this); public PercentRelativeLayout(Context context) { super(context); } public PercentRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public PercentRelativeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(), attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mHelper.handleMeasuredStateTooSmall()) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); mHelper.restoreOriginalParams(); } public static class LayoutParams extends RelativeLayout.LayoutParams implements PercentLayoutHelper.PercentLayoutParams { private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } @Override public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() { return mPercentLayoutInfo; } @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr); } }}我们可以看到,这里先是自定义一个新的LayoutParams(里面定义了新的属性),然后重写了generateLayoutParams方法。
在自定义的LayoutParams中实现了接口PercentLayoutHelper.PercentLayoutParams;
public interface PercentLayoutParams { PercentLayoutInfo getPercentLayoutInfo(); }重写了getPercentLayoutInfo()方法,返回mPercentLayoutInfo:
@Override public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() { return mPercentLayoutInfo; }而,mPercentLayoutInfo中包含了自定义的百分比属性(实在构造方法中取到的):
public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); }
public static PercentLayoutInfo getPercentLayoutInfo(Context context, AttributeSet attrs) { PercentLayoutInfo info = null; TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentLayout_Layout); int index = R.styleable.PercentLayout_Layout_layout_widthPercent; String sizeStr = array.getString(index); PercentLayoutInfo.PercentVal percentVal = getPercentVal(sizeStr, true); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent width: " + percentVal.percent); } info = checkForInfoExists(info); info.widthPercent = percentVal; } sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_heightPercent); percentVal = getPercentVal(sizeStr, false); if (sizeStr != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent height: " + percentVal.percent); } info = checkForInfoExists(info); info.heightPercent = percentVal; } // value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginPercent, 1, 1, -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginPercent); // just for judge percentVal = getPercentVal(sizeStr, false); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent margin: " + percentVal.percent); } info = checkForInfoExists(info); info.leftMarginPercent = getPercentVal(sizeStr, true); info.topMarginPercent = getPercentVal(sizeStr, false); info.rightMarginPercent = getPercentVal(sizeStr, true); info.bottomMarginPercent = getPercentVal(sizeStr, false); } //value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginLeftPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginLeftPercent); percentVal = getPercentVal(sizeStr, true); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent left margin: " + percentVal.percent); } info = checkForInfoExists(info); info.leftMarginPercent = percentVal; } // value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginTopPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginTopPercent); percentVal = getPercentVal(sizeStr, false); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent top margin: " + percentVal.percent); } info = checkForInfoExists(info); info.topMarginPercent = percentVal; } // value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginRightPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginRightPercent); percentVal = getPercentVal(sizeStr, true); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent right margin: " + percentVal.percent); } info = checkForInfoExists(info); info.rightMarginPercent = percentVal; } //value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginBottomPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginBottomPercent); percentVal = getPercentVal(sizeStr, false); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent bottom margin: " + percentVal.percent); } info = checkForInfoExists(info); info.bottomMarginPercent = percentVal; } // value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginStartPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginStartPercent); percentVal = getPercentVal(sizeStr, true); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent start margin: " + percentVal.percent); } info = checkForInfoExists(info); info.startMarginPercent = percentVal; } //value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginEndPercent, 1, 1, // -1f); sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_marginEndPercent); percentVal = getPercentVal(sizeStr, true); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent end margin: " + percentVal.percent); } info = checkForInfoExists(info); info.endMarginPercent = percentVal; } //textSizePercent sizeStr = array.getString(R.styleable.PercentLayout_Layout_layout_textSizePercent); percentVal = getPercentVal(sizeStr, false); if (percentVal != null) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "percent text size: " + percentVal.percent); } info = checkForInfoExists(info); info.textSizePercent = percentVal; } //maxWidth percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_maxWidthPercent, true); if (percentVal != null) { checkForInfoExists(info); info.maxWidthPercent = percentVal; } //maxHeight percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_maxHeightPercent, false); if (percentVal != null) { checkForInfoExists(info); info.maxHeightPercent = percentVal; } //minWidth percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_minWidthPercent, true); if (percentVal != null) { checkForInfoExists(info); info.minWidthPercent = percentVal; } //minHeight percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_minHeightPercent, false); Log.d(TAG,"minHeight = "+percentVal); if (percentVal != null) { checkForInfoExists(info); info.minHeightPercent = percentVal; } array.recycle(); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "constructed: " + info); } return info; }
获得属性后,在onMeasure中对器子控件,重新计算高宽。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mHelper.handleMeasuredStateTooSmall()) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
public void adjustChildren(int widthMeasureSpec, int heightMeasureSpec) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "adjustChildren: " + mHost + " widthMeasureSpec: " + View.MeasureSpec.toString(widthMeasureSpec) + " heightMeasureSpec: " + View.MeasureSpec.toString(heightMeasureSpec)); } int widthHint = View.MeasureSpec.getSize(widthMeasureSpec); int heightHint = View.MeasureSpec.getSize(heightMeasureSpec); Log.d(TAG, "widthHint = " + widthHint + " , heightHint = " + heightHint); for (int i = 0, N = mHost.getChildCount(); i < N; i++) { View view = mHost.getChildAt(i); ViewGroup.LayoutParams params = view.getLayoutParams(); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "should adjust " + view + " " + params); } if (params instanceof PercentLayoutParams) { PercentLayoutInfo info = ((PercentLayoutParams) params).getPercentLayoutInfo();//关键调用 if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "using " + info); } if (info != null) { supportTextSize(widthHint, heightHint, view, info); supportMinOrMaxDimesion(widthHint, heightHint, view, info); if (params instanceof ViewGroup.MarginLayoutParams) { info.fillMarginLayoutParams((ViewGroup.MarginLayoutParams) params, widthHint, heightHint); } else { info.fillLayoutParams(params, widthHint, heightHint); } } } } }
上面关键代码:
PercentLayoutInfo info = ((PercentLayoutParams) params).getPercentLayoutInfo();
1 0
- android-percent-support-lib-sample
- android-percent-support-lib-sample
- 安卓适配之android-percent-support-lib-sample的用法
- Android percent-support-lib
- Android适配—百分比布局库(android-percent-support-lib-sample)
- Android--百分比布局库(percent-support-lib)
- Android 百分比布局库(percent-support-lib)
- Android百分比布局(percent-support-lib)
- Android 百分比布局库(percent-support-lib)
- Android percent-support-lib百分比布局
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 百分比布局库(percent-support-lib) 解析与扩展
- 解决STM32 SPI 半残废 NSS无法拉高
- 定位问题:*** glibc detected *** : double free or corruption (!prev): 0x09b077d8
- Springmvc JSON交互
- Android利用ContentResolver查询的三种方式
- AOP Spring
- android-percent-support-lib-sample
- SQL表复制
- Bentley STAAD.Pro V8i SS6 v20.07.11.33 1CD(土木結構分析)
- [转载] 尺度不变特征变换匹配算法详解
- C++栈实践
- 希尔排序堆排序和基数排序
- COPRA.RF.v2005.SR1-ISO 1CD(设计检验轧辊的虚拟现实的集成软件)
- 影像去条带噪声
- Android System Property