屏幕适配-百分比布局

原理:以父容器尺寸作为参考,在View的加载过程,根据当前父容器实际尺寸换算出目标尺寸,在作用在View上。

百分比布局实际是对容器的一中扩展,扩展的是宽高等比例的设置。

1、自定义属性

attrs.xml

2、对属性进行解析

以RelativeLayout为例,看一下它是如何对属性进行解析的?

RelativeLayout的工作原理:在它里面定义了一个LayoutParams静态内部类,在这里面定义了我们的自定义属性,这些属性都是我们这个容器的特有的属性。

解析是在 public LayoutParams(Context c, AttributeSet attrs)构造方法中:

现在我们看一下,这些属性是如何添加到我们的View中的。

我们都知道PhoneWindow是Window的唯一实现类,我们从PhoneWindow的setContentView开始

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {

synchronized (mConstructorArgs) {

Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

final Context inflaterContext = mContext;

final AttributeSet attrs = Xml.asAttributeSet(parser);

Context lastContext = (Context) mConstructorArgs[0];

mConstructorArgs[0] = inflaterContext;

View result = root;

........

if (TAG_MERGE.equals(name)) {

if (root == null || !attachToRoot) {

throw new InflateException(" can be used only with a valid "

+ "ViewGroup root and attachToRoot=true");

}

rInflate(parser, root, inflaterContext, attrs, false);

} else {

// Temp is the root view that was found in the xml 表示我们布局文件的根布局

final View temp = createViewFromTag(root, name, inflaterContext, attrs);

ViewGroup.LayoutParams params = null;

if (root != null) {

if (DEBUG) {

System.out.println("Creating params from root: " +

root);

}

// Create layout params that match root, if supplied

params = root.generateLayoutParams(attrs);

if (!attachToRoot) {

// Set the layout params for temp if we are not

// attaching. (If we are, we use addView, below)

temp.setLayoutParams(params);

}

}

...........

}

我们看到重要的核心代码 params = root.generateLayoutParams(attrs);和

temp.setLayoutParams(params);

如下就是我们自定义的百分不布局:

public class PercentLayout extends RelativeLayout {

public PercentLayout(Context context) {

super(context);

}

public PercentLayout(Context context, AttributeSet attrs) {

super(context, attrs);

}

public PercentLayout(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//获取父容器的尺寸

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

int count = getChildCount();

for (int i = 0; i < count; i++) {

View child = getChildAt(i);//重新设置子View的布局属性,在进行View的测量

ViewGroup.LayoutParams params = child.getLayoutParams();

//如果说是百分比布局属性

if (checkLayoutParams(params)){

LayoutParams lp = (LayoutParams)params;

//自定百分比属性

float widthPercent = lp.widthPercent;

float heightPercent = lp.heightPercent;

float marginLeftPercent = lp.marginLeftPercent;

float marginRightPercent= lp.marginRightPercent;

float marginTopPercent= lp.marginTopPercent;

float marginBottomPercent = lp.marginBottomPercent;

//根据当前父容器实际尺寸换算出目标尺寸

if (widthPercent > 0){

params.width = (int) (widthSize * widthPercent);

}

if (heightPercent > 0){

params.height = (int) (heightSize * heightPercent);

}

if (marginLeftPercent > 0){

((LayoutParams) params).leftMargin = (int) (widthSize * marginLeftPercent);

}

if (marginRightPercent > 0){

((LayoutParams) params).rightMargin = (int) (widthSize * marginRightPercent);

}

if (marginTopPercent > 0){

((LayoutParams) params).topMargin = (int) (heightSize * marginTopPercent);

}

if (marginBottomPercent > 0){

((LayoutParams) params).bottomMargin = (int) (heightSize * marginBottomPercent);

}

}

}

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override

protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {

return p instanceof LayoutParams;

}

public LayoutParams generateLayoutParams(AttributeSet attrs){

return new LayoutParams(getContext(), attrs);

}

public static class LayoutParams extends RelativeLayout.LayoutParams{

private float widthPercent;

private float heightPercent;

private float marginLeftPercent;

private float marginRightPercent;

private float marginTopPercent;

private float marginBottomPercent;

public LayoutParams(Context c, AttributeSet attrs) {

super(c, attrs);

//解析自定义属性

TypedArray a = c.obtainStyledAttributes(attrs,R.styleable.PercentLayout);

widthPercent = a.getFloat(R.styleable.PercentLayout_widthPercent, 0);

heightPercent = a.getFloat(R.styleable.PercentLayout_heightPercent, 0);

marginLeftPercent = a.getFloat(R.styleable.PercentLayout_marginLeftPercent, 0);

marginRightPercent = a.getFloat(R.styleable.PercentLayout_marginRightPercent, 0);

marginTopPercent = a.getFloat(R.styleable.PercentLayout_marginTopPercent, 0);

marginBottomPercent = a.getFloat(R.styleable.PercentLayout_marginBottomPercent, 0);

a.recycle();

}

}

}

android百分比布局适配,安卓屏幕适配-百分比布局相关推荐

  1. 【Android 屏幕适配】屏幕适配基础概念 ④ ( 屏幕适配限定符 | 手机/平板电脑设备屏幕适配 )

    文章目录 一.屏幕适配限定符 二.手机/平板电脑设备屏幕适配 平板电脑市场占有率 密度无关像素计算 手机设备限定符 平板设备限定符 参考文档 : 设备兼容性概览 屏幕兼容性概览 支持不同的像素密度 声 ...

  2. 安卓屏幕适配——pt适配,将pt作为宽度百分比单位

    PS:这个方案存在缺陷,其实并没什么鸟用.不过其中涉及的物理尺寸和像素的转换,这个知识还是有点应用的,比如可以用来制作直尺,将手机屏幕当直尺用,测量其他物体的尺寸. 1.物理尺寸和像素单位的转换方法 ...

  3. android 屏幕适配dimens,关于android:安卓屏幕适配一键生成dimens文件

    工具类 import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.Pr ...

  4. Android高级-网易云音乐屏幕适配

    为什么要进行屏幕适配 屏幕碎片化表现为以下几个方面: 1:屏幕尺寸碎片化: 2:屏幕密度碎片化 3:厂商碎片化:水滴屏,刘海屏 屏幕适配常见方式 二 谷歌推出的百分比布局 手写百分比布局; 为什么百分 ...

  5. android大屏适配_Android屏幕适配

    Android屏幕适配 2020-04-20 09:07:33  By: 琛恋柏 随着安卓手机的样式越来越多,屏幕的大小也不一致,分辨率大小也多规格化,所以在开发中就遇到很多关于屏幕适配的问题,当然前 ...

  6. 通过excel生成不同dimens文件来实现安卓屏幕适配

    在安卓项目中,对安卓市场上不同生产商和尺寸的手机实现屏幕适配一直是开发者比较闹心的问题,网上也有很多第三方适配方案来解决,在此不做多述.我们一般都是希望写一套布局文件,在屏幕纵横比相差不是非常大的情况 ...

  7. 安卓屏幕适配方案(根据今日头条方案,升级版)

    前言 屏幕适配方案有很多,比如原生的dp,鸿洋大神的AutoLayout,宽高限定符,今天我用缺点比较小的今日头条方案 头条适配方案的文章链接:https://mp.weixin.qq.com/s/d ...

  8. ios 纯代码怎么适配ipad_iOS屏幕适配(纯代码)

    在iOS实际项目开发中, 我们经常要适配不同尺寸的屏幕,如iPhone4s,iPhone5/s,iPhone6/s,iPhone6Plus等. 在代码中创建一个控件如: UILabel *label ...

  9. 计算器界面网格布局java,安卓案例:网格布局实现计算器界面

    安卓案例:网格布局实现计算器界面 一.网格布局(GridLayout) GridLayout布局使用虚细线将布局划分为行.列和单元格,也支持一个控件在行.列上都有交错排列. (一)继承关系图 (二)常 ...

最新文章

  1. python添加行索引_python-熊猫在特定级别向多索引添加行
  2. jquery技巧总结
  3. 财务需要学python-财务方面的学生如何学习python?
  4. Android——APK 在32bit/64bit平台 动态库问题
  5. 如何在QQ浏览器查看默认搜索引擎
  6. VIM Emacs 临时获得权限(:w !sudo tee %)
  7. visio2016无法安装的完美解决方法
  8. 51单片机 矩阵键盘
  9. Linux 上的NetworkManager示例
  10. 电脑风扇转一下停一下开不了机解决方案
  11. STM32几种流行开发环境的优缺点
  12. 数字序号的级别与文章层次结构的关系
  13. 新能源车企凶猛下沉,“新车商”会是一条捷径吗?
  14. unity3D AR涂涂乐制作浅谈
  15. 【洛谷P3932】浮游大陆的68号岛【前缀和】
  16. python打开文件代码-python_文件操作代码实例
  17. 教你创建qq好友桌面快捷方式
  18. 考研计算机软件与理论院校排名,计算机软件与理论专业考研院校排名
  19. 上海交通大学学生生存手册_给学生的生存技巧
  20. CMMI的关键过程域(KPA)

热门文章

  1. C# Datagridview完整攻略
  2. 使用WebBrowser控件获取网页源码的方法
  3. 在asp.net 中应用POST传递和接收XML文件以及参数.
  4. 通过一道题目来理解互斥和同步
  5. struts2采用convention-plugin实现零配置
  6. PyTorch基础(13)-- torch.nn.Unfold()方法
  7. 白话详细解读(四)-----FCN
  8. Java中“==”和equals()的区别
  9. php smarty 限制显示字数,smarty现在显示字数的各种写法
  10. 在區塊鏈上建立可更新的智慧合約(一)