博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReactNative与Android中的屏幕适配
阅读量:4086 次
发布时间:2019-05-25

本文共 27397 字,大约阅读时间需要 91 分钟。

前言:从开始接触rn到现在终于能写出点东西了,的确得为自己好好地点个赞 ,不管咋样,学习还是得继续啊,废话少说了,在rn中我们也需要对屏幕进行适配,但是rn中的适配貌似比原生容易很多(不得佩服facebook那些大神哈,对android原生控件封装的太屌!)。

http://blog.csdn.net/vv_bug/article/details/54958200

我们先看看rn中的屏幕适配(作为一个android程序员去做rn确实比程序员考虑的东西多一点点哈,嘻嘻~~): 
结合android的一些适配经验,我在rn中也封装了一个工具类 
ScreenUtils.js:

/** * 屏幕工具类 * ui设计基准,iphone 6 * width:750 * height:1334 */var ReactNative = require('react-native');var Dimensions = require('Dimensions');export var screenW = Dimensions.get('window').width;export var screenH = Dimensions.get('window').height;var fontScale = ReactNative.PixelRatio.getFontScale();export var pixelRatio = ReactNative.PixelRatio.get();const r2=2;const w2 = 750/r2;``const h2 = 1334/r2;/** * 设置text为sp * @param size  sp * @returns {Number} dp */export const DEFAULT_DENSITY=2;export function setSpText(size:Number) {    var scaleWidth = screenW / w2;    var scaleHeight = screenH / h2;    var scale = Math.min(scaleWidth, scaleHeight);    size = Math.round((size * scale + 0.5) * pixelRatio / fontScale);    return size;}/** * 屏幕适配,缩放size * @param size * @returns {Number} * @constructor */export function scaleSize(size:Number) {    var scaleWidth = screenW / w2;    var scaleHeight = screenH / h2;    var scale = Math.min(scaleWidth, scaleHeight);    size = Math.round((size * scale + 0.5));    return size/DEFAULT_DENSITY;} 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

搞过rn的童鞋知道,rn中直接写宽高都是dp的,所以我们要以一个美工设计的ui基准来计算我们的宽高,数学不好哈,不过大概是这样的: 
我们先定义好ui的设计基准:

/** * 屏幕工具类 * ui设计基准,iphone 6 * width:750 * height:1334 */var ReactNative = require('react-native');var Dimensions = require('Dimensions');export var screenW = Dimensions.get('window').width;export var screenH = Dimensions.get('window').height;var fontScale = ReactNative.PixelRatio.getFontScale();export var pixelRatio = ReactNative.PixelRatio.get();const r2=2;const w2 = 750/r2;``const h2 = 1334/r2;/** * 设置text为sp * @param size  sp * @returns {Number} dp */export const DEFAULT_DENSITY=2; 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

然后获取到我们自己手机的屏幕宽高,生成一个百分比,然后算出在iphone6上的100px,在我们手机上是多少px,最后转换成dp设置在在我们布局的style中:

const styles = StyleSheet.create({    container: {        backgroundColor: 'white',        justifyContent: 'space-between',        flexDirection: 'row',        paddingTop: ScreenUtils.scaleSize(22),        paddingBottom: ScreenUtils.scaleSize(22),        paddingRight: ScreenUtils.scaleSize(12),        paddingLeft: ScreenUtils.scaleSize(12),        alignItems: 'center'    },}); 
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12

好啦~!!,rn上的适配就完啦,是不是soeasy呢???

但是在android原生中,我们写布局大多数都是在xml中写的,所以我们在写布局的时候,压根就不知道我要运行在什么手机上,所以android官方建议我们使用dp啊,然后建很多layout文件啊,很多value文件啊,是的!我个人也是比较推崇官方的做法的,效率高,清晰明了,好啦!!除了android官方说的那种方法,我们是否也可以像rn一样运行后再重新算出百分比,然后再布局呢?答案是肯定的,因为rn就是一个例子,它也是对原生控件封装过的,所以才能用js轻易控制,在此之前鸿洋大神也对百分比布局做了封装,也对齐做了很详细的解析了,先贴上大神的博客链接: 
[

好啦!我们今天要做的也就是在百分比布局的基础上简单封装下,然后使得其能够像rn一样,直接写上美工标的px就能完美适配大部分手机了。

先上张运行好的效果图(效果还是很不错的!):

布局文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

这里写图片描述

先走一遍百分比布,看它到底是咋实现适配的(以下是来自鸿洋大神封装过后的代码,我就直接拿走解析了,嘻嘻!!):

PercentLinearLayout.:

package com.yasin.px_percent_layout;import android.app.Activity;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.ScrollView;public class PercentLinearLayout extends LinearLayout {
private static final String TAG = "PercentLinearLayout"; private PercentLayoutHelper mPercentLayoutHelper; public PercentLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); mPercentLayoutHelper = new PercentLayoutHelper(this); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int tmpWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); //fixed scrollview height problems if (heightMode == MeasureSpec.UNSPECIFIED && getParent() != null && (getParent() instanceof ScrollView)) { int baseHeight = 0; Context context = getContext(); if (context instanceof Activity) { Activity act = (Activity) context; int measuredHeight = act.findViewById(android.R.id.content).getMeasuredHeight(); baseHeight = measuredHeight; } else { baseHeight = getScreenHeight(); } tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(baseHeight, heightMode); } mPercentLayoutHelper.adjustChildren(tmpWidthMeasureSpec, tmpHeightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mPercentLayoutHelper.handleMeasuredStateTooSmall()) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private int getScreenHeight() { WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mPercentLayoutHelper.restoreOriginalParams(); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(), attrs); } public static class LayoutParams extends LinearLayout.LayoutParams implements PercentLayoutHelper.PercentLayoutParams {
private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } @Override public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() { return mPercentLayoutInfo; } @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr); } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

代码不要太简单哈,就在构造方法中创建了一个mPercentLayoutHelper:

public PercentLinearLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mPercentLayoutHelper = new PercentLayoutHelper(this);    } 
1
2
3
4
5
1
2
3
4
5

我们待会再来说这个PercentLayoutHelper,

然后就是创建了一个自己的LayoutParams:

public static class LayoutParams extends LinearLayout.LayoutParams            implements PercentLayoutHelper.PercentLayoutParams {
private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } @Override public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() { return mPercentLayoutInfo; } @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr); } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

其中也咩有啥代码,创建了一个PercentLayoutInfo。

然后核心代码就是onMeasure方法里面了:

mPercentLayoutHelper.adjustChildren(tmpWidthMeasureSpec, tmpHeightMeasureSpec); 
1
2
1
2

核心也就这一句。

终结下来就是: 
1、先获取到我们在布局文件中定义的属性:

app:layout_widthPercent="10%w" app:layout_heightPercent="10%h" ....... 
1
2
3
1
2
3

2、然后把获取到的属性封装进一个叫PercentLayoutInfo的类中:

public LayoutParams(Context c, AttributeSet attrs) {            super(c, attrs);            mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs);        } 
1
2
3
4
1
2
3
4

3、在onMeasure方法中根据传进的属性对子控件进行重置大小:

@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int tmpWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);        //fixed scrollview height problems        if (heightMode == MeasureSpec.UNSPECIFIED && getParent() != null && (getParent() instanceof ScrollView)) {            int baseHeight = 0;            Context context = getContext();            if (context instanceof Activity) {                Activity act = (Activity) context;                int measuredHeight = act.findViewById(android.R.id.content).getMeasuredHeight();                baseHeight = measuredHeight;            } else {                baseHeight = getScreenHeight();            }            tmpHeightMeasureSpec = MeasureSpec.makeMeasureSpec(baseHeight, heightMode);        }        mPercentLayoutHelper.adjustChildren(tmpWidthMeasureSpec, tmpHeightMeasureSpec);        super.onMeasure(widthMeasureSpec, hei }    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

看完是不是觉得很简单呢? 是的,本来就不难哈,我们接着往下看:

先看看它是咋拿到我们在布局文件中写的属性的(怎么封装):

public static PercentLayoutInfo getPercentLayoutInfo(Context context,                                                         AttributeSet attrs) {        PercentLayoutInfo info = null;        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentLayout_Layout);        info = setWidthAndHeightVal(array, info);        info = setMarginRelatedVal(array, info);        info = setTextSizeSupportVal(array, info);        info = setMinMaxWidthHeightRelatedVal(array, info);        info = setPaddingRelatedVal(array, info);        array.recycle();        if (Log.isLoggable(TAG, Log.DEBUG)) {            Log.d(TAG, "constructed: " + info);        }        return info;    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

获取TypedArray数组中的数据(我们就只看setWidthAndHeightVal代码了):

private static PercentLayoutInfo setWidthAndHeightVal(TypedArray array, PercentLayoutInfo info) {        PercentLayoutInfo.PercentVal percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_widthPercent, true);        if (percentVal != null) {            if (Log.isLoggable(TAG, Log.VERBOSE)) {                Log.v(TAG, "percent width: " + percentVal.percent);            }            info = checkForInfoExists(info);            info.widthPercent = percentVal;        }        percentVal = getPercentVal(array, R.styleable.PercentLayout_Layout_layout_heightPercent, false);        if (percentVal != null) {            if (Log.isLoggable(TAG, Log.VERBOSE)) {                Log.v(TAG, "percent height: " + percentVal.percent);            }            info = checkForInfoExists(info);            info.heightPercent = percentVal;        }        return info;    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

获取到heightPercent跟widthPercent信息然后赋给info对象,没啥好看的,重点看看咋获取到的widthPercent信息:

private static PercentLayoutInfo.PercentVal getPercentVal(TypedArray array, int index, boolean baseWidth) {        String sizeStr = array.getString(index);        PercentLayoutInfo.PercentVal percentVal = getPercentVal(sizeStr, baseWidth);        return percentVal;    } 
1
2
3
4
5
1
2
3
4
5

也没啥看的(继续往下走):

private static PercentLayoutInfo.PercentVal getPercentVal(String percentStr, boolean isOnWidth) {        //valid param        if (percentStr == null) {            return null;        }        Pattern p = Pattern.compile(REGEX_PERCENT);        Matcher matcher = p.matcher(percentStr);        if (TextUtils.isEmpty(percentStr) ||                (!matcher.matches() && !(percentStr.toLowerCase().endsWith("px")))) {            throw new RuntimeException("the value of layout_xxxPercent invalid! ==>" + percentStr);        }        String floatVal;        String lastAlpha;        float percent;        int len = percentStr.length();        if (matcher.matches()) {            //extract the float value            floatVal = matcher.group(1);            lastAlpha = percentStr.substring(len - 1);            percent = Float.parseFloat(floatVal) / 100f;        } else {            //extract the float value            floatVal = percentStr.substring(0, percentStr.indexOf("px"));            lastAlpha = percentStr.substring(len - 1);            percent = Float.parseFloat(floatVal);        }        PercentLayoutInfo.PercentVal percentVal = new PercentLayoutInfo.PercentVal();        percentVal.percent = percent;        if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.SW)) {            percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_SCREEN_WIDTH;        } else if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.SH)) {            percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_SCREEN_HEIGHT;        } else if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.PERCENT)) {            if (isOnWidth) {                percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_WIDTH;            } else {                percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_HEIGHT;            }        } else if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.W)) {            percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_WIDTH;        } else if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.H)) {            percentVal.basemode = PercentLayoutInfo.BASEMODE.BASE_HEIGHT;        } else if (percentStr.endsWith(PercentLayoutInfo.BASEMODE.PX)) {            percentVal.basemode = PercentLayoutInfo.BASEMODE.ABSOLUTE_PX;        } else {            throw new IllegalArgumentException("the " + percentStr + " must be endWith [%|w|h|sw|sh]");        }        return percentVal;    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

好啦,终于看到核心代码了,不做太多解释,相信都看得懂,简单来说就是获取到我们设置的值,然后判断我们设置的值属于哪种类型:

类型有:

private enum BASEMODE {            BASE_WIDTH, BASE_HEIGHT, BASE_SCREEN_WIDTH, BASE_SCREEN_HEIGHT, ABSOLUTE_PX;            /**             * width_parent             */            public static final String PERCENT = "%";            /**             * width_parent             */            public static final String W = "w";            /**             * height_parent             */            public static final String H = "h";            /**             * width_screen             */            public static final String SW = "sw";            /**             * height_screen             */            public static final String SH = "sh";            /**             * absolute px             */            public static final String PX = "px";        } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

就是我们布局中写的:

app:layout_widthPercent="10%w"            app:layout_heightPercent="10%h"            app:layout_widthPercent="20%sw"            app:layout_heightPercent="20%sh"            app:layout_widthPercent="200px"            app:layout_heightPercent="200px" 
1
2
3
4
5
6
1
2
3
4
5
6

小伙伴是不是看懂了呢? 比如20%sw,就是把20跟sw取出来,然后封装进类中。

好啦,我们已经拿到我们在布局中设置的属性了,然后我们就得根据我们设置的值重新赋给子控件了。

在onMeasure中我们找到adjustChildren方法:

/**     * Iterates over children and changes their width and height to one calculated from percentage     * values.     *     * @param widthMeasureSpec  Width MeasureSpec of the parent ViewGroup.     * @param heightMeasureSpec Height MeasureSpec of the parent ViewGroup.     */    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);        if (Log.isLoggable(TAG, Log.DEBUG))            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);                    supportPadding(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);                    }                }            }        }    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

遍历我们的子控件,然后根据我们上面获取到的info类,进行重新布局:

if (info != null) {                    supportTextSize(widthHint, heightHint, view, info);                    supportPadding(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);                    }                } 
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12

demo中我们看到了:

1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10

我们有设置一个app:layout_textSizePercent:

看到这我们找到一个方法,没错!也就是这里对textview设置的size大小的:

supportTextSize(widthHint, heightHint, view, info); 
1
1

我们往下走:

private void supportTextSize(int widthHint, int heightHint, View view, PercentLayoutInfo info) {        //textsize percent support        PercentLayoutInfo.PercentVal textSizePercent = info.textSizePercent;        if (textSizePercent == null) return;        float textSize;        int base = getBaseByModeAndVal(widthHint, heightHint, textSizePercent.basemode);        if (textSizePercent.basemode == PercentLayoutInfo.BASEMODE.ABSOLUTE_PX) {            textSize = ViewUtils.scaleTextValue(mHost.getContext(), textSizePercent.percent);        } else {            textSize = (int) (base * textSizePercent.percent);        }        //Button 和 EditText 是TextView的子类        if (view instanceof TextView) {            ((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);        }    } 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

这里如果我们是直接设置的px的话(如:app:layout_textSizePercent=”28px”),我们就需要根据ui基准,然后算出在我们手机上应该显示多少:

int base = getBaseByModeAndVal(widthHint, heightHint, textSizePercent.basemode);        if (textSizePercent.basemode == PercentLayoutInfo.BASEMODE.ABSOLUTE_PX) {            textSize = ViewUtils.scaleTextValue(mHost.getContext(), textSizePercent.percent);        } else {            textSize = (int) (base * textSizePercent.percent);        } 
1
2
3
4
5
6
1
2
3
4
5
6

如果是直接设置的20%w,20%h,20%sh这样的值的话,我们就需要用父布局的宽、高、屏幕宽、高乘一个我们设置进去的百分比进行计算了:

textSize = (int) (base * textSizePercent.percent); 
1
1

好啦!!!剩下的几个方法也都差不多,我就不一一讲了哈:

if (info != null) {                    supportTextSize(widthHint, heightHint, view, info);                    supportPadding(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);                    }                } 
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12

嗯嗯~! 我们的百分比跟px布局差不多就讲完啦~, 下面看看咋使用它哈:

如果要直接使用px布局的话(不用px布局可不需要做第一步与第二步): 
1、在项目的manifest文件中定义好ui设计的基准(如iphone6):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

2、在app中的application文件中,初始化布局:

package com.example.leo.textdemo;import android.app.Application;import android.content.Context;import com.yasin.px_percent_layout.utils.PxAppConfig;/** * Created by leo on 17/2/9. */public class BaseApplication extends Application {
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); PxAppConfig.init(base); }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

然后我们就可以在布局文件中用起来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

好啦!!!文章有点长哈,最后附上项目的链接: 

你可能感兴趣的文章
现在明白为什么无名博客里好几篇文章在讲传感器的滞后
查看>>
实际我看Pixhawk定高模式其实也是飞得很稳,飘得也不厉害
查看>>
Pixhawk解锁常见错误
查看>>
C++的模板化等等的确实比C用起来方便多了
查看>>
ROS是不是可以理解成一个虚拟机,就是操作系统之上的操作系统
查看>>
用STL algorithm轻松解决几道算法面试题
查看>>
ACfly之所以不怕炸机因为它觉得某个传感器数据不安全就立马不用了
查看>>
我发觉,不管是弄ROS OPENCV T265二次开发 SDK开发 caffe PX4 都是用的C++
查看>>
ROS的安装(包含文字和视频教程,我的ROS安装教程以这篇为准)
查看>>
国内有个码云,gitee
查看>>
原来我之前一直用的APM固件....现在很多东西明白了。
查看>>
realsense-ros里里程计相关代码
查看>>
似乎写个ROS功能包并不难,你会订阅话题发布话题,加点逻辑处理,就可以写一些基础的ROS功能包了。
查看>>
if __name__ == ‘__main__‘:就是Python里的main函数,脚本从这里开始执行,如果没有main函数则从上到下顺序执行。
查看>>
PX4官方用户和开发手册的首页面是会给你选择英文和中文的
查看>>
网络协议栈我是不是可以这么理解,就是把你要发送的数据自动处理成TCPIP格式的消息发出去,这种底层的转换不需要你弄了。
查看>>
除了LwIP还有uIP
查看>>
《跟工程师学嵌入式开发》这本书最后的终极项目我反而觉得有说头
查看>>
博士的申请考核制
查看>>
那些硬件的初始化函数主要是在做些上什么?
查看>>