1. 程式人生 > >Android 安卓UI介面自適配

Android 安卓UI介面自適配

安卓機器有各種尺寸,UI介面逐個適配比較麻煩。

UI介面自動適配 示例:

           

適配函式:AutoSize(View view, int w, int h, int DesignW, int DesignH)


package sci.demo.androidautofit;

import sci.tool.ActivityComponent;
import android.os.Bundle;
import android.widget.RelativeLayout;


/** MsgPage.java:自適應尺寸資訊顯示介面示例 ----- 2018-11-1 上午10:07:54 scimence */
public class MsgPage extends ActivityComponent
{
	/** 設定介面顯示 */
	@Override
	public void Init(Bundle savedInstanceState)
	{
		this.setContentView("autofit_msg_page");
		
		RelativeLayout lPic = RelativeLayout("auto_msg_page_bg");	// 背景圖佈局Layout
		setAutofitBackground(lPic, "autofit_msg_pic");				// 為view新增自適應尺寸的影象
		
		setAutofitBackground(RelativeLayout("autofit_msg_page_btn"), "autofit_msg_wait");	// 為按鈕新增自適應尺寸的影象
	}
	
	/** 設定View點選響應邏輯 */
	@Override
	public void Click(String viewId)
	{
		if (viewId.equals("auto_msg_page_bg") || viewId.equals("autofit_msg_page_btn"))	// 點選了按鈕或者背景圖時,關閉介面
		{
			this.finish();
		}
	}
	
}
package sci.tool;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.ToggleButton;


/** Componet.java: 建立Componet後可按控制元件字串名稱進行檢索呼叫 ----- 2018-6-7 上午11:00:03 scimence */
public abstract class ActivityComponent extends Activity
{
	/** 顯示當前頁面 */
	public static void Show(Context context, Class<?> cls)
	{
		Intent intent = new Intent(context, cls);        	// 新的支付呼叫邏輯
		
		// intent.putExtra("appId", PackageName);
		// intent.putExtra("uid", ClientId);
		
		context.startActivity(intent);
	}
	
	/** 根據資源型別、名稱,獲取資源id */
	public static int getId(Context context, String name, String defType)
	{
		return context.getResources().getIdentifier(name, defType, context.getPackageName());
	}
	
	/** 根據資源id,獲取資源名稱 club.scimence.www.app_second:id/thumbsup_tittle_bg */
	public String getResourceName(int resid)
	{
		if (resid == -1) return "";
		return context.getResources().getResourceName(resid);
	}
	
	/** 獲取View對應的id字串不含包名字首,如:thumbsup_tittle_bg */
	public String getViewId(View view)
	{
		int resId = view.getId();
		String pageResName = getResourceName(resId);
		// if(pageResName.startsWith("club.scimence")) pageResName = pageResName + "";
		String packagePerfix = context.getPackageName() + ":id/";
		
		String Id = "";
		if (pageResName.startsWith(packagePerfix)) Id = pageResName.substring(packagePerfix.length());
		
		return Id;
	}
	
	/** 根據資源名稱,獲取Drawable */
	@SuppressWarnings("deprecation")
	public static Drawable getDrawable(Context context, String drawableName)
	{
		int id = getId(context, drawableName, "drawable");
		// Drawable pic = context.getResources().getDrawable(id); 		// 從Resources直接獲取影象尺寸會被修改
		
		InputStream in = context.getResources().openRawResource(id);	// 直接解析未處理過的影象資源保持原有尺寸
		Bitmap bitmap = BitmapFactory.decodeStream(in);
		BitmapDrawable pic = new BitmapDrawable(bitmap);
		
		return pic;
	}
	
	Activity context;
	OnClickListener clickListener;
	
	HashMap<String, View> Views = new HashMap<String, View>();
	
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		context = this;
		
		Init(savedInstanceState);
		setClickAble();
	}
	
	/** 設定頁面佈局layout檔名稱(不含字尾) */
	public void setContentView(String layoutName)
	{
		int layoutId = ActivityComponent.getId(this, layoutName, "layout");     // 獲取頁面佈局id
		setContentView(layoutId);												// 設定佈局
	}
	
	/** 初始化子類介面 */
	public abstract void Init(Bundle savedInstanceState);
	
	/** 為所有設定android:id="@+id/**"屬性的View,新增點選處理邏輯物件 */
	public void setClickAble()
	{
		// 點選響應處理邏輯
		clickListener = new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				
				// String key = getViewId(v);
				// Click(key);
				
				// 從已存在的控制元件中進行檢索
				for (String key : Views.keySet())
				{
					if (Views.get(key) == v)
					{
						// if (listener0 != null) listener0.Click(key);
						Click(key);
					}
				}
			}
		};
		
		// 設定可點選的按鈕
		List<View> list = Childs(this);
		for (View V : list)
		{
			String key = getViewId(V);  // 獲取View的Id名稱
			if (!key.equals(""))
			{                           // 設定了android:id屬性的View,為其新增點選響應
				if (!Views.containsKey(key)) Views.put(key, V); // 記錄View的Id屬性
				V.setOnClickListener(clickListener);
			}
		}
	}
	
	/** 記錄Id對應控制元件 */
	public void AddView(String... Id)
	{
		for (String id : Id)
		{
			if (!id.equals("") && !Views.containsKey(id))
			{
				try
				{
					View view = context.findViewById(getId(context, id, "id"));
					Views.put(id, view);
					
					view.setOnClickListener(clickListener);
				}
				catch (Exception ex)
				{
					ex.printStackTrace();
				}
			}
		}
	}
	
	/** 獲取Id對應控制元件 */
	public View GetView(String Id)
	{
		if (!Views.containsKey(Id)) AddView(Id);
		return Views.get(Id);
	}
	
	public TextView TextView(String Id)
	{
		return (TextView) GetView(Id);
	}
	
	public EditText EditText(String Id)
	{
		return (EditText) GetView(Id);
	}
	
	public Button Button(String Id)
	{
		return (Button) GetView(Id);
	}
	
	public RadioButton RadioButton(String Id)
	{
		return (RadioButton) GetView(Id);
	}
	
	public LinearLayout LinearLayout(String Id)
	{
		return (LinearLayout) GetView(Id);
	}
	
	public RelativeLayout RelativeLayout(String Id)
	{
		return (RelativeLayout) GetView(Id);
	}
	
	public ImageView ImageView(String Id)
	{
		return (ImageView) GetView(Id);
	}
	
	public ToggleButton ToggleButton(String Id)
	{
		return (ToggleButton) GetView(Id);
	}
	
	// /** View控制元件點選回撥處理邏輯 */
	// public abstract static interface ClickListener
	// {
	// public abstract void Click(String viewId);
	// }
	//
	// public ClickListener listener = new ClickListener()
	// {
	// @Override
	// public void Click(String viewId)
	// {
	// if (viewId.equals("thumbsup_close")) // 關閉介面按鈕
	// {
	//
	// }
	// else if (viewId.equals("ltpay_text_unuseable"))
	// {
	//
	// }
	// }
	// };
	
	/** 子類繼承自此實現點選響應 */
	public abstract void Click(String viewId);
	
	// -----------------
	
	/** 獲取 activity中的所有view */
	public static List<View> Childs(Activity act)
	{
		View activityRoot = act.getWindow().getDecorView();
		List<View> list = Childs(activityRoot, false);
		
		return list;
	}
	
	/** 獲取當前View的所有子view */
	public static List<View> Childs(View view, boolean ContainsThis)
	{
		List<View> viewList = new ArrayList<View>();
		
		if (!viewList.contains(view)) viewList.add(view);
		if (view instanceof ViewGroup)
		{
			ViewGroup group = (ViewGroup) view;
			for (int i = 0; i < group.getChildCount(); i++)
			{
				View child = group.getChildAt(i);
				if (!viewList.contains(child)) viewList.add(child);
				
				// 新增child的子節點
				List<View> subList = Childs(child, true);
				for (View v : subList)
				{
					if (!viewList.contains(v)) viewList.addAll(subList);
				}
			}
		}
		
		if (!ContainsThis) viewList.remove(view);
		
		return viewList;
	}
	

	// --------------
	// View尺寸自動適配

	// 影象資源應與設計寬高匹配
	public static int SCREEN_DESIGN_WIDTH = 720;	// 設計介面時,介面整體寬度
	public static int SCREEN_DESIGN_HEIGHT = 1280;	// 設計介面時,介面整體高度
	
	/** 將View以Drawable相對於 DesignW,DesignH的比例顯示 */
	public static void AutoSize(View view, Drawable drawable, int DesignW, int DesignH)
	{
		Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();
		
		AutoSize(view, w, h, DesignW, DesignH);
	}
	
	
	/** 將View以 w,h 相對於  DesignW,DesignH的比例顯示。
	 * 
	 * 適配原理:1、先計算寬高在設計螢幕中的尺寸比例值;
	 * 2、取佔比值較大的寬度比例值,或佔比值較大的高度比例值,為縮放比例值。
	 * 3、按比例值縮放影象尺寸至待適配螢幕的最適尺寸
	 *  */
	public static void AutoSize(View view, int w, int h, int DesignW, int DesignH)
	{
		Context context = view.getContext();
		DisplayMetrics dm = context.getResources().getDisplayMetrics();
		int screenWidth = dm.widthPixels;
		int screenHeight = dm.heightPixels;
		
		boolean portrait = (screenHeight > screenWidth);
		
		// 先計算寬高在設計螢幕中的尺寸比例值;
		float skW = w / (float) (portrait ? DesignW : DesignH);
		float skH = h / (float) (portrait ? DesignH : DesignW);
		// float sk = skW > skH ? skW : skH; // 以寬高較大的比例值進行尺寸適配
		
		// 生成相對於螢幕的尺寸,以寬高較大比例值充滿螢幕
		int width = w, height = h;
		if (skW >= skH)							// 寬度比例值大於高度比例值時,已寬度比例值為基準
		{
			width = (int) (skW * screenWidth);	// 按比例值,縮放至螢幕對應尺寸
			height = (int) (width * h / w);		// 按原影象寬高比例,獲取高度尺寸,影象不會拉伸變形
		}
		else									// 高度比例值大於寬度比例值時,已高度比例值為基準
		{
			height = (int) (skH * screenHeight);
			width = (int) (height * w / h);
		}
		
		// 設定顯示尺寸
		ViewGroup.LayoutParams params = view.getLayoutParams();
		// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
		params.width = width;
		params.height = height;
		view.setLayoutParams(params);
	}
	
	/** 為viewt新增自動適配尺寸的背景圖drawableName */
	public static void setAutofitBackground(View view, String drawableName)
	{
		Drawable drawablePic = getDrawable(view.getContext(), drawableName);	// 從context獲取drawableName對應的影象
		view.setBackground(drawablePic);										// 為view新增背景影象		
		
		AutoSize(view, drawablePic, SCREEN_DESIGN_WIDTH, SCREEN_DESIGN_HEIGHT);	// 為view自動適配尺寸
	}
	// --------------
	
}