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 hasAdjust = new HashMap();
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為需要進行適配螢幕的布局)