android螢幕適配的兩種方式
阿新 • • 發佈:2019-02-06
適配中小型專案;
直接上程式碼,程式碼中有註釋,考慮效能方面的原因,只適合中小型的專案,專案大了,會影響效能
step1:
/** * 為了方便框架內部使用application 和得到context上下文 用 */ public class MyApplication extends Application { private static MyApplication instance; public static MyApplication getInstance(){ return instance; } @Override public voidonCreate() { super.onCreate(); instance=this; } }
strp2:
import android.content.Context; import android.util.DisplayMetrics; import android.view.WindowManager; import java.lang.reflect.Field; /** * 用來生成按美工的基準值生成真是裝置需要的寬高值(1920*1080 720*480) */ public class UIUtils { //做成單列 private static UIUtils ourInstance; public static UIUtils getInstance(){ return ourInstance; } public static UIUtils getInstance(Context context){ if (ourInstance==null){ ourInstance=new UIUtils(context); } return ourInstance; } public static final float STANDARD_WIDHT=1080f;//標準值 public static final floatSTANDARD_HEIGHT=1872f;//標準值1920-48(48px表示手機狀態列的高度) public static final String DIMEN_CLASS="com.android.internal.R$dimen";//拿到手機狀態列的高度 //時間裝置解析度 480 800 public float displayMetticsWidth; public float displayMetticsHeight; //初始化 public UIUtils(Context context){ //獲取螢幕的真實寬高 WindowManager windowManager= (WindowManager) context.getSystemService(context.WINDOW_SERVICE); DisplayMetrics displayMetrics=new DisplayMetrics(); if(displayMetticsWidth==0.0f || displayMetticsHeight==0.0f ){ windowManager.getDefaultDisplay().getMetrics(displayMetrics); //獲取狀態列的高度 48 int sysytemBarHeight=getSysytemBarHeight(context); //處理真實寬高問題 if(displayMetrics.widthPixels>displayMetrics.heightPixels){//寬度大於高度,橫屏情況 this.displayMetticsWidth=(float) displayMetrics.heightPixels; this.displayMetticsHeight=(float) displayMetrics.widthPixels-sysytemBarHeight; }else {//豎屏 this.displayMetticsWidth=(float) displayMetrics.widthPixels; this.displayMetticsHeight=(float) displayMetrics.heightPixels-sysytemBarHeight; } } } /** * 獲取狀態列高度 * @param context * @return */ private int getSysytemBarHeight(Context context) { return getValue(context,"com.android.internal.R$dimen","system_bar_height",48); } /** * 獲取畫素 * @param context 上文 * @param attrGroupClass android原始碼中存放維度的類 * @param attrName 狀態列的資訊 * @param deFault 預設預設值 * @return */ private int getValue(Context context, String attrGroupClass, String attrName, int deFault) { try { Class e=Class.forName(attrGroupClass); Object obj=e.newInstance(); Field field =e.getField(attrName); //獲取到的是一個id int x=Integer.parseInt(field.get(obj).toString()); //把id轉化成畫素返回出去 return context.getResources().getDimensionPixelOffset(x); } catch (Exception e1) { // e1.printStackTrace(); return deFault; } } //開始獲取縮放以後的結果 public float getWidth(float width){ return width*this.displayMetticsWidth/STANDARD_WIDHT; } //開始獲取縮放以後的結果 public float getHeight(float height){ return height*this.displayMetticsHeight/STANDARD_HEIGHT; } //開始獲取縮放以後的結果 public int getWidth(int width){ return (int)(width*this.displayMetticsWidth/STANDARD_WIDHT); } //開始獲取縮放以後的結果 public int getHeight(int height){ return (int)(height*this.displayMetticsHeight/STANDARD_HEIGHT); } }
step3:
import android.view.View; import android.widget.LinearLayout; /** * view的計算工具 */ public class ViewCalculateUtil { //獲取呼叫層傳入的值進行設定 public static void setViewLinearLayoutParam(View view, int width,int height,int topMargin, int bottomMargin,int leftMargin,int rightMargin){ LinearLayout.LayoutParams layoutParams= (LinearLayout.LayoutParams) view.getLayoutParams(); if(width !=LinearLayout.LayoutParams.MATCH_PARENT && width !=LinearLayout.LayoutParams.WRAP_CONTENT){ //用自己的My 需要在manifests 中新增 android:name=".MyApplication" layoutParams.width=UIUtils.getInstance(MyApplication.getInstance()).getWidth(width); }else{ layoutParams.width=width; } if(height !=LinearLayout.LayoutParams.MATCH_PARENT && height !=LinearLayout.LayoutParams.WRAP_CONTENT){ //用自己的My 需要在manifests 中新增 android:name=".MyApplication" layoutParams.height=UIUtils.getInstance(MyApplication.getInstance()).getHeight(height); }else{ layoutParams.height=height; } // height 是豎著縮放 // weight 橫著縮放 layoutParams.topMargin=UIUtils.getInstance(MyApplication.getInstance()).getHeight(topMargin); layoutParams.bottomMargin=UIUtils.getInstance(MyApplication.getInstance()).getHeight(bottomMargin); //橫向上百分比計算 layoutParams.leftMargin=UIUtils.getInstance(MyApplication.getInstance()).getWidth(leftMargin); layoutParams.rightMargin=UIUtils.getInstance(MyApplication.getInstance()).getWidth(rightMargin); view.setLayoutParams(layoutParams); } }
在activity如何使用:
importandroid.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView text1; private TextView text2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text1 = (TextView) findViewById(R.id.text1); text2 = (TextView) findViewById(R.id.text2); ViewCalculateUtil.setViewLinearLayoutParam(text1,1040,80,10,0,20,20); ViewCalculateUtil.setViewLinearLayoutParam(text2,400,400,50,0,0,0); } }
執行結果:
第二種方式:
適合中大型專案的方式,效能比較優異
step1:
value裡面的程式碼:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="PercentRelativeLayout"> <!--寬度的百分比--> <attr name="layout_widthPrecent" format="float"></attr> <attr name="layout_heightPrecent" format="float"></attr> </declare-styleable> </resources>
自定義百分比佈局:
importandroid.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; /** * 自定義百分比 RelativeLayout */ public class PrecentRelativeLayout extends RelativeLayout{ public PrecentRelativeLayout(Context context) { super(context); } public PrecentRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public PrecentRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width= ViewGroup.MeasureSpec.getSize(widthMeasureSpec); int height= ViewGroup.MeasureSpec.getSize(heightMeasureSpec); //測量出子控制元件的寬高進行改變 int childCount=this.getChildCount(); for(int i=0;i<childCount;i++){ View child=this.getChildAt(i); ViewGroup.LayoutParams layoutParams=child.getLayoutParams(); //把已經得到的佈局引數進行更改 float widthPrecent=0; float heightPrecent=0; if(layoutParams instanceof PrecentRelativeLayout.LayoutParams){ //獲取到佈局檔案上的內容 widthPrecent = ((LayoutParams) layoutParams).getWidthPrecent(); heightPrecent = ((LayoutParams) layoutParams).getHeightPrecent(); } if(widthPrecent>0){ layoutParams.width=(int)( width * widthPrecent); layoutParams.height=(int)( height * heightPrecent); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); } //通過需要把自定義屬性封裝進去 @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { //返回自己設定好的佈局引數 return new LayoutParams(getContext(),attrs); } public static class LayoutParams extends RelativeLayout.LayoutParams{ private float widthPrecent; private float heightPrecent; public float getWidthPrecent() { return widthPrecent; } public void setWidthPrecent(float widthPrecent) { this.widthPrecent = widthPrecent; } public float getHeightPrecent() { return heightPrecent; } public void setHeightPrecent(float heightPrecent) { this.heightPrecent = heightPrecent; } /** * 把自定義屬性加入 * @param c * @param attrs */ public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray typedArray=c.obtainStyledAttributes(attrs,R.styleable.PercentRelativeLayout); widthPrecent=typedArray.getFloat(R.styleable.PercentRelativeLayout_layout_widthPrecent,this.getWidthPrecent()); heightPrecent=typedArray.getFloat(R.styleable.PercentRelativeLayout_layout_heightPrecent,this.getHeightPrecent()); } public LayoutParams(int w, int h) { super(w, h); } public LayoutParams(ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } public LayoutParams(RelativeLayout.LayoutParams source) { super(source); } } }
step2:
如何使用呢,在layout佈局檔案中做如下程式碼操作,把根據點替換
<?xml version="1.0" encoding="utf-8"?> <com.sj.screenadapter02.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.sj.screenadapter02.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_widthPrecent="0.5" app:layout_heightPrecent="0.5" /> </com.sj.screenadapter02.PercentRelativeLayout>
activity裡面不改變,
執行結果如下:
第三種:這兩種結合起來,可以做成一個萬能適配方案,可以自己嘗試一下,思想就是這樣。