在写布局时就在想有没有一种方式跟随屏幕大小自动缩放呢?
寻思半天不如上手写个出来
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 根据屏幕尺寸适配控件大小(按比例缩放)》对你有帮助,请点赞、收藏,并留下你的观点哦!