疯狂android讲义---事件处理2

//去除窗口标题

requestWindowFeature(Window.FEATURE_NO_TITLE);

//全屏显示

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

 

//获取窗口管理器

WindowManager windowManager = getWindowManager();

     Display display = windowManager.getDefaultDisplay();

     // 获取屏幕宽和高

     int screenWidth = display.getWidth();

     int screenHeight = display.getHeight();

 

 

下面这种方式:该游戏几乎不需要页面布局,直接使用PlaneView作为Activity显示的内容

final PlaneView planeView = new PlaneView(this);

     setContentView(planeView);

 

publicclass PlaneView extends View

{

  publicfloat currentX;

  publicfloat currentY;

  Bitmap plane;

  public PlaneView(Context context)

  {

     super(context);

     plane = BitmapFactory.decodeResource(context.getResources(), R.drawable.plane);

setFocusable(true);去掉这行点击没反应,这句什么情况下运用?  }

  @Override

  publicvoid onDraw (Canvas canvas)

  {

     super.onDraw(canvas);

     Paint p = new Paint();

     canvas.drawBitmap(plane , currentX , currentY , p);

  }

}

draw组件绑定键盘事件监听器

planeView.setOnKeyListener(new OnKeyListener()

     {

       publicboolean onKey(View source, int keyCode, KeyEvent event)

       {

         switch (event.getKeyCode())

         {

            case KeyEvent.KEYCODE_DPAD_DOWN:

              planeView.currentY += speed;

              break;

            case KeyEvent.KEYCODE_DPAD_UP:

              planeView.currentY -= speed;

              break;

            case KeyEvent.KEYCODE_DPAD_LEFT:

              planeView.currentX -= speed;

              break;

            case KeyEvent.KEYCODE_DPAD_RIGHT:

              planeView.currentX += speed;

              break;

         }

         planeView.invalidate();

         returntrue;

       }

     });

 

 

 

有些时候并未发现事件的踪迹,这是因为android为事件监听模型做了进一步简化:如果事件源触发的事件足够简单,事件里封装的信息比较有限,就无需封装事件对象,将事件对象直接传入事件监听器

但对于一些复杂的事件(如键盘按键事件,需要包含更多的信息,android会将事件信息封装成XXXEvent对象,并把对象作为参数传入事件监听器)

上述程序将事件信息封装成Event对象。调用KeyEvent(事件对象)getKeyCode()来获取触发事件的键。

在基于事件监听的处理模型中,事件监听器必须实现事件监听器接口,android为不同的界面组件提供了不同的监听器接口,这些接口通常以内部类的形式存在。以View为例,它包含了如下几个内部接口:

View.OnClickListener:单击事件的事件监听器必须实现的接口

View.OnCreateContextMenuListener:创建上下文菜单事件的事件监听器必须实现的接口

View.onFocusChangeListener:焦点改变事件的事件监听器必须实现的接口。

View.OnKeyListener :按键事件的事件监听器必须实现的接口。

View.OnLongClickListener:长单击事件的事件处理器必须实现的接口

View.OnTouchListener:触摸屏事件的事件监听器必须实现的接口。

普通的java程序里的方法由程序主动调用,事件处理器中的事件处理方法是由系统负责调用。

所谓事件监听器,其实就是实现了特定接口的java类得实例。实现事件监听器,通常有如下几种形式:

内部类形式:

外部类形式

activity本身作为事件监听器类:让activity本身实现监听器接口,并实现事件处理方法

匿名内部类形式:使用匿名内部类创建事件监听器对象。

 

 

内部类:

publicclass EventQs extends Activity

{

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

     //获取应用程序中的bn按钮

     Button bn = (Button)findViewById(R.id.bn);

     //为按钮绑定事件监听器。

     bn.setOnClickListener(new MyClickListener());

  }

  //定义一个单击事件的监听器

  class MyClickListener implements View.OnClickListener

  {

     //实现监听器类必须实现的方法,该方法将会作为事件处理器

     @Override

     publicvoid onClick(View arg0)

     {

       EditText txt = (EditText)findViewById(R.id.txt);

       txt.setText("bn按钮被单击了!");

     }   

  }

}

 

外部类作为事件监听器类

这种做法比较少见,主要有以下两点原因:

1,    事件监听器通常属于特定GUI界面,定义成外部类不利于提高程序的内聚性

2,    外部类的事件监听器不能自由访问创建GUI界面的类中的组件,编程不够简洁。

但如果某个事件监听器确实被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现,则可以考虑使用外部类形式。

例如:

publicclass SendSmsListener implements OnLongClickListener

{

  private Activity act;

  private EditText address;

  private EditText content;

 

  public SendSmsListener(Activity act, EditText address, EditText content)

  {

     this.act = act;

     this.address = address;

     this.content = content;

  }

  @Override

  publicboolean onLongClick(View source)

  {

     String addressStr = address.getText().toString();

     String contentStr = content.getText().toString();

     SmsManager smsManager = SmsManager.getDefault();

     PendingIntent sentIntent = PendingIntent.getBroadcast(act, 0,

       new Intent(), 0);

     smsManager.sendTextMessage(addressStr, null, contentStr

       , sentIntent, null);

     Toast.makeText(act, "ŷ", Toast.LENGTH_LONG).show();

     returnfalse;

  }

}

 

 

3,    activity本身作为事件监听器

缺点是分工不明确,看起来比较怪异。

//实现事件监听器接口

publicclass ActivityListener extends Activity

  implements OnClickListener

{

  EditText show;

  Button bn;

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

     show = (EditText)findViewById(R.id.show);

     bn = (Button)findViewById(R.id.bn);

     //直接使用Activity作为事件监听器

     bn.setOnClickListener(this);

  }

 

  //实现事件处理方法

  @Override

  public void onClick(View v)

  {

     // TODO Auto-generated method stub

     show.setText("bn按钮被单击了!");

  }

}

 

匿名内部类:
publicclass AnonymousListener extends Activity

{

  EditText show;

  Button bn

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

     show = (EditText)findViewById(R.id.show);

     bn = (Button)findViewById(R.id.bn);

     //直接使用Activity作为事件监听器

     bn.setOnClickListener(new OnClickListener()

     {

       //实现事件处理方法

       @Override

       public void onClick(View v)

       {

         // TODO Auto-generated method stub

         show.setText("bn按钮被单击了!");

       }     

     });

  }

}这是常用的,因为基本上监听器只会用一次

 

3.2.7

直接绑定到标签

直接在界面布局文件中为制定标签绑定事件处理方法。

对于很多android界面组件标签而言,它们都支持如onClick,onLongClick等属性,这种属性的属性值就是一个形如xxx(View source)的方法的方法名。

publicclass BingingTag extends Activity

{

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

  }

  //定义一个事件处理方法

  //其中source参数代表事件源

  publicvoid clickHandler(View source)

  {

     EditText show = (EditText)findViewById(R.id.show);

     show.setText("bn按钮被单击了");

  }

}

在布局文件中为Button按钮绑定了一个事件处理方法:clickHanlder,所以在对应的activity中要定义一个void clickHandler(View source)方法,该方法会负责处理该按钮上的单击事件。

 

3.3 基于回调的事件处理

如果说监听器是委派式,那么回调则恰好相反;对于回调的事件处理模型来说,事件源与事件监听器是统一的,或者说监听器消失了。当用户在GUI组件上激发某种事件时,组件自己特定的方法会负责处理该事件。

为了使用回调机制类处理GUI组件上所发生的事件,我们需要为组件提供相应的事件处理方法,而java是一种静态语言,无法为某个对象动态的添加方法,因此只能继承GUI组件类,并重写该类的事件处理方法来实现。

android为所有GUI组件都提供了一些事件处理的回调方法,以View为例,该类包含如下方法。

boolean  onKeyDown(int keyCode,KeyEvent event):当用户在该组件按下某个按键时触发该方法。

boolean onKeyLongPress(int KeyCode,KeyEvent event):当用户在该组件上常按某个按键时触发该方法。

boolean onKeyShortcut(int KeyCode,KeyEvent event):当一个键盘快捷键事件发生时触发该方法。

boolean onKeyUp(int keyCode,KeyEvent event):当用户在该组件上松开某个按键时触发该方法

boolean onTouchEvent(MotionEvent event):当用户在该组件上触发触摸屏事件时触发该方法

boolean onTrackballEvent(MotionEvent event) 当用户在该组件上触发轨迹球屏事件时触发该方法。

 

publicclass CallbackHandler extends Activity

{

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

  }

}

publicclass MyButton extends Button

{

  public MyButton(Context context , AttributeSet set)

  {

     super(context , set);

     // TODO Auto-generated constructor stub

  }

  @Override

  publicboolean onKeyDown(int keyCode, KeyEvent event)

  {

     super.onKeyDown(keyCode , event);

     Log.v("-crazyit.org-" , "the onKeyDown in MyButton");

     //返回true,表明该事件不会向外扩散

     returntrue;

  }

}

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<!-- 使用自定义View时应使用全限定类名 -->

<org.crazyit.event.MyButton 

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:text="单击我"

    />

</LinearLayout>

 

布局文件中使用Mybutton组件,java程序无须为该按钮绑定事件监听器因为该按钮自己重写了onKeyDown()方法,这意味着该按钮将会自己处理相应的事件。

通过上面介绍不然发现:基于监听的事件处理模型来说,事件源和事件监听器是分离的,当事件源发生特定事件后,该事件交给事件监听器负责处理;对于回调事件处理模型来说,事件源和事件监听器是统一的,当事件源发生特定事件后,该事件还是由模型本身负责。

3.3.2  基于回调的事件传播

几乎所有基于回调的事件处理都有一个boolean类型的返回值,该返回值标识该处理方法是否能完全处理该事件:

1,    返回true,表明已处理不会传播出去

2,    false ,表明未完全处理,会继续传播

对于基于回调的事件传播而言,某组件上的事情不仅激发该组件上的回调方法,也会激发该组件所在activity的回调方法只要能传播到该activity

publicclass MyButton extends Button

{

  public MyButton(Context context , AttributeSet set)

  {

     super(context , set);

  }

  @Override

  publicboolean onKeyDown(int keyCode, KeyEvent event)

  {

     super.onKeyDown(keyCode , event);

     Log.v("-MyButton-" , "the onKeyDown in MyButton");

     //返回false,表明并未完全处理该事件,该事件依然向外扩散

     returnfalse;

  }

}

publicclass Propagation extends Activity

{

  @Override

  publicvoid onCreate(Bundle savedInstanceState)

  {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

     Button bn = (Button)findViewById(R.id.bn);

     //bn绑定事件监听器

     bn.setOnKeyListener(new OnKeyListener()

     {

       @Override

       publicboolean onKey(View source

         , int keyCode, KeyEvent event)

       {

         //只处理按下键的事件

         if (event.getAction() == KeyEvent.ACTION_DOWN)

         {

            Log.v("-Listener-" , "the onKeyDown in Listener");

         }

         // 返回false,表明该事件会向外传播

         returnfalse;

       }

     });

  }

  //重写onKeyDown方法,该方法可监听它所包含的所有组件的按键被按下事件

  @Override

  publicboolean onKeyDown(int keyCode, KeyEvent event)

  {

     super.onKeyDown(keyCode , event);

     Log.v("-Activity-" , "the onKeyDown in Activity");

     //返回false,表明并未完全处理该事件,该事件依然向外扩散

     returnfalse;

  }

}

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<!-- 使用自定义View时应使用全限定类名 -->

<org.crazyit.event.MyButton 

    android:id="@+id/bn"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:text="单击我"

    />

</LinearLayout>

 

最终的结果是

the onKeyDown in Listener

the onKeyDown in MyButton

the onKeyDown in Activity

最先触发的是绑定在按键上的监听器,接着触发该组件提供的事件回调方法,然后传播到该组件所在的activity,当将false改成true的时候就会停止传播。

 

 

 

 

 

你可能感兴趣的:(java,android,layout,button,Constructor,encoding)