Android的屏幕实在是太多了,一开始接触Android的时候感觉屏幕适配是个很棘手的问题。在网上也查找了很多种屏幕适配的方式,有说准备5套布局与5套图片的,有编写工具生成不同的values文件的,找了很多都不是很满意。最终由人提醒找到了一个十分简单的方法轻松适配多个屏幕,只需要写分代码一份布局文件,基本上能满足多屏幕适配的要求。
首先定义屏幕宽度与高度:
public static int screenWidth;
public static int screenHeight;
在Oncreate中获得当前屏幕的宽度与高度:
/*
* 得到屏幕真实高度,当手机版本高于4.4且有虚拟键NavigationBar则可以获得到
* */
WindowManager w = this.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics1 = new DisplayMetrics();
d.getMetrics(metrics1);
screenWidth = metrics1.widthPixels;
screenHeight = metrics1.heightPixels;
/*
* 根据sdk获取屏幕是否有虚拟键的屏幕宽度
* */
if (Build.VERSION.SDK_INT < 17)
try {
screenHeight = (Integer) Display.class
.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/navigation bar)
else if (Build.VERSION.SDK_INT >= 17)
try {
android.graphics.Point realSize = new android.graphics.Point();
Display.class
.getMethod("getRealSize", android.graphics.Point.class)
.invoke(d, realSize);
screenHeight = realSize.y;
} catch (Exception e) {
// TODO: handle exception
}
重点在这了:
public int fitX(int n){
return (int)((n/1080.0)*screenWidth);
}
public int fitY(int n){
return (int)((n/1920.0)*screenHeight);
}
由于我们公司的项目只给了1080的屏幕的设计图,所以此处我以1080为基准建立了2个方法,传入的n是以设计图所设计的px值,利用n与1080屏幕进行相除得到比例乘以当前屏幕的宽度就得到了在当前屏幕中所要用到的宽度值。
接下来是用代码根据设计图来设计布局:
如图是一个以1080为基准的设计图,以中间的刻度盘为例,他是水平居中,上边距为182px,先看布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#141414"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/qs_accelerator_2"
android:scaleType="center"
android:id="@+id/qs_accelerator_2"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:scaleType="center"
android:src="@drawable/qs_accelerator_6"
android:id="@+id/qs_accelerator_1"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/qs_accelerator_2"
android:layout_centerHorizontal="true"
android:clickable="true"
android:scaleType="center"
android:src="@drawable/qs_accelerator_3"
android:id="@+id/qs_accelerator_3"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_exceed"
android:textSize="25sp"
android:textColor="#ffffff"
android:layout_centerHorizontal="true"
android:text="EXCEED"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_exceed"
android:id="@+id/tv_exceed_num"
android:layout_centerHorizontal="true"
android:text="233"
android:textColor="#ffffff"
android:textSize="25sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_speeding"
android:text="SPEEDING"
android:textColor="#ec1d23"
android:layout_centerHorizontal="true"
android:textSize="25sp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/speeding_bg"
android:layout_centerHorizontal="true"
android:id="@+id/speeding_sign"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/tv_exceed_num"
android:layout_below="@+id/tv_exceed"
android:id="@+id/exceed_sign"
android:src="@drawable/qs_speed_logo"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#00000000"
android:layout_alignParentBottom="true"
android:id="@+id/qs_bottom_layout">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:clickable="true"
android:scaleType="center"
android:layout_marginLeft="20dp"
android:id="@+id/back"
android:src="@drawable/back"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:scaleType="center"
android:visibility="invisible"
android:layout_centerInParent="true"
android:src="@drawable/qs_accelerator_5"/>
</RelativeLayout>
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/qs_accelerator_2"
android:scaleType="center"
android:id="@+id/qs_accelerator_2"
/>
id为
qs_accelerator_2为中间的刻度表,此时我设定他水平居中
android:layout_centerHorizontal="true"
但是我并不在布局中设置他是上边距android:layout_marginTop="" ?如果设置成dp的话那在有一些屏幕是无法完美适配的,此处我们可以来看代码:
package com.tenifs.nuenue;
import java.io.IOException;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import org.msgpack.MessagePack;
import org.msgpack.type.MapValue;
import org.msgpack.type.ValueFactory;
import net.tsz.afinal.http.AjaxCallBack;
import net.tsz.afinal.http.AjaxParams;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.tenifs.nuenue.CommonDialog.OnCustomDialogListener;
import com.tenifs.nuenue.app.MyApplication;
import com.tenifs.nuenue.unti.Content;
public class AcceleratorActivity extends BaseActivity implements OnTouchListener{
MyApplication application;
View view;
<span style="color:#ff0000;">ImageView qs_accelerator_1;</span>
ImageView qs_accelerator_2;
ImageView qs_accelerator_3;
ImageView speeding_sign;
ImageView exceed_sign;
ImageView back;
TextView tv_exceed;
TextView tv_exceed_num;
TextView tv_speeding;
RelativeLayout qs_bottom_layout;
ValueAnimator animator;
int screenWidth;
int screenHeight;
int rotate_angle =0;
boolean handle_flag;
private Timer mTimer = null;
private TimerTask mTimerTask = null;
int question_id = 0;
int speed = 0;
int blingCount = 0;
int exceed_num;
boolean click_flag = true;
int speedTime= 0;
private Handler mHandler = null;
private int status = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
SoundPool soundPool;
HashMap musicId=new HashMap();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
view = getWindow().getDecorView();
HideNavigationBar.hideSystemUI(view);
super.onCreate(savedInstanceState);
setContentView(R.layout.accelerator);
application = MyApplication.getApp();
speedTime = application.getProCount(40001);
soundPool=new SoundPool(5, 0,5);
musicId.put(1, soundPool.load(this, R.raw.accelerator, 1));
Bundle bundle = this.getIntent().getExtras();
question_id=bundle.getInt("question_id");
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
AssetManager mgr = getAssets();
Typeface tf = Typeface.createFromAsset(mgr, "fonts/LCD.TTF");
qs_accelerator_1 = (ImageView) findViewById(R.id.qs_accelerator_1);
qs_accelerator_2 = (ImageView) findViewById(R.id.qs_accelerator_2);
qs_accelerator_3 = (ImageView) findViewById(R.id.qs_accelerator_3);
speeding_sign = (ImageView) findViewById(R.id.speeding_sign);
exceed_sign = (ImageView) findViewById(R.id.exceed_sign);
tv_exceed = (TextView) findViewById(R.id.tv_exceed);
tv_exceed_num = (TextView) findViewById(R.id.tv_exceed_num);
tv_speeding = (TextView) findViewById(R.id.tv_speeding);
back = (ImageView) findViewById(R.id.back);
tv_exceed.setTypeface(tf);
tv_exceed_num.setTypeface(tf);
tv_speeding.setTypeface(tf);
qs_bottom_layout = (RelativeLayout) findViewById(R.id.qs_bottom_layout);
layout();
qs_accelerator_3.setOnTouchListener(this);
back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
AcceleratorActivity.this.finish();
}
});
}
public void layout(){
RelativeLayout.LayoutParams linearParams1 = (android.widget.RelativeLayout.LayoutParams) qs_accelerator_1.getLayoutParams();
linearParams1.topMargin=fitY(187);
qs_accelerator_1.setLayoutParams(linearParams1);
qs_accelerator_2.setLayoutParams(linearParams1);
RelativeLayout.LayoutParams linearParams3 = (android.widget.RelativeLayout.LayoutParams) qs_accelerator_3.getLayoutParams();
linearParams3.topMargin=fitY(395);
qs_accelerator_3.setLayoutParams(linearParams3);
RelativeLayout.LayoutParams linearParams4 = (android.widget.RelativeLayout.LayoutParams) qs_bottom_layout.getLayoutParams();
linearParams4.height=fitY(297);
qs_bottom_layout.setLayoutParams(linearParams4);
RelativeLayout.LayoutParams linearParams5 = (android.widget.RelativeLayout.LayoutParams) tv_exceed.getLayoutParams();
linearParams5.topMargin=fitY(785);
tv_exceed.setLayoutParams(linearParams5);
tv_exceed.setVisibility(View.INVISIBLE);
RelativeLayout.LayoutParams linearParams6 = (android.widget.RelativeLayout.LayoutParams) tv_exceed_num.getLayoutParams();
linearParams6.topMargin=fitY(28);
tv_exceed_num.setLayoutParams(linearParams6);
tv_exceed_num.setVisibility(View.INVISIBLE);
RelativeLayout.LayoutParams linearParams7 = (android.widget.RelativeLayout.LayoutParams) exceed_sign.getLayoutParams();
linearParams7.leftMargin=fitY(27);
linearParams7.topMargin=fitY(28);
exceed_sign.setLayoutParams(linearParams7);
exceed_sign.setVisibility(View.INVISIBLE);
RelativeLayout.LayoutParams linearParams8 = (android.widget.RelativeLayout.LayoutParams) speeding_sign.getLayoutParams();
linearParams8.topMargin=fitY(823);
speeding_sign.setLayoutParams(linearParams8);
speeding_sign.setVisibility(View.INVISIBLE);
RelativeLayout.LayoutParams linearParams9 = (android.widget.RelativeLayout.LayoutParams) tv_speeding.getLayoutParams();
linearParams9.topMargin=fitY(823);
tv_speeding.setLayoutParams(linearParams9);
tv_speeding.setVisibility(View.INVISIBLE);
}
public int fitX(int n){
return (int)((n/1080.0)*screenWidth);
}
public int fitY(int n){
return (int)((n/1920.0)*screenHeight);
}
RelativeLayout.LayoutParams linearParams1 = (android.widget.RelativeLayout.LayoutParams) qs_accelerator_1.getLayoutParams();
linearParams1.topMargin=fitY(187);
qs_accelerator_1.setLayoutParams(linearParams1);
<pre name="code" class="java">public int fitX(int n){
return (int)((n/1080.0)*screenWidth);
}
public int fitY(int n){
return (int)((n/1920.0)*screenHeight);
}
以上的就是用法了,这样设置的话就可以轻松设配各种屏幕了,如果设计图是720p的那只需要把1080换成720。如果控件是图片最好根据1080的设计图设定图片的大小。这个也能在代码中实现:
<span style="white-space:pre"> </span>RelativeLayout.LayoutParams linearParams1 = (android.widget.RelativeLayout.LayoutParams) qs_accelerator_1.getLayoutParams();
linearParams1.topMargin=fitY(187);
<pre name="code" class="java"><span style="white-space:pre"> </span>linearParams1.width=fitX(600);
<span style="white-space:pre"> </span>linearParams1.height=fitX(600);
qs_accelerator_1.setLayoutParams(linearParams1);
这样设定的话,所要用到的图片在各个屏幕下都是和设计图差不多了。不过此方式也有缺点,比如设置文字的大小的话,由于设计图给的是pt,所以只能在布局文件中设置了
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_speeding"
android:text="SPEEDING"
android:textColor="#ec1d23"
android:layout_centerHorizontal="true"
android:textSize="25sp"
/>
这样的话不同屏幕的字体大小会有出入,只能在各个values中设置dimen来设配了。