浅谈屏幕适配之measure(上)

        刚做android的候在制定控件宽高时都习惯用wrap_content,match_parent属性或是直接写一个固定的值,但是在很多情况下,这种做法无法实现屏幕的适配问题。比如一个布局,上面是一个titleBar,下面是一个bottomTab,中间是一个ListView,若用上述的做法,或许在一种分辨率下可以把控件契合的很完美,但是可能换了个分辨率之后,中间的ListView就突然变“短”了或者最下面一部分被bottomTab遮盖了。诚然用weight属性可以解决类似的问题,但是在很多情况下我们还是需要在代码中动态的设置ListView的高度。

       下面就给出一个简单的例子:

xml布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/topBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:background="#00ff00"
        android:gravity="center"
        android:text="TitleBar"
        android:textSize="20sp" />

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/topBar" >
    </ListView>

    <TextView
        android:id="@+id/bottomTab"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:background="#ff0000"
        android:gravity="center"
        android:text="BottomTab"
        android:textSize="20sp" />

</RelativeLayout>
java代码:

public class MainActivity extends Activity {
	private ListView list;
	private List<String> data;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
		setContentView(R.layout.activity_main);
		initView();
		getData();
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1,data);
		list.setAdapter(adapter);
	}

	private void getData() {
		data = new ArrayList<String>();
		for (int i = 0; i < 50; i++) {
			String item = "第" + i + "行";
			data.add(item);
		}
	}

	private void initView() {
		list = (ListView) findViewById(R.id.list);
	}
}



非常基础的一个小例子,效果如下图:


已经拉到最底部,可是总共50行数据却只能显示49行!也就是说有1行被bottomTab遮盖了,解决的思路就是将listView的高度设置成屏幕高度-标题栏状态栏高度-topTitle高度-bottomTab高度,有些人可能会使用weight属性来解决问题,但到底是几比几比几只能一点一点去测试,个人不推荐这种做法。

首先是测量屏幕高度,这个很简单,网上有很多相关代码:

DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
totalHeight = metric.heightPixels;

状态栏和标题栏(应用默认)高度:

View v = getWindow().findViewById(Window.ID_ANDROID_CONTENT);///获得根视图
int topHeight = v.getTop();///状态栏标题栏的总高度

其次是测量底部高度,因为底部高度已经给了一个固定值50dp,所以我们也可以非常方便的获取到:

bottomHeight = bottomTab.getLayoutParams().height;

重点是顶部布局,顶部使用的是wrap_content,我们无法直接使用top.getHeight()或者top.getMeasuredHeight()去获取顶部高度,所以在此引出measure()方法:

titleBar.measure(0, 0);
titleHeight = titleBar.getMeasuredHeight();

最后我们设置listview的高度:

list.getLayoutParams().height = totalHeight-topHeight -titleHeight-bottomHeight;

总结一下,代码如下:

private View bottomTab,titleBar;
private int totalHeight, titleHeight, bottomHeight;// 屏幕高度,titleBar高度,bottomTab高度
private void setListViewHeight() {
		// 测量屏幕高度
		DisplayMetrics metric = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metric);
		totalHeight = metric.heightPixels;
		Log.i("info", "totalHeight>"+totalHeight);
		//标题栏和状态栏高度
		View v = getWindow().findViewById(Window.ID_ANDROID_CONTENT);///获得根视图
		int topHeight = v.getTop();///状态栏标题栏的总高度
		Log.i("info", "topHeight>"+topHeight);</span>
		//底部高度
		bottomHeight = bottomTab.getLayoutParams().height;
		Log.i("info", "bottomHeight>"+bottomHeight);
		//顶部高度
		Log.i("info", "bottomHeightWithoutMeasure>"+titleBar.getMeasuredHeight());
		titleBar.measure(0, 0);
		titleHeight = titleBar.getMeasuredHeight();
		Log.i("info", "bottomHeightWithMeasure>"+titleHeight);		
		//设置listview高度
		list.getLayoutParams().height = totalHeight-topHeight-titleHeight-bottomHeight;
		Log.i("info", "listHeight>"+list.getLayoutParams().height );
	}


效果图:



ok,最后一行成功显示出来!

我们来看看Log输出:



问题解决。


  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值