1、一般在启动虚拟机的时候可以通过cmd中的命令来启动对应的虚拟机并加载sdcard虚拟镜像。但是在eclipse中的对某个具体的project可以在它的run configurations中的target标签中,设置application additional command中的额外的命令选项,在这里加上对应的sdcard的启动命令 : -sdcard F:\Android\mySmallSDcard ,那么以后在通过eclipse启动模拟器时,就会自动加载sdcard虚拟镜像。
2、对于UI的微调可以通过 windows自带的 画图程序 来修改 ,可以对某个区域的颜色进行复制黏贴。从UI设计的角度来看,图片的渐变色增加了立体感,而图片和背景色本身的重叠能够消除图片中的不好看的颜色。
3、在eclipse中的source标签中,shift left和shift right对于整体移动代码块非常方便。通过使用Android中layout文件的可视化视图能够大概的看到layout文件的效果,但是与实际的效果还是有差距的。
4、为了能够实现在多个用标签表示的程序之间随意跳转的功能,其实比较方便的一种方法就是:在调用startActivity(..)从一个Intent跳转到另一个Intent后,调用finish()结束跳转前的Intent.
5、Android UI设计中的布局
(1)FrameLayout :最简单的布局模型,在这种布局下每个添加的子控件都被放在布局的左上角,并覆盖在前一子控件的上层。另外需要注意的是:当使用ImageView显示图片时,应当使用android:src指定显示的图片,而不是使用android:background,否则和内容相关的操作将不起作用。
(2)RelativeLayout:子控件会根据它们所设置的参照控件和参数进行相对布局。参照控件可以是父控件,也可以是其他子控件,但被参照的控件必须要在它之前定义。相对布局模型涉及到的属性设置比较多。
-- 将父控件作为参照控件的属性,例如:android:layout_centerInParent="true",将当前控件放置于父控件的横向和纵向的中央部分。这样的属性只能设置为boolean类型的值,true或false。
-- 将其他控件作为参照控件的属性,例如:android:layout_below="@id/aclock",将当前控件放置于id引用名为aclock的下方,其值必须是一个id的引用名。
-- 以尺寸值作为属性值,例如:android:layout_marginLeft="40px"
(3)LinearLayout:是最常用的一种布局方式,提供了控件水平或者垂直排列的模型,同时可以设置子控件的weight布局参数控制各个子控件在布局中的相对大小。
常用的一些属性有:android:layout_weight 宽度
android:layout_height 高度
android:orientation 排列方式
android:gravity 对齐方式:如果无子控件的View设置这个属性,表示其内容的重力倾向,即对齐方式;若是有子控件的View,则设置的是其子控件的对齐方式。多个gravity的值可以通过“|”来组合使用。
6、菜单和对话框
(1)菜单:Android平台所提供的菜单大致可分为三类:选项菜单(Options Menu),上下文菜单(Context Menu),子菜单(Submenu)。
--1、选项菜单:可以在底部弹出带图标的选项菜单,最多只能显示6个菜单项,但设置了6个以上的菜单项后,就只能显示5个菜单项,最后一个菜单项就变成了“更多”字样,而点击“更多
”,就会弹出扩展选项菜单,扩展菜单选项不支持图标,但可以有单选框和复选框。
第一次调用选项菜单时,Activity会调用onCreateOptionsMenu(),需要重新实现override,并在里面初始化选项菜单就可以了。
如:
/*
* Options Menu
*/
private final int MENU_START = Menu.FIRST;
private final int MENU_STOP = Menu.FIRST+1;
private boolean startOrStop = true ;
@Override
public boolean onCreateOptionsMenu(Menu menu){
menu.add(0, MENU_START, 0, "录音").setIcon(android.R.drawable.ic_media_play);
menu.add(0, MENU_STOP, 1, "停止").setIcon(android.R.drawable.ic_media_pause).setEnabled(false);
return true;
}
需要注意的是:菜单项的Id必须是唯一的,为的是事件侦听。
MenuItem可选的设置有:单选框或复选框、快捷键、短标题、图标、监听菜单项单击事件(onMenuItemClickListener),设置Intent。
除了上面的提到的给菜单项设置单击事件侦听,也可以重新实现onOptionsItemSelected。
如:
@Override
public boolean onOptionsItemSelected(MenuItem item){
super.onOptionsItemSelected(item);
switch(item.getItemId()){
case MENU_START:
/*
* Do some thing
*/
startOrStop = false ;
break;
case MENU_STOP:
/*
* Do some thing
*/
startOrStop = true ;
break;
default:
break;
}
return false ;
}
在第一次初始化了选项菜单后,如果需要动态更改菜单选项的话,就可以重新实现onPrepareOptionsMenu(),它会在每次显示选项菜单之前调用。可以在这个函数中根据程序的运行情况即时
地更新菜单项的内容,如标题,是否可用等等。
如:
@Override
public boolean onPrepareOptionsMenu(Menu menu){
super.onPrepareOptionsMenu(menu);
MenuItem item1 = menu.findItem(MENU_START);
MenuItem item2 = menu.findItem(MENU_STOP);
if( startOrStop == true ){
item1.setEnabled(true);
item2.setEnabled(false);
}
else{
item1.setEnabled(false);
item2.setEnabled(true);
}
return true ;
}
7、经常遇到且很有用的几个类及其介绍
--java.lang.Runnable
Represents a command that can be executed. Often used to run code in a different Thread.
表示可以被执行的一条命令,通常在另外一个不同的线程中执行代码。主要覆盖public void run()函数。
--android.os.Message
Defines a message containing a description and arbitrary data object that can be sent to a Handler.
This object contains two extra int fields and an extra object field that allow you to not do allocations in many cases.
While the constructor of Message is public, the best way to get one of these is to call Message.obtain() or one of the Handler.obtainMessage() methods,
which will pull them from a pool of recycled objects.
定义了一个Message,它包含了一个描述和任意数据对象,可以被发送给某个Handler。这个对象包含了两个额外的int域和一个额外的对象域,在很多情况下避免了空间分配。
虽然Message的构造函数是公共的,但是最好的方法是通过Message.obtain()或Handler.obtainMessage()中的某一个来得到,系统会从一个回收的对象池中拉一个对象出来。
Message.what : User-defined message code so that the recipient can identify what this message is about.
Message.obj : An arbitrary object to send to the recipient. When using Messenger to send the message across processes this can only be non-null if it
contains a Parcelable of a framework class (not one implemented by the application).
--android.os.Handler
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single
thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the
thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed
on a different thread than your own.
Handler用于给相关联的某个线程的MessageQueue发送Message和处理Runnable对象。每个Handler对象实例只和单个线程和它的消息队列相关。当创建一个新的Handler,它就和创建创建
它的线程/线程的消息队列绑定,从这一刻起,Handler就会向这个消息队列发送消息和runnables对象,并且当消息从队列中出来时执行它们。
boolean android.os.Handler.sendMessage(Message msg) : Pushes a message onto the end of the message queue after all pending messages before the current time. It will be received in handleMessage(Message), in the thread attached to this handler.
boolean android.os.Handler.postDelayed(Runnable r, long delayMillis) : Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.
--android.os.Looper
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread
that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
用于为一个线程运行message loop。线程默认是没有message loop的,要创建时,可以在将要运行loop的线程中调用prepare(),然后调用loop()让这个线程处理这些消息直到loop停止。
和message loop的大多数交互是通过Handler类进行的。
MessageQueue android.os.Looper.myQueue() : 返回和当前线程相关的MessageQueue对象。
void android.os.MessageQueue.addIdleHandler(IdleHandler handler) : 添加MessageQueue的IdleHandler。
--android.os.MessageQueue.IdleHandler
Callback interface for discovering when a thread is going to block waiting for more messages.
发现一个线程什么时候将要阻塞以等待更多的消息的回调接口。
--android.widget.PopupWindow
void android.widget.PopupWindow.showAtLocation(View parent, int gravity, int x, int y) : 在某个具体的位置显示PopupWindow对象
void android.widget.PopupWindow.update(int x, int y, int width, int height) : 将PopupWindow对象显示在指定位置
void android.widget.PopupWindow.dismiss() : 抛弃PopupWindow对象。
--SeekBar控件在布局文件中的主要的属性有:
android:progressDrawable 进度条的背景图片和进度条(一般采用@drawable/xxx.xml布局文件,并使用layer-list一次加载多个层次图片)
android:thumb 进度条中的小球(一般采用@drawable/xxx.xml布局文件,并使用selector根据控件属性变化,加载不同的图片)
android:progress 进度条当前的进度
android:secondaryProgress 二级进度条
SeekBar主要的侦听事件:SeekBar.onSeekBarChangeListener,侦听包括手动滑动滑钮,程序执行等情况下的progress变化。
<LinearLayout android:layout_width="500px"
android:layout_height="51px"
android:layout_above="@id/video_line"
>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="50px"
android:gravity="center_horizontal"
android:layout_alignParentBottom="true">
<LinearLayout android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="@drawable/mm_background"
android:orientation="horizontal">
上面的四个层次的LinearLayout都不是多余的,layout_above指定相对位置 ,gravity="bottom"指定整体靠底部 gravity="center_horizontal"指定整体水平居中
orientation="horizontal"指定对平排列
8、调试过程中遇到的小错误提示:
1、findViewById()时要注意写明针对的是哪一个view,如果不指定,默认是在当前view下面的,发生错误时会出现NullPointerException,没有找到对应的控件id。
2、实际应用程序的测试需要到真机上实现,模拟器在测试的时候有些功能是看不到的,或者说在模拟器上正确的在真机上就不一定正确,反之亦然。
3、在Android UI设计中需要注意的是一般都要把图标放在draw-hdpi的文件夹下,否则在大小显示的时候会有问题。