动手学Android之四——布局初步(一)

来源:互联网 发布:win10视频桌面软件 编辑:程序博客网 时间:2024/04/30 12:28

要感恩帮助过你的人

         通过前几节,我们已经大概认识Android程序开发是怎样进行的了,这节我们来讲讲布局的知识。所谓布局,就是把我的控件放到我想放的位置去。那么具体是怎么操作呢?

         我们先建立一个工程,有一个MainActivity,加载一个main.xml的布局文件,让它能够执行起来。这些都是之前的知识了。

         下面我们着重来说说main.xml这个布局文件。

         之前我们已经见识了LinearLayout的一些属性,也知道一些基本控件了,下面我们先来添加两个Button,为了看得更清楚,我们把LinearLayout改成绿色。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#00FF00"    android:orientation="vertical" >        <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/btn1Text"         />        <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="@string/btn2Text"         /></LinearLayout>

         运行一下,我们的界面会是什么样呢?大家肯定可以想象到的。


         如果这时候我想让Button水平排列呢?你肯定想到了,改变LinearLayout的android:orientation="vertical"属性,改成android:orientation=" horizontal",看看效果:


         咦?怎么只有一个Button了?注意,我们Button的android:layout_width="match_parent"呀,也就是说一个Button的宽度就是填充父控件的,另一个Button就没有控件显示了,其实它在屏幕的右边,哈哈,你肯定知道怎么改了android:layout_width="wrap_content"不就OK了!再看看:


         水平排列是水平排列了,可是这是你想要的效果吗?我想让这两个button水平排列,并且填充屏幕耶!我的手机的屏幕宽度是480px,我把每个button的宽度设成240px不就行了,我们来试试:


         好像真的可以耶,不过我们看到eclipse上面显示了一个warning:


         它说不要用px,建议用dp,好吧,我们换成dp试一下:


         啊?怎么变成这样了,eclipse坑了我们,但是eclipse为什么要坑我们呢?我们和它无冤无仇!这里我们就要详细说一说了,在android的布局文件中,可能经常用到3种单位,px、dp、sp,其中sp我们其实也见过了,在上一节设置字体大小的时候,我们就是用的sp呀。那么这几个东西有什么区别呢?我们都知道,这个世界上有很多手机,它们各自有着自己的屏幕,它们屏幕的分辨率也是不一样的,比如说我的手机屏幕分辨率是480X854,注意单位是px(像素),但是也许人家一个同样大小的屏幕(我指的是物理大小),它的分辨率稍微低一点,比如是320X480,那么我这个程序在它的手机上就不能正常显示了,所以android出现了dp这种单位,它是设备无关像素,也就是说用它的话,就可以在不同分辨率的手机上都显示正确,那么它的原理是什么呢?先不着急,给大家看个东西。我们在onCreate中加上:

DisplayMetrics displayMetrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);System.out.println("width : " + displayMetrics.widthPixels + "   height : " + displayMetrics.heightPixels + "   density : " + displayMetrics.density);

         这几句话的意思这里稍微解释下,首先定义了一个DisplayMetrics对象,这个对象代表了屏幕显示参数,然后我们用getWindowManager得到一个WindowManager的对象(匿名对象),再调用它的getDefaultDisplay得到一个Display对象,从而可以得到这个DisplayMetrics,然后我们打印出它的widthPixels、heightPixels和density来看看。那么这个打印出来的东西去哪里看呢,其实就在下面的Logcat里面,我们运行程序,会发现:


看到第二行没有,它打印出来了,但是这样找太难了,犹如大海捞针啊,我们可以为我们的控制台输出信息添加过滤器的:

         我们点击这里的绿色+号:


         在里面填写上过滤器名字:sysout(可以随便取)和by Log Tag:System.out(不能乱写),它代表过滤System.out打印出来的东西,加上后,我们再看:


         在Saved Filters下面多了一个sysout,里面就只有我们打印的信息了,一下子清爽很多啊!这里顺便说一下,System.out.println有快捷键的,我们在eclipse中输入syso然后alt+/键就能自动补全,好用吧?

         这里输出了我的手机屏幕大小480X854px,但是还有一个density,这就是问题所在,其实我们的px=dp*density,这样,我们上面的程序相当于输入了width:240*1.5=360px,所以出现上面的情况了,那么我们知道怎么改了,把width改成160dp就ok了吧?这时候相当于输入了240px呀,试试看吧!

果然OK了。那么对于一个320X480px的手机会是什么效果呢?240px不照样不行么?秘密在于density,在320X480px的手机上,density会等于1,这时候相当于输入了160px,所以显示还是正确的。(这里强烈建议大家在自己的手机上做这个实验,我手头只有一部手机,没办法验证所有分辨率,大家一起做,把结果回复在评论中,团结力量大啊,如果我这里的理解有什么问题还请指出,本人感激不尽!)不过这种方法在pad中貌似不太适用。

         就没有别的办法吗?别着急,我们还有一条路

<Button        android:layout_width="0dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="@string/btn1Text"         />

         我们使用weight属性,为了使用weight属性,我们把width设为0,我们为两个Button分配相同的weight,这里weight表示权重,两个Button权重相同,自然就等宽咯!运行后结果是正确的(不贴图啦)。

         但是这里为什么width=0呢?我们改一改看看:

<Button        android:id="@+id/btn1"        android:layout_width="200dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="@string/btn1Text"         />        <Button        android:id="@+id/btn2"        android:layout_width="100dp"        android:layout_height="wrap_content"        android:layout_weight="1"        android:text="@string/btn2Text"         />

         运行下:


         哈哈,这不就是2:1的比例吗?等等,真的是2:1吗!?请仔细看,不过肉眼很难看出来,我们不如把Button的width输出来看一看!我们为Button增加id(其实我上面已经加了),然后在程序中定义两个Button,用findViewById将其找出来,这些在上节都讲过的哈!然后我们在onCreate中System.out.println("btn1: " + btn1.getWidth() + "  btn2 : " + btn2.getWidth());,看看结果:


!?怎么都是0?啊,这是因为在onCreate中,我们的布局还没有完全加载上,我们延迟一点再调用btn的getWidth方法就行。那怎么办呢?很好办,我们给按钮绑定一个点击事件就好了,在点击事件中输出信息。这个大家都会的吧?这里我用另一种写法:我先定义一个内部类:

class OnBtnClickListener implements OnClickListener {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubSystem.out.println("btn1 : " + btn1.getWidth() + "   btn2 : " + btn2.getWidth());}}

然后申明一个它的变量:

private OnBtnClickListener listener = new OnBtnClickListener();

         然后绑定:

btn1.setOnClickListener(listener);btn2.setOnClickListener(listener);

         这时候我们再来看看(别忘记点按钮哈):


         哈哈,有数据了,但是是315和165耶,可不是320和160,这该怎么解释呢?(这里网上很多博客都没有给出具体计算公式,只是告诉我们一些大概的规则,还引进什么优先级啊的一些莫名其妙的概念)今天我们就利用科学研究方法,来打破这层神秘面纱!我们输入不同的数据,把输出结果记录下来,形成下表:

 

layout_width1

layout_width2

layout_weight1

layout_weight2

real_width1

real_width2

100dp

100dp

1

1

240

240

200dp

100dp

1

1

315

165

300dp

100dp

1

1

390

90

400dp

100dp

1

1

465

15

500dp

100dp

1

1

540

0

500dp

100dp

1

2

610

0

500dp

100dp

2

1

470

10

500dp

100dp

3

1

435

45

500dp

100dp

4

1

414

66

500dp

100dp

5

1

400

80

500dp

100dp

10

2

400

80

match_parent

match_parent

2

1

160

320

wrap_content

wrap_content

不设置

不设置

104

104

wrap_content

wrap_content

2

1

285

195


分析表中数据,你有没有发现weight的算法呢?我好想发现了一个规律,给大家分享一下:

         我们先来道破这神秘的第2条,315和165是怎么得来的?首先,我们把dp换成px,因为最后显示都是以px为标准的嘛,那btn1就是300px,btn2就是150px,而我的屏幕是480px,那两个加起来只有450px啊,还差30px怎么办,看下weight是1:1,好了,哥俩一人一半,所以btn1=300px+30/2px=315px,btn2=150px+30/2px=165px。

         再来看看第4条,btn1是600px,btn2是150px,超出了270px,看下weight是1:1,那就每人减去135px,最后就是btn1=465px,btn2=15px啦,又对了耶!

         那第5条数据呢,我们同样分析,btn1=750px,btn2=150px,多出了420px,weight是1:1,每人减去210px,所以btn1=540px,btn2小于0了,那没办法,只能给0px了!

         那第6条数据呢?btn1=750px,btn2=150px,多出了420px,但是weight是1:2,那这样的话btn1减去140px,btn2减去280px,这样就是1:2啦,算下结果btn1=610px,btn2=0,又对啦!其他的例子大家自己算吧!

         对于match_parent和wrap_content,其实就相当于设成了480px和104px啦!

         这下我们知道为什么把width设为0,它还是1:1地出现了吧?有了这个规律,妈妈再也不用担心我的weight属性搞不定了!(这部分内容我在任何地方都没有看到过,纯属自己研究出来的,转载请说明出处,如有错误请慷慨指出,谢谢!)

         研究累了,这节先到这里吧!总结一下:

1、  dp和px的区别

2、  DisplayMetrics

3、  System.out.println和过滤器的添加

4、  独家之weight属性详解

这节的例子在:http://download.csdn.net/detail/yeluoxiang/7221363。希望大家在自己的机器上跑一跑,把数据贡献出来,大家一起分析啊!






0 0
原创粉丝点击