术语和概念
屏幕尺寸
屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如2.8寸,3.5寸)。
简而言之,Android把所有的屏幕尺寸简化为四类:超大、大、正常、小。 (small, normal, large, and extra large.)
程序可以针对这四种尺寸的屏幕提供三种不同的布局方案,然后系统会负责把你的布局方案以合适的方式渲染到对应的屏幕上,这个过程是不需要程序员用代码来干预的。
屏幕密度
物理屏幕上的像素总数。与尺寸类似,也有四种: 低、中、高、超高。 ( low, medium, high, and extra high.) 密度较低的屏幕,在长和宽方向都只有比较少的像素,而高密度的屏幕通常则会有很多——甚至会非常非常多——像素排列在同一区域。屏幕的密度是非常重要的,举个例子,长宽以像素为单位定义的界面元素(比如一个按钮),在低密度的屏幕上会显得很大,但在高密度的屏幕上则会显得很小。
屏幕长宽比
屏幕的物理长度与物理宽度的比例。程序可以为制定长宽比的屏幕提供制定的素材,只需要用系统提供的资源分类符long和notlong。
分辨率
屏幕上拥有的像素的总数。注意,虽然大部分情况下分辨率都被表示为“宽度×长度”,但分辨率并不意味着屏幕长宽比。在Android系统中,程序一般并不直接处理分辨率。
密度无关的像素(DIP)
指一个抽象意义上的像素,程序用它来定义界面元素。它作为一个与实际密度无关的单位,帮助程序员构建一个布局方案(界面元素的宽度,高度,位置)。
一个与密度无关的像素,在逻辑尺寸上,与一个位于像素密度为160DPI的屏幕上的像素是一致的,这也是Android平台所假定的默认显示设备。在运行的时候,平台会以目标屏幕的密度作为基准,“透明地”处理所有需要的DIP缩放操作。要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式:pixels = dips * (density / 160)。举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。我们强烈推荐你用DIP来定义你程序的界面布局,因为这样可以保证你的UI在各种分辨率的屏幕上都可以正常显示。
支持的屏幕分辨率范围
1.5及更早版本的Android系统,在设计的时候假定系统只会运行在一种分辨率的设备上——HVGA(320×480)分辨率,尺寸为3.2寸。由于系统只能工作在一种屏幕上,开发人员就可以针对那个屏幕来编写自己的程序,而无需去考虑程序在其他屏幕上的显示问题。
但自从Android 1.6以来,系统引入了对多种尺寸、多种分辨率屏幕的支持,以此满足拥有各种配置的新平台的运行需求。这就意味着开发人员在针对Android 1.6或更新版系统开发程序的时候,需要为自己的程序在多种分辨率的屏幕上良好显示作出额外的设计。
为了简化程序员面在对各种分辨率时的困扰,也为了具备各种分辨率的平台都可以直接运行这些程序,Android平台将所有的屏幕以密度和分辨率为分类方式,各自分成了四类:
·四种主要的尺寸:超大、大,正常,小;
·四种不同的密度:超高、高(hdpi),中(mdpi)和低(ldpi)。
如果需要的话,程序可以为各种尺寸的屏幕提供不同的资源(主要是布局),也可以为各种密度的屏幕提供不同的资源(主要是位图)。除此以外,程序不需要针对屏幕的尺寸或者密度作出任何额外的处理。在执行的时候,平台会根据屏幕本身的尺寸与密度特性,自动载入对应的资源,并把它们从逻辑像素(DIP,用于定义界面布局)转换成屏幕上的物理像素。
下表列出了Android平台支持的屏幕中一些比较常用的型号,并显示了系统是如何把它们分类到不同的屏幕配置里的。有些屏幕分辨率并不在下面的列表上,但系统仍会把它们归入下列的某一个类型中。
Low density (120), ldpi | Medium density (160), mdpi | High density (240), hdpi | Extra high density (320), xhdpi | |
---|---|---|---|---|
Smallscreen | QVGA (240x320) | 480x640 | ||
Normalscreen | WQVGA400 (240x400) WQVGA432 (240x432) |
HVGA (320x480) | WVGA800 (480x800) WVGA854 (480x854) 600x1024 |
640x960 |
Largescreen | WVGA800** (480x800) WVGA854** (480x854) |
WVGA800* (480x800) WVGA854* (480x854) 600x1024 |
||
Extra Largescreen | 1024x600 | WXGA (1280x800)† 1024x768 1280x768 |
1536x1152 1920x1152 1920x1200 |
2048x1536 2560x1536 2560x1600 |
private LayoutInflater mLayoutInflater = null;
private FrameLayout dynamicChangesView = null;
private View newViewOne = null;
……
mLayoutInflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
newViewOne = mLayoutInflater.inflate(R.layout.view_one, null,false);
dynamicChangesView.addView(newViewOne);
8
17
1
2
3
4
5)view_three.xml
public class DynamicChangesView extends Activity {
private Button selectViewOneBtn = null;
private Button selectViewTwoBtn = null;
private Button selectViewThreeBtn = null;
private LayoutInflater mLayoutInflater = null;
public LinearLayout optionsView = null;
private FrameLayout dynamicChangesView = null;
private View newViewOne = null;
private View newViewTwo = null;
private View newViewThree = null;
private Context mContext = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
private void initData() {
mContext = this;
setContentView(R.layout.activity_view_group);
selectViewOneBtn = (Button) findViewById(R.id.selectViewOneBtn);
selectViewTwoBtn = (Button) findViewById(R.id.selectViewTwoBtn);
selectViewThreeBtn = (Button) findViewById(R.id.selectViewThreeBtn);
optionsView = (LinearLayout) findViewById(R.id.optionsView);
dynamicChangesView = (FrameLayout) findViewById(R.id.dynamicChangesView);
selectViewOneBtn.setOnClickListener(mOnClickListener);
selectViewTwoBtn.setOnClickListener(mOnClickListener);
selectViewThreeBtn.setOnClickListener(mOnClickListener);
dynamicChangesView.setOnClickListener(mOnClickListener);
mLayoutInflater = (LayoutInflater) mContext
.getSystemService(LAYOUT_INFLATER_SERVICE);
newViewOne = mLayoutInflater.inflate(R.layout.view_one, null,false);
newViewTwo = mLayoutInflater.inflate(R.layout.view_two, null,false);
// newViewThree = mLayoutInflater.inflate(R.layout.view_three, null,false);
newViewThree = new ViewThree(mContext);
dynamicChangesView.addView(newViewOne);
}
private OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if(v == selectViewOneBtn){
dynamicChangesView.removeAllViews();
Log.v("", "-----------> selectViewOneBtn");
dynamicChangesView.addView(newViewOne);
}else if(v == selectViewTwoBtn){
dynamicChangesView.removeAllViews();
Log.v("", "-----------> selectViewTwoBtn");
dynamicChangesView.addView(newViewTwo);
}else if(v == selectViewThreeBtn){
dynamicChangesView.removeAllViews();
Log.v("", "-----------> selectViewThreeBtn");
dynamicChangesView.addView(newViewThree);
}else if(v == dynamicChangesView){
if(optionsView.getVisibility() == View.GONE)
optionsView.setVisibility(View.VISIBLE);
else
optionsView.setVisibility(View.GONE);
}
}
};
}
public class ViewThree extends FrameLayout{
private LayoutInflater mLayoutInflater = null;
private Button displayButton = null;
private Button hideButton = null;
private DynamicChangesView mActivity = null;
public ViewThree(Context context) {
super(context);
mActivity = (DynamicChangesView)context;
mLayoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.addView(mLayoutInflater.inflate(R.layout.view_three, null,false));
displayButton = (Button) findViewById(R.id.display_button);
hideButton = (Button) findViewById(R.id.hide_button);
displayButton.setOnClickListener(mOnClickListener);
hideButton.setOnClickListener(mOnClickListener);
}
public ViewThree(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ViewThree(Context context, AttributeSet attrs) {
super(context, attrs);
}
private OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if(v == displayButton){
mActivity.optionsView.setVisibility(View.VISIBLE);
}else if(v == hideButton){
mActivity.optionsView.setVisibility(View.GONE);
}
}
};
}