在写布局时就在想有没有一种方式跟随屏幕大小自动缩放呢?
寻思半天不如上手写个出来
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) {//获取view
if (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(TypedValue.COMPLEX_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()
–标记放弃运行
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)