1. 程式人生 > >android螢幕適配的兩種方式

android螢幕適配的兩種方式

適配中小型專案;

直接上程式碼,程式碼中有註釋,考慮效能方面的原因,只適合中小型的專案,專案大了,會影響效能

  step1:

/**
 * 為了方便框架內部使用application 和得到context上下文 用
 */
public class MyApplication extends Application {

    private static MyApplication instance;
    public static MyApplication getInstance(){
        return instance;
}

    @Override
public void 
onCreate() { 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 float
STANDARD_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裡面不改變,

執行結果如下:


第三種:這兩種結合起來,可以做成一個萬能適配方案,可以自己嘗試一下,思想就是這樣。