但经我查阅书籍和实践之后发现,xml是一个布局文件,java是一个代码文件,两者之间的联系并非如.NET中那么简单的用文件关联吧!
页面中的控件都存放在布局控件中,与winPhone类似。Android的布局分线性布局(LinearLayout),绝对布局(AbsoluteLayout),网格布局(TableLayout)
在本例中使用了线性布局,所有控件都以水平或垂直排列,通过orientation属性设置,发现在xml文件中,所有android的属性都以 android:ProptoryName的形式,例如android:orientation,水平则是horizontal;垂直是vertical。
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="none"
android:textSize="20dip"
android:gravity="right"
android:id="@+id/brewcontent_label"/>
上面则是一个Labe的声明,控件长和宽是layout_height和layout_width,有两个选项fill_parent(占满父容器)和wrap_content(适应内容),控件的id则是以@+id/brewcontent_label,这个用到内部资源,brewcontent_label是控件的id,id要符合标识符的规则。在java文件中获取界面上的控件时,并不能如在.NET中那么方便,需要另外声明相应的变量,然后在onCreate方法中对其赋值,且要通过以下的形式
txtTime=(TextView)findViewById(R.id.brew_time);
在本例中的代码如下所示
Button btnAdd,btnDes;
TextView txtTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnAdd=(Button) findViewById(R.id.brew_time_up);
btnDes=(Button) findViewById(R.id.brew_time_down);
txtTime=(TextView)findViewById(R.id.brew_time);
}
由于在.NET中缺少winPhone的开发经验,但是与ASP.NET类比的话,onCreate方法就类似于与Page_Load事件绑定的方法。
点击事件
当要给控件添加事件,也并非如在.NET下那么方便(在可视化界面中双击控件,或者对事件绑定方法),但是在Java中没有委托这个类型。
例如这里要给按钮的Click事件绑定一个方法,它需要指定的类实现OnClickListener接口,该接口需要实现onClick(View view)方法,传入的参数则是触发的事件的空间。例如
public class MainActivity extends Activity implements OnClickListener{
Button btnAdd,btnDes;
TextView txtTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnAdd=(Button) findViewById(R.id.brew_time_up);
btnDes=(Button) findViewById(R.id.brew_time_down);
txtTime=(TextView)findViewById(R.id.brew_time);
btnAdd.setOnClickListener(this);
btnDes.setOnClickListener(this);
}
@Override
public void onClick(View view) {
//。。。。。
}
}
除了上面这种以本类实现OnClickListener接口,然后去绑定本类实例这种方式外,下面则列举其余两种事件绑定的方式
btnAdd.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View sender) {
AddTxtTime();
}
});
btnDes.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
DesTxtTime();
}});
不过这种直接用接口构造实例的形式,从传参方面是将得通的,但是以接口名来构造实例,在C#中我还没见过,下面的这个方式其实也是按上面这种衍生出来的,换了个表现形式
OnClickListener btnAdd_Onclick,btnDes_Onclick;
btnAdd_Onclick=new OnClickListener(){
@Override
public void onClick(View v) {
AddTxtTime();
}};
btnDes_Onclick=new OnClickListener(){
@Override
public void onClick(View v) {
DesTxtTime();
}};
btnAdd.setOnClickListener(btnAdd_Onclick);
btnDes.setOnClickListener(btnDes_Onclick);
按OnXXXListener命名方式命名的接口除了OnClickListener外,OnFocusChangeListener ,OnKeyListener ,OnLongClickListener ,OnTouchListener。相应的View类也有setOnXXXListener的方法。
上面使用了标签Label和按钮Button,以及简单的Click事件,下面则尝试一下另外的事件
按键事件
这回用到的一个图片控件ImageView,要在如果给控件添加图片,则要把图片放到资源文件夹里面,但是命名规则要注意,只能用小写字母,数字和下划线
设置android:src属性则可,@drawable/加图片的名字(不包含后缀)。如
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/lbHelloworld"
android:src="@drawable/wp_20131103_001" />
这次用到的事件是键盘响应事件,就直接重写onKeyDown方法,同类型的方法还有onKeyUp。方法传入两个参数,int类型的keyCode是按键的编码,KeyEvent类型的msg是按键的信息,虽然keyCode是一个int类型,但是也可以用KeyEvent的枚举作匹对。如下面代码
@Override
public boolean onKeyDown(int keyCode,KeyEvent msg)
{
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_RIGHT:
mAlphavalue += 20;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
mAlphavalue -= 20;
break;
default:
break;
}
if(mAlphavalue>=0xFF)mAlphavalue = 0xFF;
if(mAlphavalue<=0x0)mAlphavalue = 0x0;
mImage.setAlpha(mAlphavalue);
return super.onKeyDown(keyCode,msg);
}
这里的switch语句的用法算是我第一次遇见,至少在C#我也没用过两个标签用同一段处理表达式,default除外。
上面的代码作用则是按了上或者右方向键的,则增加图片的Aplpha值,让图片变得不透明;按下或者左方向键则减少图片的Aplpha值,让图片变得透明。
运动事件
现在就看看运动事件,这里介绍的运动时间是触摸屏的事件,这个事件对winPhone的来说相当于触控事件。它需要给继承Activity的类重写onTouchEvent方法,这个方法原型如下
public boolean onTouchEvent(MotionEvent event)
可以通过getX()和getY()获取触摸的坐标值,通过getAction()获取事件的类型,事件类型有以下几种
- ACTION_DOWN: 表示用户开始触摸.
- ACTION_MOVE: 表示用户在移动(手指或者其他)
- ACTION_UP:表示用户抬起了手指
- ACTION_CANCEL:表示手势被取消了
- ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.
对于Android2.2以后的版本增加的多点触控,还有另一个方法getActionMasked,这个方法能获取到的事件类型会更多,例如
- ACTION_POINTER_DOWN:有一个非主要的手指按下了.
- ACTION_POINTER_UP:一个非主要的手指抬起来了
至于两者区别现在暂时不去了解,以上这些值可以在MotionEvent枚举中获取
下面则是一个示例代码
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action=event.getAction();
float pX=event.getX();
float pY=event.getY();
String actionStr;
switch(action)
{
case MotionEvent.ACTION_DOWN:actionStr="ACTION_DOWN";break;
case MotionEvent.ACTION_MOVE:actionStr="ACTION_MOVE";break;
case MotionEvent.ACTION_UP:actionStr="ACTION_UP";break;
case MotionEvent.ACTION_CANCEL:actionStr="ACTION_CANCEL";break;
case MotionEvent.ACTION_OUTSIDE:actionStr="ACTION_OUTSIDE";break;
default:actionStr="";break;
}
this.lbaction.setText("Acton="+actionStr);
this.lbPosition.setText("Position=("+pX+","+pY+")");
return super.onTouchEvent(event);
}
对于运动事件还有滚动球事件,它的声明如下
public boolean onTrackballEvent(MotionEvent event)
与触摸事件的方法一样传入MotionEvent类型的参数,不过滚动球这种设备最近也很少看见了,现在也不作尝试了。
重绘事件
之前在.NET经常利用GDI+对界面进行重绘,定义控件的时候就重写OnPaint方法,如果在使用控件的话就绑定Paint事件,在java Android方面则重写onDraw方法,但这个方法在Acitvity类中,要另外定义一个继承与View的类,相当于定义一个控件,不过现在还不清楚Android各个类之间的实际意义,还不好乱下定论,不过在C#中,窗体,页面两个类都会是控件类的子类。
在本例中也使用了触控事件,但重点在于onDraw方法的重写
1 public class Page2 extends View {
2
3
4 Paint curPaint;
5 float pX,pY;
6 int action;
7
8 public Page2(Context context) {
9 super(context);
10 // TODO Auto-generated constructor stub
11
12 curPaint=new Paint();
13 pX=pY=0;
14 }
15
16 @Override
17 protected void onDraw(Canvas canvas)
18 {
19 switch(action)
20 {
21 case MotionEvent.ACTION_DOWN:
22 curPaint.setColor(Color.BLUE);break;
23 case MotionEvent.ACTION_MOVE:
24 curPaint.setColor(Color.RED);break;
25 case MotionEvent.ACTION_UP:
26 curPaint.setColor(Color.GREEN);break;
27 default:curPaint.setColor(Color.WHITE);break;
28 }
29 canvas.drawCircle(pX, pY, 10, curPaint);
30 }
31
32 @Override
33 public boolean onTouchEvent(MotionEvent event)
34 {
35
36 action=event.getAction();
37 pX=event.getX();
38 pY=event.getY();
39 invalidate();
40 return true;
41 }
42
43
44 }
触控方法里面比较重要的是直接返回true,不调用基类方法,让重写的onDraw方法及时响应,否则只能体现出按下的效果,移动与提起的操作都体现不出来。
在继承Activity的类中的onCrete方法左如下更改,内容视图不再是activity_main了,也就是activity_main.xml的布局完全不起作用,上面使用的控件全都用不上,反而是另外的一个视图。就是刚定义的Page2
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Page2(this));
}