好吧,很久没有写了。不过我也从没有想过放弃,给自己点个赞。。。。
昨天晚上主要把之前学的按钮绑定事件做了一个练习,写了一个短信发送器。现在开始分析编写过程。
首先还是布局,用到了两个文本显示控件TextView标签、一个号码输入框、一个多行文本输入框、一个按钮。
<!--
号码输入
1 在修改id属性时,注意把后面用到这个id的地方也一并修改
2 文本字体大小属性textSize,尺寸单位建议使用sp,而不是px或dp
-->
<TextView
android:id="@+id/tv_inputTel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/inputTel"
android:textSize="15sp" />
这里讲到了尺寸单位这个概念,我从网上找来了它们的详细解释(
原文传送门):
px:
即像素,1px代表屏幕上一个物理的像素点;
px单位不被建议使用,因为同样100px的图片,在不同手机上显示的实际大小可能不同,如下图所示(图片来自android developer guide,下同)。
偶尔用到px的情况,是需要画1像素表格线或阴影线的时候,用其他单位如dp会显得模糊。
dp:
这个是最常用但也最难理解的尺寸单位。它与“像素密度”密切相关,所以首先我们解释一下什么是像素密度。假设有一部手机,屏幕的物理尺寸为1.5英寸x2英寸,屏幕分辨率为240x320,则我们可以计算出在这部手机的屏幕上,每英寸包含的像素点的数量为240/1.5=160dpi(横向)或320/2=160dpi(纵向),160dpi就是这部手机的像素密度,像素密度的单位dpi是Dots Per Inch的缩写,即每英寸像素数量。横向和纵向的这个值都是相同的,原因是大部分手机屏幕使用正方形的像素点。
不同的手机/平板可能具有不同的像素密度,例如同为4寸手机,有480x320分辨率的也有800x480分辨率的,前者的像素密度就比较低。Android系统定义了四种像素密度:低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi),它们对应的dp到px的系数分别为0.75、1、1.5和2,这个系数乘以dp长度就是像素数。例如界面上有一个长度为“80dp”的图片,那么它在240dpi的手机上实际显示为80x1.5=120px,在320dpi的手机上实际显示为80x2=160px。如果你拿这两部手机放在一起对比,会发现这个图片的物理尺寸“差不多”,这就是使用dp作为单位的效果,见下图。
是不是所有android手机的屏幕宽度用dp衡量都是固定值(例如320dp)呢?答案是否定的,如果写一个程序画宽度等于320dp的横线,在不同手机上运行,会发现在有些手机上横线比手机屏幕短,有些则比屏幕长,在平板上与手机上相比差别则更加明显。
dip:
与dp完全相同,只是名字不同而已。在早期的Android版本里多使用dip,后来为了与sp统一就建议使用dp这个名字了。
sp:
与缩放无关的抽象像素(Scale-independent Pixel)。sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。
还有几个比较少用到的尺寸单位:
mm:
即毫米;
in:
即英寸,1英寸=2.54厘米(约);
pt:
1pt=1/72英寸=0.035厘米;
最佳实践,文字的尺寸一律用sp单位,非文字的尺寸一律使用dp单位。例如textSize="16sp"、layout_width="60dp";偶尔需要使用px单位,例如需要在屏幕上画一条细的分隔线时:
<View layout_width="match_parent" layout_height="1px"/>
另外,文本编辑框还学到了一个属性,那就是定义文本框可以显示多行的属性lines。
接下来就是.java文件里的内容了,采用了第三种绑定方式,实现OnClickListener接口,重写onClick方法,然后在onCreate方法里给按钮绑定,用的是setOnClickListener方法。
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.bt_send:
//获取号码,短信内容字符串
String num = etTel.getText().toString().trim();
String context = etContext.getText().toString().trim();
if(TextUtils.isEmpty(num)){
Toast.makeText(this, "电话号码不能为空", Toast.LENGTH_SHORT).show();
return;
}else if(TextUtils.isEmpty(context)){
Toast.makeText(this, "短信内容不能为空", Toast.LENGTH_SHORT).show();
return;
}else{
//发送短信用到的类SmsManager
SmsManager sms = SmsManager.getDefault();
//如果输入的短信内容超过140个字符,那么将分多次发送
ArrayList<String> contexts = sms.divideMessage(context);
for(String str : contexts){
sms.sendTextMessage(num, null, str, null, null);
}
}
break;
}
}
在重写onClick方法时,我又学到了一些东西:
1.使用短信管理SmsManager这个类的时候,声明变量并不是new一个,而是调用了静态方法getDefault方法(我猜这个就是用了java设计模式里面的单例模式,singleton)。
2.短信发送最多140个字符/70个汉字,为预防超出,就分开发送。具体做法是调用SmsManager里的divideMessage方法来分割短信内容context,返回的是一个ArrayList。然后循环ArrayList,调用SmsManager的sendTextMessage发送文本型短信,其中需要传递五个参数,他们是什么且对应什么:destinationAddress—目的地地址(目标电话号码);scAddress—虚拟本地地址(虚拟本机号码);text—短信内容;sentIntent—发送的意图;deliveryIntent—交付的意图;
前三个参数都比较好理解,后两个是什么鬼东西?下面是百度来的:
sentIntent | 如果不为null,当短信发送成功或者失败时,这个PendingIntent会被广播出去成功的结果代码是Activity.RESULT_OK,或者下面这些错误之一 RESULT_ERROR_GENERIC_FAILURE RESULT_ERROR_RADIO_OFF RESULT_ERROR_NULL_PDU 对于 RESULT_ERROR_GENERIC_FAILURE, |
---|---|
deliveryIntent | 如果不为null,当这个短信发送到接收者那里,这个PendtingIntent会被广播,状态报告生成的pdu(指对等层次之间传递的数据单位)会拓展到数据("pdu") |
这次学习到的就这么多了,我们下期再见(我相信会很快)。。。