Android学习笔记(三) 简单控件与基本事件
利用Eclipse新建一个解决方案,代码区域有两个文件,以xml后缀的那个是页面文件,java后缀的是页面的后端代码文件,与winPhone的比起来,甚至与ASP.NET比起来,xml是aspx或xmal,java就相当于aspx.cs或xmal.cs。但经我查阅书籍和实践之后发现,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)); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步