失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android 根据屏幕尺寸适配控件大小(按比例缩放)

Android 根据屏幕尺寸适配控件大小(按比例缩放)

时间:2019-07-20 01:26:47

相关推荐

Android 根据屏幕尺寸适配控件大小(按比例缩放)

在写布局时就在想有没有一种方式跟随屏幕大小自动缩放呢?

寻思半天不如上手写个出来

package com.android.juzi.layout;import android.app.Activity;import android.content.Context;import android.content.res.Resources;import android.util.DisplayMetrics;import android.util.Log;import android.util.TypedValue;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.view.ViewGroup.MarginLayoutParams;import android.widget.AbsListView;import android.widget.TextView;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class Container {public static int ORIGINAL_W = 720;//重要:开发者设备屏幕宽度,view大小是跟随这个设置的private static boolean yool;//是否启动过private boolean icu = true;private int width;private View rootView;private Exclude exclude;private Class[] view_Optimize;private boolean width_Height,padding,text,margin;private Map<Class,Boolean> list = new HashMap<>();public Container(Activity a) {if (a == null) {log("Activity == null");return;}ViewGroup v = a.findViewById(android.R.id.content);//获取setContentView的布局init(a, v);}public Container(View v) {if (v == null) {log("View == null");return;}init(v.getContext(), v);}public Container(Context c, int i) {if (c == null) {log("Context == null");return;}LayoutInflater layoutInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);if (layoutInflater == null) {throw new AssertionError("LayoutInflater构建错误.");}View v = layoutInflater.inflate(i, null, false);init(c, v);}private void init(Context c, View v) {if (c == null || v == null) {return;}Resources res = c.getResources();DisplayMetrics metrics = res.getDisplayMetrics();int w = metrics.widthPixels,h = metrics.heightPixels;width = w < h ? w : h;rootView = v;}public boolean isLoad() {/**是否启动过运行后view宽高已经被改变再次运行view就会越来越小/大**/return this.yool;}public int getDisplayWidth() {return width;}public Container addIsolateView(Class[] c) {if (c == null) {return null;}for (int i=0;i < c.length;i++) {addIsolateView(c[i]);}return this;}public Container addIsolateView(Class s) {return addIsolateView(s, false);}public Container addIsolateView(Class...s, boolean...b) {if (s == null || b == null) {return null;}if (s.length != b.length) {return null;}for (int i=0;i < s.length;i++) {addIsolateView(s[i], b[i]);}return this;}public Container addIsolateView(Class...s, boolean b) {if (s == null) {return null;}for (int i=0;i < s.length;i++) {addIsolateView(s[i], b);}return this;}public Container addIsolateView(Class s, boolean b) {/**插入需要排除的View.class参数2仅对ViewGroup生效参数2代表是否修改自己true自己会修改,子控件不会修改false自己和子控件都不会修改**/if (s == null) {return null;}list.put(s, b);return this;}public Container setExclude(Exclude e) {return setExclude(new Class[]{View.class}, e);}public Container setExclude(Class v, Exclude e) {return setExclude(new Class[]{v}, e);}public Container setExclude(Class...v, Exclude e) {/**通过view.class回调若是view等于这个class那么就回调可用于列表适配器刷新以及设置view的其它属性**/view_Optimize = v;exclude = e;return this;}public int calculate(int i) {return calculate(((double)width) / ((double)ORIGINAL_W), i);} public View startSkip() {//重新开始,会导致view大小持续增大或增小if (rootView == null || !icu) {return rootView;}if ((width_Height && padding) && (text && margin)) {log("无可修改项目!");return rootView;}dateView(rootView, width);this.yool = true;return rootView;}public View start() {//启动,不能第二次启动if (!this.yool) {startSkip();} else {log("start已运行过!");}return rootView;}public void quit() {//标记放弃运行icu = false;}public static interface Exclude {void onView(Container con, View v, Class c);}public Container refuse_Width_Height() {width_Height = true;//拒绝修改宽高return this;}public Container refuse_Padding() {padding = true;//拒绝修改内边距return this;}public Container refuse_TextSize() {text = true;//拒绝修改文字大小return this;}public Container refuse_Margin() {margin = true;//拒绝修改外边距return this;}private boolean[] isInstanceofView(View v) {/**排除列表,排除控件**/for (Class o:list.keySet()) {if (isInstanceof(v, o) || !icu) {return new boolean[]{false,list.get(o)};}}return new boolean[]{true,true};}private int calculate(double w, int old) {//计算宽度if (old < 1) {return old;}if (w > 0) {return (int)(old * w);}return old;}private void dateView(View view, int w) {//获取viewif (view == null || !icu) {return;}if (ORIGINAL_W == w) {return;}boolean[] rt = isInstanceofView(view);//排除if (!rt[1]) {return;}try {//更新view,使用宽度计算相差,并修改datalayout(view, ((double)w) / ((double)ORIGINAL_W));view.invalidate();view.requestLayout();} catch (Exception e) {log("dateView: " + e.toString());e.printStackTrace();}if (view instanceof ViewGroup) {if (!rt[0]) {return;}View[] children = null;try {Field field = ViewGroup.class.getDeclaredField("mChildren");field.setAccessible(true);children = (View[]) field.get((ViewGroup) view);//通过反射获取ViewGroup内的子控件//历遍获取子控件} catch (Exception e) {log("dateView: " + e.toString());} if (children == null) {return;}for (View child : children) {if (!icu) {return;}dateView(child, w);//重新执行自己}if (view instanceof AbsListView) {AbsListView abs = (AbsListView)view;abs.setAdapter(abs.getAdapter());//重设适配器,防止适配器内的数据未经过更新就直接更改view属性}}if (exclude != null && view_Optimize != null) {for (Class o:view_Optimize) {if (!icu) {return;}if (isInstanceof(view, o)) {exclude.onView(this, view, o);//回调}}}}private void datalayout(View v, double w) throws Exception {if (v == null || !icu) {return;}LayoutParams params = getLayoutParams(v);//修改内边距if (!padding) {data_Padding(v, w);}//修改TextView文字大小if (!text) {data_Text(v, w);}//修改view宽高if (!width_Height) {params = data_Width_Height(params, w);}//修改外边距if (!margin) {params = data_Margin(params, w);}v.setLayoutParams(params);}//如果view无LayoutParams则会创建一个private LayoutParams getLayoutParams(View v) {LayoutParams params = v.getLayoutParams();if (params == null) {int w_ = v.getMeasuredWidth(),h_ = v.getMeasuredHeight(),z_ = 30;params = new LayoutParams(w_ > 0 ? w_ : z_, h_ > 0 ? h_ : z_);}return params;}//宽高private LayoutParams data_Width_Height(LayoutParams params, double w) {params.width = calculate(w, params.width);params.height = calculate(w, params.height);return params;}//内边距大小private void data_Padding(View v, double w) {int left = calculate(w, v.getPaddingLeft());int top = calculate(w, v.getPaddingTop());int right = calculate(w, v.getPaddingRight());int bottom = calculate(w, v.getPaddingBottom());v.setPadding(left, top, right, bottom);}//TextView文字大小private void data_Text(View v, double w) {//TextView文字大小if (!(v instanceof TextView)) {return;}TextView view = (TextView)v;view.setTextSize(PLEX_UNIT_PX, calculate(w, (int) view.getTextSize()));}//外边距大小private LayoutParams data_Margin(LayoutParams params, double w) {if (!(params instanceof MarginLayoutParams)) {return params;}ViewGroup.MarginLayoutParams par = (MarginLayoutParams) params;par.leftMargin = calculate(w, par.leftMargin);par.rightMargin = calculate(w, par.rightMargin);par.topMargin = calculate(w, par.topMargin);par.bottomMargin = calculate(w, par.bottomMargin);return par;}//自制instanceof//用于排除方法private boolean isInstanceof(Object object, Class clazz) {if (object == null || clazz == null || !icu) {return false;}String str = clazz.getName();if (str == object.getClass().getName()) {return true;}Class<?> obj = object.getClass().getSuperclass();String cla = obj.getName();String onj = Object.class.getName();if (str == cla) {return true;}while (icu) {if (obj == null) {return false;}obj = obj.getSuperclass();if (obj == null) {return false;}cla = obj.getName();if (str == cla) {return true;}if (cla == onj) {return false;} }return false;}private void log(String s) {Log.w("Container", s);}}

new Container(activity).getDisplayWidth()

–首先 获取当前屏幕宽度

接下来需要修改

ORIGINAL_W = int

这个全局变量值

它代表着你的屏幕也就是开发者测试的机的屏幕宽度

当你设置好宽度的时候

con = new Container(activity)

con = new Container(view)

con = new Container(context,R.layout.id)

返回大小 = calculate(w or h)

–计算与旧的差值

setExclude(class,Exclude 回调)

setExclude(class{},Exclude 回调)

setExclude(Exclude 回调)

–修改后的回调,通过view.class回调

++若是view等于这个class那么就回调

++可用于列表适配器刷新以及设置view的其它属性

++如果通过addIsolateView排除了是不会回调此方法的

new Container.Exclude()

onView(Container,view,class)

addIsolateView(Class)

addIsolateView(Class,boolean)

addIsolateView(Class{},boolean)

addIsolateView(Class{},boolean{})

–插入需要排除的View.class

++参数2仅对ViewGroup(容器)生效

++参数2代表是否修改自己

++true自己会修改,子控件不会修改

++false自己和子控件都不会修改

boolean = isLoad()

–是否启动过

++运行后view宽高已经被改变

++再次运行view就会越来越(小/大)

refuse_Margin()

–拒绝修改外边距

refuse_TextSize()

–拒绝修改文字大小

refuse_Padding()

–拒绝修改内边距

refuse_Width_Height()

–拒绝修改宽高

那么再来讲下启动方法

上面那些参数需要先设置后再启动

view = start()

–启动,不能第二次启动

++当你准备打包app时建议使用此方法启动

view = startSkip()

–启动,可以重新启动

++注意++

++此方法建议只在测试时使用

++运行后view宽高已经被改变

++再次运行view就会越来越(小/大)

++可以通过isLoad判断

if (con.isLoad()){

//已运行

}else{

//未运行

}

quit()

–标记放弃运行

如果觉得《Android 根据屏幕尺寸适配控件大小(按比例缩放)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。