码迷,mamicode.com
首页 > 移动开发 > 详细

android屏幕适配

时间:2014-09-10 17:53:01      阅读:312      评论:0      收藏:0      [点我收藏+]

标签:android屏幕适配

一、屏幕适配工具类

public class MultiScreenTool {

static Activity activity;
public DisplayMetrics displayMetrics = null;
public int defaultX = 0;
public int defaultY = 0;
public float defaultDensity = 1.5f;
public float nowDensity = 0;
private static MultiScreenTool instanceVertical = null;
private static MultiScreenTool instanceHorizontal = null;
private int tagId;
//private Map<String, Boolean> hasAdjust = new HashMap<String, Boolean>();
private String debugId;


public String getDebugId() {
return debugId;
}


public void setDebugId(View view) {
this.debugId = this.getViewCode(view);
}


/**
* 此函数在系统启动的第一个Activity的OnCreate中调用
* @param act
*/
private MultiScreenTool(int width, int height, float nowDensity) {
defaultX = width;
defaultY = height;
this.nowDensity = nowDensity;
}


/**
* 对此工具进行初始化,使用singleTonVertical或者singleTonHorizontal进行获取实例前,必须调用此函数一次

* @param act
*/
public static void init(Activity act) {
DisplayMetrics dm = new DisplayMetrics();
DisplayMetrics dm2 = new DisplayMetrics();
if (act == null) {
// 偶然异常使得系统娶不到activity,则使用480*800的数据
dm.heightPixels = 480;
dm.widthPixels = 800;
dm.xdpi = 240f;
dm.ydpi = 240f;
dm.density = 1.5f;
return;
} else {
activity = act;
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
}
// 横屏、竖屏的x、y坐标颠倒
dm2.heightPixels = dm.widthPixels;
dm2.widthPixels = dm.heightPixels;
//Log.i("DisplayMetrics", "activity: " + activity + "     dm2.widthPixels :" + dm2.widthPixels + "     dm2.heightPixels:" + dm2.heightPixels);
dm2.xdpi = dm.ydpi;
dm2.ydpi = dm.xdpi;
dm2.density = dm.density;
// Log.i("DisplayMetrics","xdpi: "+dm2.xdpi+"ydpi: "+dm2.ydpi+"heightPixels: "+dm2.heightPixels+"widthPixels: "+dm2.widthPixels);
instanceVertical = new MultiScreenTool(Constant.DEFAULT_WIDTH, Constant.DEFAULT_HEIGHT, dm.density);
instanceHorizontal = new MultiScreenTool(Constant.DEFAULT_HEIGHT, Constant.DEFAULT_WIDTH, dm.density);
if (dm.widthPixels < dm.heightPixels) {
// 当前竖屏
instanceVertical.displayMetrics = dm;
instanceHorizontal.displayMetrics = dm2;
} else {
// 横屏
instanceHorizontal.displayMetrics = dm;
instanceVertical.displayMetrics = dm2;
}
instanceVertical.tagId = act.getResources().getIdentifier("view_tag_id", "id", act.getPackageName());
instanceHorizontal.tagId = act.getResources().getIdentifier("view_tag_id", "id", act.getPackageName());
}


/**
* 其他地方不要使用new,而是调用此函数来获取实例

* @return
*/
public static MultiScreenTool singleTonVertical() {
/*
* if (instanceVertical == null) { System.out.println(
* "error,使用MultiScreenTool.singleTonVertical前请先调用MultiScreenTool。init进行初始化,只需调用一次。"
* );
* }
*/
if (instanceVertical == null) {
MultiScreenTool.init(Constant.currentActivity);
}
return instanceVertical;
}


/**
* 其他地方不要使用new,而是调用此函数来获取实例

* @return
*/
public static MultiScreenTool singleTonHolizontal() {
/*
* if (instanceHorizontal == null) { System.out.println(
* "error,使用MultiScreenTool.instanceHorizontal前请先调用MultiScreenTool。init进行初始化,只需调用一次。"
* );
* }
*/
if (instanceHorizontal == null) {
MultiScreenTool.init(Constant.currentActivity);
}
return instanceHorizontal;
}


/**
* 取得屏幕X方向的像素值px

* @return
*/
public int getScreenXDp() {
// density= px/dp 是对的
return displayMetrics.widthPixels;
}


/**
* 取屏幕Y方向的像素值px

* @return
*/
public int getScreenYDp() {
return displayMetrics.heightPixels;
}


/**
* 输入一个X方向的数值,返回一个经过调整、适应多屏幕的px值

* @param xInPx
*            X方向的px值
* @return 适应多屏幕的像素值px
*/
public int adjustX(int xInPx) {
int ret = (int) (xInPx * displayMetrics.widthPixels / this.defaultX * this.defaultDensity / this.nowDensity + 0.5f);
if (ret > displayMetrics.widthPixels) {
ret = displayMetrics.widthPixels;
}
return ret;
}


/**
* 输入一个X方向的数值,返回一个经过调整、适应多屏幕的px值

* @param xInPx
*            X方向的px值
* @return 适应多屏幕的像素值px
*/
private float adjustXInFloat(float xInPx) {
float ret = xInPx * displayMetrics.widthPixels / this.defaultX * this.defaultDensity / this.nowDensity + 0.5f;
if (ret > displayMetrics.widthPixels) {
ret = displayMetrics.widthPixels;
}
return ret;
}


/**
* 输入一个Y方向的数值,返回一个经过调整、适应多屏幕的px值

* @param yInPx
*            Y方向的px值
* @return 适应多屏幕的像素值px
*/
public int adjustY(int yInPx) {
int ret = (int) (yInPx * displayMetrics.heightPixels / this.defaultY * this.defaultDensity / this.nowDensity + 0.5f);
if (ret > displayMetrics.heightPixels) {
ret = displayMetrics.heightPixels;
}
return ret;
}


/**
* 输入一个X方向的数值,返回一个经过调整、适应多屏幕的px值

* @param xInPx
*            X方向的px值
* @return 适应多屏幕的像素值px
*/
public int adjustXIgnoreDensity(int xInPx) {
int ret = (int) (xInPx * displayMetrics.widthPixels / this.defaultX);
if (ret > displayMetrics.widthPixels) {
ret = displayMetrics.widthPixels;
}
return ret;
}


/**
* 输入一个Y方向的数值,返回一个经过调整、适应多屏幕的px值

* @param yInPx
*            Y方向的px值
* @return 适应多屏幕的像素值px
*/
public int adjustYIgnoreDensity(int yInPx) {
int ret = (int) (yInPx * displayMetrics.heightPixels / this.defaultY);
if (ret > displayMetrics.heightPixels) {
ret = displayMetrics.heightPixels;
}
return ret;
}


public void adjustView(View view) {
adjustView(view, true);
}


/**
* 调整某个View的位置、大小以适应多屏幕

* @param view
* @param addOnHierarchyChangeListener 是否添加UI变动监听器
*/
public void adjustView(View view, boolean addOnHierarchyChangeListener) {
if (view.getLayoutParams() == null) {
//Log.i("MultiScreenTool", "Error: MultiScreenTool.adjustView:参数view.getLayoutParams() == null,view未应该在加入到layout后才调用此函数。");
return;
}
// if (this.getDebugId() != null && this.getDebugId().equals(getViewCode(view))) {
// //Log.i("MultiScreenTool", "stop here");
// }
if (view instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < vg.getChildCount(); ++i) {
adjustView(vg.getChildAt(i), addOnHierarchyChangeListener);
}
// 所有可能有adapter的
if (addOnHierarchyChangeListener) {
vg.setOnHierarchyChangeListener(new HierarchyChangeListener(this));
}
}
//System.out.printf(view.hashCode() + "");
// if (hasAdjust.get(getViewCode(view)) != null) {
// return;
// } else {
// hasAdjust.put(getViewCode(view), true);
// Log.i("MultiScreenTool", "hasAdjust.size(): " + hasAdjust.size());
// }
// if (view.getTag(tagId) != null) {
// return;
// } else {
// view.setTag(tagId, true);
// }
int tmp = 0;
// boolean hasAdjust = false;
// 调整layout 参数
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
// Log.i("MultiScreenTool", "density=" + displayMetrics.density + "width=" + lp.width + "height=" + lp.height + "leftMargin="
// + lp.leftMargin + "topMargin=" + lp.topMargin + "bottomMargin=" + lp.bottomMargin + "rightMargin=" + lp.rightMargin);
// view.getd
if (lp.height > 0) {
lp.height = this.adjustY((int) (lp.height));
// hasAdjust = true;
} else if (lp.height == RelativeLayout.LayoutParams.WRAP_CONTENT) {
tmp = view.getMeasuredHeight();
if (tmp != 0) {
lp.height = this.adjustY(tmp);
}
}
if (lp.width > 0) {
lp.width = this.adjustX((int) (lp.width));
// hasAdjust = true;
} else if (lp.width == RelativeLayout.LayoutParams.WRAP_CONTENT) {
tmp = view.getMeasuredWidth();
if (tmp != 0) {
lp.width = this.adjustX(tmp);
}
}
lp.leftMargin = this.adjustX((int) (lp.leftMargin));
lp.topMargin = this.adjustY((int) (lp.topMargin));
lp.bottomMargin = this.adjustY((int) (lp.bottomMargin));
lp.rightMargin = this.adjustX((int) (lp.rightMargin));
// Log.i("MultiScreenTool", "width=" + lp.width + "height=" + lp.height + "leftMargin=" + lp.leftMargin + "topMargin=" + lp.topMargin
// + "bottomMargin=" + lp.bottomMargin + "rightMargin=" + lp.rightMargin);
view.setLayoutParams(lp);
// 调整padding参数
view.setPadding(this.adjustX(view.getPaddingLeft()), this.adjustY(view.getPaddingTop()), this.adjustX(view.getPaddingRight()), this.adjustY(view.getPaddingBottom()));
} else if (view.getLayoutParams() instanceof ViewGroup.LayoutParams) {
ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) view.getLayoutParams();
// view.getd
if (lp.height > 0) {
lp.height = this.adjustY((int) (lp.height));
// hasAdjust = true;
} else if (lp.height == RelativeLayout.LayoutParams.WRAP_CONTENT) {
tmp = view.getMeasuredHeight();
if (tmp != 0) {
lp.height = this.adjustY(tmp);
}
}
if (lp.width > 0) {
lp.width = this.adjustX((int) (lp.width));
// hasAdjust = true;
} else if (lp.width == RelativeLayout.LayoutParams.WRAP_CONTENT) {
tmp = view.getMeasuredWidth();
if (tmp != 0) {
lp.width = this.adjustX(tmp);
}
}
view.setLayoutParams(lp);
// 调整padding参数
view.setPadding(this.adjustX(view.getPaddingLeft()), this.adjustY(view.getPaddingTop()), this.adjustX(view.getPaddingRight()), this.adjustY(view.getPaddingBottom()));
} else {
// Log.i("MultiScreenTool", "MultiScreenTool: 以下layoutparams()类型没有处理" + view.getLayoutParams().getClass().toString());
}
//如果是图片,而且没有被调整,那么多半是因为设置了背景图,view中娶不到宽高,这里做特殊 处理
// if (view instanceof ImageView && hasAdjust == false){
// int bgWidth = view.getBackground().getMinimumWidth();
// bgWidth = this.adjustX(bgWidth);
// int bgHight = view.getBackground().getMinimumHeight();
// bgHight = this.adjustY(bgHight);
// ViewGroup.LayoutParams rlp = view.getLayoutParams();
// rlp.height = bgHight;
// rlp.width = bgWidth;
// view.setLayoutParams(rlp);
// }
// 调整字体大小
if (view instanceof android.widget.TextView) {
android.widget.TextView tv = (android.widget.TextView) view;
float textSizeInPx = tv.getTextSize();
textSizeInPx = this.adjustXInFloat(textSizeInPx);
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizeInPx);
}
}


/**
* 将某个view及下面的所有子view的登记信息从登记表中清除,后面窗口重新初始化时才能调整

* @param view
*/
public void unRegisterView(View view) {
//// if (this.getDebugId() != null && this.getDebugId().equals(getViewCode(view))) {
//// Log.i("MultiScreenTool", "stop here");
//// }
//// if (view instanceof ViewGroup) {
//// ViewGroup vg = (ViewGroup) view;
//// for (int i = 0; i < vg.getChildCount(); ++i) {
//// unRegisterView(vg.getChildAt(i));
//// }
//// }
//// // System.out.printf(view.getId()+ "");
////// if (hasAdjust.get(getViewCode(view)) != null) {
////// hasAdjust.remove(getViewCode(view));
////// }
////
//// view.setTag(tagId,null);
// return;
}


private String getViewCode(View view) {
String code = view.hashCode() + "_" + view.getId();
return code;
}


/**
* 调整ImageView,这张ImageView中一般取不到图片的宽和高,所以使用adjustView无法调整
* @param view
*/
public ViewGroup.LayoutParams getAdjustLayoutParamsForImageView(ImageView view) {
if (view.getTag(tagId) != null) {
return view.getLayoutParams();
} else {
view.setTag(tagId, true);
}
int bgWidth = view.getBackground().getMinimumWidth();
bgWidth = this.adjustXIgnoreDensity(bgWidth);
int bgHight = view.getBackground().getMinimumHeight();
bgHight = this.adjustYIgnoreDensity(bgHight);
ViewGroup.LayoutParams rlp = new ViewGroup.LayoutParams(bgWidth, bgHight);
return rlp;
}


/**
* 检查屏幕尺寸是否变化(有些平板,横竖转换转换后其高宽和原来不一样)
* @param act 调用的activity 
*/
// public void checkWidthAndHeight(Activity act) {
public void checkWidthAndHeight() {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
if (dm.widthPixels > dm.heightPixels) {
if (this.displayMetrics.widthPixels > this.displayMetrics.heightPixels) {
this.displayMetrics.widthPixels = dm.widthPixels;
this.displayMetrics.heightPixels = dm.heightPixels;
} else {
this.displayMetrics.widthPixels = dm.heightPixels;
this.displayMetrics.heightPixels = dm.widthPixels;
}
} else {
if (this.displayMetrics.widthPixels > this.displayMetrics.heightPixels) {
this.displayMetrics.widthPixels = dm.heightPixels;
this.displayMetrics.heightPixels = dm.widthPixels;
} else {
this.displayMetrics.widthPixels = dm.widthPixels;
this.displayMetrics.heightPixels = dm.heightPixels;
}
}
}
}

(注:这里的Constant是一个保存当前activity常量的类)

二、使用方法

1、可以在BaseActivity的onCreate()中进行初始化

public class BaseActivity extends Activity {


protected MultiScreenTool mst = null;
public Handler handler;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Constant.currentActivity = this;
// 判断横屏竖屏,初始化多屏幕适应工具
if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
mst = MultiScreenTool.singleTonHolizontal();
} else {
mst = MultiScreenTool.singleTonVertical();
}
mst.checkWidthAndHeight();
ActivityPool.push(this);
}


@Override
protected void onStart() {
super.onStart();
Constant.currentActivity = this;
if (!getClass().equals(StartActivity.class)) {// 是否是启动页面
mst.checkWidthAndHeight();
}
}


@Override
protected void onResume() {
super.onResume();
Constant.currentActivity = this;
DCAgent.onResume(this);
// 获取得屏幕分辨率
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
if (dm.widthPixels > dm.heightPixels) {
Constant.SCREEN_WIDTH = dm.widthPixels;
Constant.SCREEN_HEIGHT = dm.heightPixels;
} else {
Constant.SCREEN_WIDTH = dm.heightPixels;
Constant.SCREEN_HEIGHT = dm.widthPixels;
}
}


@Override
protected void onPause() {
super.onPause();
DCAgent.onPause(this);
}


@Override
protected void onDestroy() {
super.onDestroy();
mst = null;
}


@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
default:
break;
}
return super.onKeyDown(keyCode, event);
}


public void finishSelf() {
ActivityPool.remove(this);
this.finish();
}

}

(注:这只是一个例子,只需选取与mst相关的内容即可)


2、调用mst对象进行调整

RelativeLayoutmainRelativeLayout = (RelativeLayout) findViewById(R.id.main_relativeLayout);
       mst.adjustView(mainRelativeLayout);

(main_relativeLayout为需要进行适配屏幕的布局)



android屏幕适配

标签:android屏幕适配

原文地址:http://blog.csdn.net/u012408019/article/details/39182197

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!