Android的平台架构和特性
四层架构:应用层、应用架构层、C++库、Linux
第一层:应用层
第二层:应用框架层
第三层:C++
第四层:Linux框架层
搭建Android开发环境
JDK(1.6以上版本)
Android SDK(软件开发工具包)
Ecilpse 跨平台的自由集成开发环境
ADT 安卓开发工具
整合安装包 adt-bundle-windows 整合了 SDK、Ecilpse、ADT的安装包
都用同一位的(32位,64位):
安装的JDK位数要跟SDK的位数一致
配置sdk到电脑上:adt-bundle-windows\sdk\platform-tools
(配置java环境的话,配置完成,在命令行输入java即可)
配置好之后,在命令输入行输入adb,查看一个配置状态
developer.Android.com
1、Android SDK目录结构
doc:API文档,自学或是解惑
platforms:不同版本的Android系统
platforms 不同版本的系统
Android对应版本号 API Level
2.2 8
2.3 9、10
3.0 11
4.0 14
4.3 18
sources:Android源代码
(查看源代码就关联此文件夹)Extennal folder
tools:Android开发、调试工具
sample:示例程序
platforms-tools:adb.exe
adb.exe 连接开发工具跟模拟器的桥梁
(靠真机连接也是要用到adb.exe)
developer.Android.com
2、模拟器
与真机功能的区别:硬件相关的,通讯、蓝牙、USB、WIFI、电池
横纵屏幕切换: ctrl + F12
退回上一个界面: ESC
回到桌面: HOME
菜单Menu: F2
3、DDMS 虚拟机调试窗口服务(DalvikDebug Monitor Service)
4、Android系统文件目录
/mnt/sdcard目录
/data/app 用户安装的APK(Android App Package)
/data/data 包存档数据
/system/app 系统自带app 区别:权限更高。Root权限
4、ADB(AndroidDebug Bridge)
(1)查看当前运行的模拟器:
adb devices
(2) 当模拟器和eclipce断开连接:
adb kill-server 结束adb进程
adb start-server 重启adb进程
(adb devices就具有启动进程的作用)
(3) 电脑和手机之间文件相互复制:
adb push 电脑路径/文件名手机文件路径 pc ――>模拟器
adb pull 手机文件路径/文件名电脑文件路径模拟器――> pc
(4) 安装、卸载apk程序
adb install -r 文件路径
(-r 表示强制安装,会覆盖已安装的app)
adb uninstall 包名
(包名可以在清单文件 Androidmanifest.xml查询)
(文件的路径)包名是作为android间应用区别的唯一标识
四、创建一个新的Android项目
1、Android项目的文件系统:
src java源文件
bin apk(工程运行完后生成)
gen R 不能修改
(系统帮我们完成了数据流的读写,不要手动修改)、
所有资源在R文件中注册用到的系统的图片通过R文件,
直接读取文件,节省了io代码
res 资源文件
-drawable 图片分辨率
ldpi 240x400
mdpi 320x480
hdpi 480x800
xhdpi 1280×720
xxhdpi 1920×1080
- values 字符串、颜色
-layout 布局文件
Androidmanifest.xml 清单文件
布局文件、UI组件
Activity(就是一个显示界面)可以理解为是一个网页
布局文件跟activity的关联
setcontentView(R.layout.xxx)
布局文件:都是xml格式文件
介绍xml格式(清单文件)
节点的开始、属性及属性的内容、节点的结束
子节点
节点: <>成对出现的</>
</>单个出现
1、布局文件:xxx.xml; 控制app显示出来的界面布局。
2、TextView 文本框
<TextView
android:id="@+id/textView1"
(每个组件必备的属性,每个控件的身份标识)
android:layout_width="match_parent" (组件的宽)
android:layout_height="wrap_content" (组件的高)
// 值为match_parent说明组件大小填充容器,
值为wrap_content说明组件大小适
应其内容。fill_parent(早期时候使用,现在不用了,主要涉及到命名规则的问题,觉得这样命名不是很好,就没再用了)与match_parent相同当不建议使用。自定义大小:xxdp
android:textSize="20sp" (文本大小单位sp)
android:textColor="#ff000000"
(#开头,八个16进制数,透明度、红、绿、蓝。)
透明度为ff时(完全不透明)可省略:#000000)
android:text="Large Text" (设置文本内容)
/>
注:id、layout_width、layout_height每个组件都有的,
没有宽高的话组件就会出错,
没有id的话要掉用组件的时候就找不到对象。
Button 按钮
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
4、EditText 编辑框
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10" > (组件的宽度)
一开始编辑框没有内容,要是没有给个默认的高度的话,
控件就无法显示了,所以我们在输入数据之前,给编辑框一个默认的宽度
Button button = (Button) findViewById(R.id.btn_queding);
mEditText = (EditText) findViewById(R.id.et_shuru);
mTextView = (TextView) findViewById(R.id.tv_xianshi);
//设置按钮的点击事件
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//获取文本
String str = mEditText.getText().toString();
//设置文本
mTextView.setText(str);
}
});
注意:android里面成员变量需要m开头
设置按钮的监听器对象
new OnClickListener()
设置按钮的点击事件
OnClickListener 接口,后面不需要用到这个类,
就不需要有名类,设置成匿名内部类即可
button.setonclickListener()
editText.getText();出错;解决方法:
(换句话说是非final变量和内部类的生命周期不一样!
方法被调用后,非final变量也会随之消失,这样就会出现内部类引用非法!)
设置成成员变量;小写字母m开头的
或是将变量设置成final类;
小技巧:
Ctrl + T 查看类结构
Ctrl + 1 系统自动生成解决方案
Ctrl + F11 运行项目
Alt + / 自动联想
==============================================================================
类的加载顺序:
成员变量--->构造方法--->普通方法
(查找控件这个方法要在setContentView(R.layout.xxx)之后)
打日志:
Logcat
作用:调试
1、Log.v("MainActivity+ll",""+m);
调试颜色是黑色的,任何信息都会输出
2、Log.d("MainActivity+ll", ""+m);
调试颜色是蓝色的,输出调试信息
3、Log.i("MainActivity+ll", ""+m);
调试颜色是绿色的,输出一般性的提示信息
4、Log.w("MainActivity+ll", ""+m);
调试颜色是橙色的,warning警告的意思
提示我们代码需要优化
5、Log.e("MainActivity+ll", ""+m);
调试颜色是红色的,error错误的意思
Assert 断言单元测试
ImageView
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="42dp"
//图片(前景图片)
android:src="@drawable/ic_launcher"
//设置图片的拉伸模式
android:scaleType="center"
center:居中不放大
fitXY :按照控件的宽高缩放
fitStart:从左侧开始按照图片的宽高比例进行缩放
//设置背景(所有控件都有这个属性)
可以是颜色,也可以是图片
android:background="#00ff00"
/>
res文件下资源文件的命名规则
(小写字母)a~z 0~9_ 不能以数字开头
在代码中去改变ImageView属性的方法
设置前景图片
mImageView.setImageResource(R.drawable.xxx);
设置背景图片
mImageView.setBackgroundResource(R.drawable.xxx);
ImageButton继承ImageView
布局
1、LinearLayout线性布局
android:orientation=""设置控件的排列方式
horizontal水平
vertical 垂直
android:layout_weight="1"权重
数值一样的话,实现一个平分容器的效果
android:layout_gravity 控件在布局中的对齐方式
控件的通用属性:
内容与控件的间隙:
android:padding=“xxdp”(四边)
paddingLeft (左)
paddingRight (右)
paddingTop (上)
paddingBottom(下)
控件之间的间隙:
android:layout_margin=“xxdp” (四边)
layout_marginLeft
layout_marginRight
layout_marginTop
layout_marginBottom
内容在控件中的对齐方式:
android:gravity=""(上下左右居中)
注意:跟android:layout_gravity=“”进行区分
2、RelativeLayout相对布局
控件在布局中的对齐方式
android:layout_alignParentLeft="true"(左)
android:layout_alignParentTop="true" (上)
android:layout_alignParentBottom="true"(下)
android:layout_alignParentRight="true"(右)
android:layout_centerHorizontal="true"(水平居中)
android:layout_centerVertical="true" (垂直居中)
android:layout_centerInParent="true" (居中)
控件之间的对齐方式
android:layout_alignLeft="@+id/textView1"
//传入控件id @+id/xxxx
android:layout_alignRight="@+id/xiaoming"
android:layout_alignTop="@+id/xiaoming"
android:layout_alignBottom="@+id/xiaoming"
控件之间的位置关系
android:layout_below="@+id/xiaoming"
//传入控件id @+id/xxxx
android:layout_toRightOf="@+id/xiaoming"
android:layout_toLeftOf="@+id/xiaoming"
android:layout_above="@+id/xiaoming"
3、FrameLayout 帧布局
特性:层叠控件
4、TableLayout 表格布局
每一行都是一个TableRow
每一行的高度是由该tableRow里面最高的控件决定
5、AbsoluteLayout绝对布局
(不建议使用)
Activity
四大组件之一
activty的创建三要素:
1、创建的类要继承Activity
2、setContentView()引用一个布局文件
3、在清单文件里面进行配置
android:name="com.example.ex_0122_01_activity.MainActivity"
(包名.类名)
Activity跳转
1、A--->B
调用startActivity(intent);
第一个界面:
一般是在点击事件里:
//获取一个意图对象
Intentintent = new Intent();
//设置要开启的activity
intent.setClass(MainActivity.this,SecondActivity.class);
//设置要传递的消息
(消息是键值对的形式传递)
key:必须是字符串
values:基本数据类型,以及实现了序列化接口的对象
intent.putExtra("key1","呵呵");
intent.putExtra("key2",true);
//开启一个新的activity
startActivity(intent);
第二个界面:
//获取第一个界面传过来的意图对象
Intent intent =getIntent();
//通过key把意图对象里的信息获取到
intent.getStringExtra("key1");
2、A--->B--->A
第一个界面:
Intentintent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
intent.putExtra("key1","呵呵");
intent.putExtra("key2",true);
//开启一个新的界面,并等待返回消息
startActivityForResult(intent,0);
第二个界面:
Intentdata = new Intent();
data.putExtra("key3","对方已不是你好友");
//返回一个消息到第一个界面
setResult(0,data );
//关闭当前界面
finish();
第一个界面:
接收第二个界面返回的消息
重写onActivityResult()这个方法
@Override
protectedvoid onActivityResult(int requestCode, \
intresultCode, Intent data) {
super.onActivityResult(requestCode,resultCode, data);
Stringstr = data.getStringExtra("key3");
mTextView.setText(str);
}
魔鬼数字:引用参数的类型为数值的时候,一般不直接赋值
而是去设置常量,设置成常量之后再引用
也可以去创建一个接口,专门用来存放我们的常量
请求码:
A有两个按钮,都是跳转到B,B界面处理完返回消息
就用请求码来区分是哪一个按钮请求到B界面返回的结果
startActivityForResult(intent , 请求码);
结果码:
B有两个按钮,都是跳回A,在A就是通过结果来进行判断,
返回不同的处理时间
setResult(结果码, intent);
onActivityResult()
Activity的生命周期
生命周期:一个对象从创建到销毁中间经历的状态
创建--->运行 oncreate onstart onresume
可见可操作
运行--->销毁 onpause onstop ondestory
运行--->暂停(可见不可操作)
onpause
暂停--->恢复 onresume
运行--->停止(不可见不可操作)
onpause onstop
停止--->恢复
onreStart onstart onresume
当activity处于暂停或是停止状态,更高优先级的应用需要
内存时,activity可能会终止
数据持久化
内存:关闭界面、断电掉数据
外存:断电不掉数据
U盘硬盘 sdcard
权限
/mnt/sdcard/
onstop:去保存数据--->sdcard
onstart:去从sdcard读取数据,把数据显示到界面上
Service服务
四大组件之一,它一直运行在后台,没有界面
创建Service的要素
1、继承Service
2、清单文件配置
android:name="com.example.ex_0124_02_service.MyService"
(包名.类名)
启动service的方法
1、在Activity里面调用startService(service);
oncreate onstartCommand
注意:第一次启动服务时,会调用oncreate onstartCommand
服务没有结束之前,多次点击启动服务,
只会调用onstartCommand
启动服务:activity跟service关系松散
关闭服务:stopService(service)
绑定服务
绑定的方法:
1、bindService(service, conn , Context.BIND_AUTO_CREATE);
参数:第一个:Intent对象
第二个:serviceConne对象
(声明成成员变量)
第三个:Context.BIND_AUTO_CREATE
(当我们绑定服务时,如果服务不存在,会自动启动)
调用oncreate onBind
解除绑定:
在Activity内调用unBindService(conn)
调用onUnBind onDestory
注意:绑定跟解绑调用的参数conn,必须是同一个对象所以要声明为成员变量
ServiceConnectionconn = new ServiceConnection() {
@Override
publicvoid onServiceDisconnected(ComponentName name) {
//TODO Auto-generated method stub
//服务异常终止会调用这个方法
Log.e("MainActivity","onServiceDisconnected");
}
@Override
publicvoid onServiceConnected(ComponentName name, IBinder service) {
//TODO Auto-generated method stub
//onBind()返回一个非空的IBinder类型的对象时,才会被调用
Log.e("MainActivity","onServiceConnected");
}
};
注:在serveice里onBind方法内必须返回一个参数,否则会抛出异常
public IBinder onBind(Intent intent)
{
Log.e("MyService", "onBind()");
Throw xxxxxxxx//它是提示我们编程人员,绑定了服务,就必须实现这个接口,就必须有返回值,否则就会出错
return binder; //返回一个IBinder对象,没有则返回空值
}
注意:
service的生命周期不是完全跟activity的生命周期绑在
一起的,如果通过startService()开启服务之后,再去
绑定服务,当我们关闭activity之后,服务不会被关闭,
只会解除绑定
Activity通过绑定的方式调用service中方法的步骤
步骤:
1、在service里面去声明一个Mybinder,继承Binder
(Binder实现了IBinder)
2、在类Mybinder创建方法调用Service里面的方法
3、创建Mybinder类型的对象
4、在onBinder(),返回Mybinder对象(自动转型)
5、在activity的onServiceConnected()方法中,
去获取Ibinder类型的对象,然后把它强转成Mybinder
类型的对象,就可以使用这个对象里面的方法了
注:onServiceConnected能够被执行的条件:
service的onBind返回一个非空的对象
BroadcastReceiver 广播接收者
四大组件之一
特性:群发单向
广播:android里面应用之间传输信息的机制
广播接收者创建的三要素:
1、创建的类要去继承BroadcastReceiver
2、重写onReceive()
3、在清单文件设置
android:name="com.example.ex_00_example.MyReceiver"
(包名.类名)
场景:1)系统接受某个事件。会群发广播消息
2)应用自己发广播
1、接收广播:接收短信
1、创建广播
2、在清单文件配置
权限:
<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
3、在清单文件配置:
<intent-filter>
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
2、应用自己发广播
Intentintent = new Intent();
//设置广播的过滤条件
intent.setAction("www.xinbo.com");
intent.putExtra("listen","listen one");
//发送广播
sendBroadcast(intent );
发送广播:跨进程通讯。
注意:接发广播的应用包名不能一样
(改包名:在配置清单之内改)
在代码中注册广播:
1)MyReceiver receiver = new MyReceiver();
2)在onStart()方法注册:
IntentFilter filter = new IntentFilter();
filter.addAction("85.5MHZ");
3)注册广播接收者
registerReceiver(myReceiver, filter );
4)在onStop()注销广播
unregisterReceiver(receiver);
两种广播的区别:
1)清单进程不存在,只要有广播,就会触发
2)code 灵活控制时机
intent:
显式意图:对于明确了目标组件的意图
开启的对象,必须在同一个应用里面
隐式意图:对于没有明确指出目标组件的意图
只要条件匹配,就可以开启
也能够跨应用开启
当startActivity(intent )启动一个activity界面时,它会默认发出
category---->android.intent.category.DEFAULT
也能够通过隐式意图去开启另一个应用的服务
直接通过隐式意图去启动service
中级部分
通知系统:
1、Toast:一般是在屏幕下方的黑方框,显示一段时间后会消失
Toast.makeText(MainActivity.this, "下载完成",Toast.LENGTH_LONG).show()
Toast.LENGTH_LONG
Toast.LENGTH_SHORT
特性:Toast不会获取焦点,提示消息过了一段时间会自动消失
应用场景:
不需要用户去点击确认,也不需要用户去反馈
在应用的其他界面依然能够看到Toast提示
2、Notifycation是显示在手机状态栏的通知,具有全局效果
作用:
来消息时,在通知栏显示,当用户点击之后,可以打开查看详细信息
使用场景:
未读短信
未接电话
广告
升级过程
下载
步骤:
1、调用getSystemService(Context.NOTIFICATION_SERVICE)方法获取系统的NotificationManager(消息管理器)
在oncreat()方法里面写:
NotificationManager notifyMgr = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
3、创建一个Notification对象:(一般在点击事件里面。)
Notification notification = new Notification(R.drawable.ic_launcher,
"未读短信",System.currentTimeMillis());
参数:第一个:图片
第二个:文本
第三个:显示时间。
4、设置标题和内容
notification.setLatestEventInfo(this, "小丽","呵呵",
contentIntent );
5、点击事件关联的Activity (新建一个Activity)
Intent intent = new Intent(this, SecondActivity.class);
PendingIntent contentIntent = PendingIntent.
getActivity(this, 0, intent , 0);
2、用NotificationManager发送Notification;
mNotificationManager.notify(1, notification );
6、设置不能消除:
通知:
正在运行时不能被清除
notification.flags = Notification.FLAG_ONGOING_EVENT;
点击后消失:
Notification.flags = Notification.FLAG_AUTO_CANCEL;
Dialog对话框
实现两种方法:
方法一:
1、创建AlertDialog.Builder对象
AlertDialog.Builderbuilder = new AlertDialog.Builder(MainActivity.this);
2、设置标题跟内容
builder.setTitle("对话框");
builder.setMessage("删除好友");
builder.setPositiveButton("确定", newDialogInterface.OnClickListener() {
@Override
publicvoid onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"确定删除", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", newDialogInterface.OnClickListener() {
@Override
publicvoid onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"取消删除", Toast.LENGTH_SHORT).show();
}
});
builder.setNeutralButton("帮助", newDialogInterface.OnClickListener() {
@Override
publicvoid onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"给个意见", Toast.LENGTH_SHORT).show();
}
});
3、通过AlertDialog.Builder对象创建AlertDialog对象
.show()
方法二:
1、执行showDialog(1)方法
2、重写onCreateDialog(intid)方法
菜单Menu
optionMenu选项菜单
场景:一些不常用但用必要的功能
第一种方法:
code:
1)重写onCreateOptionsMenu()
menu.add(0,1, 0, "确定").setIcon(R.drawable.ic_launcher);
menu.add(0,2, 0, "取消").setIcon(R.drawable.ic_launcher);
menu.add(0,3, 0, "帮助").setIcon(R.drawable.ic_launcher);
menu.add(0,4, 0, "设置").setIcon(R.drawable.ic_launcher);
menu.add(0,5, 0, "设置").setIcon(R.drawable.ic_launcher);
menu.add(0,6, 0, "设置").setIcon(R.drawable.ic_launcher);
menu.add(0,7, 0, "设置").setIcon(R.drawable.ic_launcher);
2)菜单项的点击事件
重写onOptionsItemSelected()方法
通过item.getItemId()来进行区分
当选项超过6个后,会以列表形式显示出来
列表显示出来的选项,不显示图片
第二种方法:
xml:创建menu文件夹
publicboolean onCreateOptionsMenu(Menu menu) {
MenuInflatermenuInflater = getMenuInflater();
menuInflater.inflate(R.menu.item_menu,menu);
returntrue;
}
ContextMenu上下文菜单
1、给控件注册上下文菜单
registerForContextMenu(mTextView1);
2、重写onCreateContextMenu方法
添加菜单选项
public void onCreateContextMenu(ContextMenumenu, View v,
ContextMenuInfomenuInfo) {
Log.e("MainActivity","ContextMenu");
switch(v.getId()) {
caseR.id.textView1:
menu.add(0,1, 0, "确定");
menu.add(0,2, 0, "取消");
break;
caseR.id.textView2:
menu.add(0,3, 0, "复制");
menu.add(0,4, 0, "剪切");
break;
default:
break;
}
super.onCreateContextMenu(menu,v, menuInfo);
}
3、重写onContextItemSelected方法
实现点击事件
@Override
publicboolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case1:
mTextView1.setText("确定");
break;
case2:
mTextView1.setText("取消");
break;
case3:
mTextView2.setText("复制");
break;
case4:
mTextView2.setText("剪切");
break;
default:
break;
}
returnsuper.onContextItemSelected(item);
}
选项菜单跟上下文菜单的区别
1、触发方式不一样:
optionMenu:点击menu F2
ContextMenu:长按控件(隐蔽)
2、显示方式:
optionMenu:界面底部弹出
ContextMenu:界面中间弹出
3、作用范围:
optionMenu:activity
ContextMenu:view(已经注册了上下文菜单的控件)
4、调用时的创建方法以及次数不一样:
optionMenu:创建的时候只调用一次onCreateOptionsMenu
ContextMenu:每次弹出的时候,都会调用onCreateContextMenu
UI控件
checkBox:多选框
场景:获取一些用户不需要填写的信息(兴趣爱好)
属性:
xml中 :android:checked="true"//设置默认是否选中
code中 :Check对象.setChecked(true);//设置默认是否选中
Check对象.isChecked();//判断是否选中
代码例子:
privatevoid btn_01() {
CheckBoxcheckBox01 = (CheckBox) findViewById(R.id.checkBox1);
CheckBoxcheckBox02 = (CheckBox) findViewById(R.id.checkBox2);
CheckBoxcheckBox03 = (CheckBox) findViewById(R.id.checkBox3);
StringBufferbuffer = new StringBuffer();
if(checkBox01.isChecked()){
Stringstr = checkBox01.getText().toString();
buffer.append(str+"、");
}
if(checkBox02.isChecked()){
Stringstr = checkBox02.getText().toString();
buffer.append(str+"、");
}
if(checkBox03.isChecked()){
Stringstr = checkBox03.getText().toString();
buffer.append(str+"、");
}
Stringstring = buffer.toString();
Stringsubstring = string.substring(0, string.length()-1);
mTextView.setText(substring);
}
radioGroup:单选框
如果想要实现单选的话,radioButton必须放在radioGroup里面
xml属性:
设置radioGroup里radioButton的排列方向
android:orientation="horizontal"
code:
RadioGroupradioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
//查找被选中的radioButton的id
intid = radioGroup.getCheckedRadioButtonId();
//通过id去找到所对应的radioButton控件对象
RadioButtonradioButton = (RadioButton) findViewById(id);
mTextView.setText(radioButton.getText().toString());
ProgressBar进度条
水平进度条
xml:
android:max="200" //总进度
android:progress="100" //当前进度
android:secondaryProgress="150" //第二进度
code:
progressBar.setMax(10);
progressBar.setProgress(2);
progressBar.setSecondaryProgress(8);
圆形进度条(无进度的进度条)
控件的通用属性:
android:visibility="visible"
值:visible 可见
nvisible 不可见但占位置
gone 不可见也不占用空间
//代码中设置控件的可见性
mProgressBar02.setVisibility(View.INVISIBLE);
SeekBar可拖拽的进度条
seekBar.setOnSeekBarChangeListener(newOnSeekBarChangeListener() {
@Override
publicvoid onStopTrackingTouch(SeekBar seekBar) {
Log.e("MainActivity","onStopTrackingTouch");
}
@Override
publicvoid onStartTrackingTouch(SeekBar seekBar) {
Log.e("MainActivity","onStartTrackingTouch");
}
@Override
publicvoid onProgressChanged(SeekBar seekBar, int progress,
booleanfromUser) {
Log.e("MainActivity","onProgressChanged");
//当进度发生改变的时候就被调用
}
});
RatingBar
xml:
android:numStars="4"
android:rating="1.5"
code:
RatingBar ratingBar =(RatingBar) findViewById(R.id.ratingBar1);
ratingBar.setOnRatingBarChangeListener(newOnRatingBarChangeListener() {
@Override
publicvoid onRatingChanged(RatingBar ratingBar, float rating,
booleanfromUser) {
Log.e("MainActivity","onRatingChanged--->"+rating);
}
});
时间跟日期的控件
TimePicker&DatePicker
StringBufferbuffer = new StringBuffer();
inthour = mTimePicker.getCurrentHour();
intminute = mTimePicker.getCurrentMinute();
intyear = mDatePicker.getYear();
intmonth = mDatePicker.getMonth();
intday = mDatePicker.getDayOfMonth();
buffer.append(year+"/"+(month+1)+"/"+day+" "+hour+":"+minute);
mTextView.setText(buffer.toString());
注意点:month是0~11
对于时间跟日期的选择,一般都是以对话框的形式显示出来
TimePickerDialog:
//获取日历对象
Calendarcalendar = Calendar.getInstance();
TimePickerDialogtimePickerDialog = new TimePickerDialog(
MainActivity.this,new OnTimeSetListener() {
@Override
publicvoid onTimeSet(TimePicker view, int hourOfDay,
intminute) {
StringBufferbuffer = new StringBuffer();
buffer.append(hourOfDay+ ":" + minute);
mTime.setText(buffer.toString());
}
},calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),true);
//显示
timePickerDialog.show();
DatePickerDialog:
//获取日历对象
Calendarcalendar = Calendar.getInstance();
DatePickerDialogdatePickerDialog = new DatePickerDialog(
MainActivity.this,new OnDateSetListener() {
@Override
publicvoid onDateSet(DatePicker view, int year,
intmonthOfYear, int dayOfMonth) {
StringBufferbuffer = new StringBuffer();
buffer.append(year+"/"+(monthOfYear+1)+"/"+dayOfMonth);
mDate.setText(buffer.toString());
}
},calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
datePickerDialog.show();
1、常见异常类型
1、NullPointException空指针异常
对象.方法 .之前的那个对象
2、ClassNotFoundException 指定的类不存在
ActivityNotFoundException activity不存在
检查清单文件:类名是否声明一致过滤条件是否一致
3、ArrayIndexOutOfBoundsException 数组下标越界
StringIndexOutOfBoundsException 字符串索引越界
4、ArithMeticException 算术异常
除数为0
5、ClassCastException 类转换异常
常见:修改布局,拖动了布局,容易出现
方法:project--->clean
6、IllegalStateException
非法状态异常调了两次
IllegalArgumentException
非法参数异常参数调用出错
========================================================
listView:以列表的形式去显示内容,结构相似
功能:批量展示数据,以垂直列表形式显示信息
普通控件:内容跟控件在同一个对象里面
组合控件:内容跟控件不在同一个对象里面
原理:
listview Apapter(适配器)
框跟行的分隔行布局
所有行内容
注意点:
listview的高度必须是match,不能是wrap_parent
步骤:
1、在activity的布局文件里面,创建一个listview控件
2、创建一个行布局文件
3、在activity里面找到这个listview控件对象
4、初始化数据
5、创建适配器对象
6、通过listview设置适配器
listView.setAdapter(adapter)
@Override
publicView getView(int position, View convertView, ViewGroup parent) {
//得到布局转换器
LayoutInflaterlayoutInflater = getLayoutInflater();
//把布局xml文件转换成布局对象
Viewinflate = layoutInflater.inflate(R.layout.item_list, null);
//查找该行布局上的控件对象
ImageViewimageView = (ImageView) inflate
.findViewById(R.id.imageView1);
TextView textView1 =(TextView) inflate
.findViewById(R.id.textView1);
TextViewtextView2 = (TextView) inflate
.findViewById(R.id.textView2);
//查找当前行对应的消息内容
Stringtit = title.get(position);
Stringsub_tit = sub_Title.get(position);
imageView.setImageResource(imageList[position]);
textView1.setText(tit);
textView2.setText(sub_tit);
//把设置完成的行布局对象显示出来
returninflate;
}
//决定lisview的行数
@Override
publicint getCount() {
//TODO Auto-generated method stub
returnimageList.length;
}
listView的优化技巧
1、复用行布局对象convertView
用convertView去替代即将出现的控件对象
Viewinflate = null;
if(convertView==null){
LayoutInflaterlayoutInflater = getLayoutInflater();
inflate= layoutInflater.inflate(R.layout.item_list, null);
}else{
inflate= convertView;
}
2、减少控件的查找次数
1)、创建一个类。属性就是我们所需要的控件类型
2)、getview()方法里创建类的对象
Viewinflate = null;
ViewHolderholder = null;//声明一个Viewholder对象
if(convertView==null){
//得到布局转换器
LayoutInflaterlayoutInflater = getLayoutInflater();
//把布局xml文件转换成布局对象
inflate= layoutInflater.inflate(R.layout.item_list, null);
holder= new ViewHolder();//创建一个Viewholder对象
//找到控件对象,然后保存到holder对象里面去
holder.imageView= (ImageView) inflate
.findViewById(R.id.imageView1);
holder.textView1= (TextView) inflate
.findViewById(R.id.textView1);
holder.textView2= (TextView) inflate
.findViewById(R.id.textView2);
//把ViewHolder对象放到inflate“包”里
inflate.setTag(holder);
}else{
inflate= convertView;//得到inflate对象
//从inflate对象的“包”里面拿到Viewholder对象
holder= (ViewHolder) inflate.getTag();
}
数据的封装
一行有多个数据,把数据封装到一个对象里面
便于数据的管理以及操作
步骤:
1、创建一个类。属性就是我们需要的数据类型
2、new出对象,把数据传入
3、把创建的对象存放到一个容器中
4、在getView方法中,通过容器得到相应行的数据对象
5、设置控件内容