UIDatePicker的初始化:
self.datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 50, 100, 150)];
[datePicker setTimeZone:[NSTimeZone timeZoneWithName:@"GMT+8"]];//中国是标准加8
[datePicker setDate:[NSDate date] animated:YES];
UIDatePicker的时间范围:
[datePicker setMinimumDate:dateMin];//可显示的最小时间
[datePicker setMaximumDate:dateMax];//可显示的最大时间
[datePicker setDatePickerMode:datePickerMode];
UIDatePickerModeTime, //时间显示器
UIDatePickerModeDate, //日期显示器
UIDatePickerModeDateAndTime, //日期时间显示器
UIDatePickerModeCountDownTimer //时间倒计时
[datePicker addTarget:self action:@selector(datePickerValueChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:datePicker];
参考地址:http://www.flexbj.com/post-29.html
<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="Init()" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:comp="comp.*"> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.events.ListEvent; import mx.controls.Alert; import flash.trace.Trace; import comp.CheckBoxHeaderRenderer; import comp.CheckBoxItemRenderer; import mx.collections.ArrayCollection; public var dataArray:ArrayCollection = new ArrayCollection; private function Init():void{ dataArray.addItem({name:'张三',phone:'2270',email:'12@123.com'}); dataArray.addItem({name:'李四',phone:'2270',email:'12@123.com'}); dataArray.addItem({name:'王五',phone:'2270',email:'12@123.com'}); dataArray.addItem({name:'赵六',phone:'2270',email:'12@123.com'}); dataArray.addItem({name:'小七',phone:'2270',email:'12@123.com'}); dgId.dataProvider = dataArray; } private function ladygaga():void{ var arr:Array=cbc.selectItems; var s:String=''; for each(var o:Object in arr) s+=o.name+"\t"; Alert.show(s); } //选择某行时,同时选中checkbox private function selItem():void{ var selindex:int=dgId.selectedIndex; var dataArr:ArrayCollection=dgId.dataProvider as ArrayCollection; var selectItems:Array = cbc.selectItems; for(var i:int=0;i<dataArr.length;i++){ if(i==selindex){ var obj:Object=dataArr.getItemAt(i); trace(obj.dgSelected); obj.dgSelected=!obj.dgSelected; trace(obj.dgSelected); if(obj.dgSelected) selectItems.push(obj); else{ for(var j:int = 0; j<selectItems.length; j++){ if(selectItems[j] == obj){ selectItems.splice(j,1); } } } } } dataArr.refresh(); } //清除checkbox选中 private function clearChecked():void{ cbc.selectItems.splice(0,cbc.selectItems.length); var da:ArrayCollection = dgId.dataProvider as ArrayCollection; for each(var obj:Object in da){ obj.dgSelected=false; } cbc.cloumnSelected=false; da.refresh(); } ]]> </fx:Script> <mx:DataGrid id="dgId" x="10" y="10" width="450" height="200" itemClick="selItem()" fontSize="12"> <mx:columns> <comp:CheckBoxColumn dataField="dgSelected" width="25" id="cbc" draggable="false" resizable="false" sortable="false" headerRenderer="{new ClassFactory(comp.CheckBoxHeaderRenderer)}" itemRenderer="{new ClassFactory(comp.CheckBoxItemRenderer)}"/> <mx:DataGridColumn headerText="姓名" dataField="name"/> <mx:DataGridColumn headerText="电话" dataField="phone"/> <mx:DataGridColumn headerText="邮件" dataField="email"/> <mx:DataGridColumn headerText="操作" itemRenderer="comp.Operate" dataField="name"/> <mx:DataGridColumn headerText="操作" itemRenderer="ddd.ddd" dataField="phone"/> </mx:columns> </mx:DataGrid> <mx:HBox y="300"> <mx:Button top="300" click="ladygaga()" label="弹出选中" fontSize="12"/> <mx:Button click="clearChecked()" label="清除选中" fontSize="12"/> </mx:HBox> </s:WindowedApplication>
<?xml version="1.0" encoding="utf-8"?> <s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" focusEnabled="true"> <fx:Script> <![CDATA[ import mx.controls.Alert; protected function lblData_clickHandler(event:MouseEvent):void { Alert.show(dataGridListData.label); } ]]> </fx:Script> <s:HGroup top="0" left="0" right="0" bottom="0" horizontalAlign="center"> <s:Label text="删除" click="lblData_clickHandler(event)" buttonMode="true" /> </s:HGroup> </s:MXDataGridItemRenderer>
bug:已有选中行后,如果在点击checkbox不起作用,或者是不是想要的结果
修复:在checkboxitemrenderer的change事件中派发一个事件,通知父组件不要在触发itemclick事件
dispatchEvent(new Event(CHECKBOX_CHANGE));
addEventListener(CheckBoxItemRenderer.CHECKBOX_CHANGE, function(){
checkboxClick = true;
}, true);
private function itemClick():void{
if(checkboxClick) {
// 这里直接返回不继续执行
checkboxClick = false;
return;
}
}
到目前为止,我们已经理解了游戏的结构。即使只是简单的知道了接收输入,更新内部状态,然后渲染到屏幕上,当然也会播放声音或者震动一下
让我们保持简单,看下面的图表
android上面任何事情都是发生在Activity内部,Activity会新建一个view,view是一切事情发生的地方,像触摸和最后的图片显示。把activity想成桌子,而view是一张白纸让我们画东西,我们用铅笔画图,化学反应都是在纸上的,产生了图片,同样也适用于Activity和View,像下图所示
让我们打开DroidzActivity.java,看这行代码
只是Activity在创建时候把R.layout.view赋给了它,我们的例子中 在开始时候就赋值了
让我们创建了一个新的view,一个View是一个简单的类,提供了事件处理,和可见的矩形供我们画,最简单的是扩展Android自己的Surfaceview,我们也需要实现surface.callback来获得surface改变的路径,例如当view被销毁或者设备的方向改变了
MainGamePanel.java
01 package net.obviam.droidz; 02 03 import android.content.Context; 04 import android.graphics.Canvas; 05 import android.view.MotionEvent; 06 import android.view.SurfaceHolder; 07 import android.view.SurfaceView; 08 09 public class MainGamePanel extends SurfaceView implements 10 SurfaceHolder.Callback { 11 12 public MainGamePanel(Context context) { 13 super(context); 14 // adding the callback (this) to the surface holder to intercept events 15 getHolder().addCallback(this); 16 // make the GamePanel focusable so it can handle events 17 setFocusable(true); 18 } 19 20 @Override 21 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 22 } 23 24 @Override 25 public void surfaceCreated(SurfaceHolder holder) { 26 } 27 28 @Override 29 public void surfaceDestroyed(SurfaceHolder holder) { 30 } 31 32 @Override 33 public boolean onTouchEvent(MotionEvent event) { 34 return super.onTouchEvent(event); 35 } 36 37 @Override 38 protected void onDraw(Canvas canvas) { 39 } 40 }
上面的代码只是重写了我们感兴趣的方法,除了15和17行,其他都没什么特别的
这行代码把当前类设置成了在实际surface上发生的事件需要处理的handler
上面的代码使 game panel获得焦点,为了能够获得事件。我们加入了回调并使得view获得焦点,我们不会丢失这个view
20行后面重写的方法会被用到,但是现在让他们为空
让我们建立一个线程,它会是我们实际的游戏循环
01 package net.obviam.droidz; 02 03 public class MainThread extends Thread { 04 05 // flag to hold game state 06 private boolean running; 07 public void setRunning(boolean running) { 08 this.running = running; 09 } 10 11 @Override 12 public void run() { 13 while (running) { 14 // update game state 15 // render state to the screen 16 } 17 } 18
你看到它没有做太多事情,重写了run方法,当running标识为true时,做了个无限循环
当前的进程没有实例化,当屏幕加载的时候,我们来让它运行
看一下修改过的MainGamePanel类
01 package net.obviam.droidz; 02 03 import android.content.Context; 04 import android.graphics.Canvas; 05 import android.view.MotionEvent; 06 import android.view.SurfaceHolder; 07 import android.view.SurfaceView; 08 09 public class MainGamePanel extends SurfaceView implements 10 SurfaceHolder.Callback { 11 12 private MainThread thread; 13 14 public MainGamePanel(Context context) { 15 super(context); 16 getHolder().addCallback(this); 17 18 // create the game loop thread 19 thread = new MainThread(); 20 21 setFocusable(true); 22 } 23 24 @Override 25 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 26 } 27 28 @Override 29 public void surfaceCreated(SurfaceHolder holder) { 30 thread.setRunning(true); 31 thread.start(); 32 } 33 34 @Override 35 public void surfaceDestroyed(SurfaceHolder holder) { 36 boolean retry = true; 37 while (retry) { 38 try { 39 thread.join(); 40 retry = false; 41 } catch (InterruptedException e) { 42 // try again shutting down the thread 43 } 44 } 45 } 46 47 @Override 48 public boolean onTouchEvent(MotionEvent event) { 49 return super.onTouchEvent(event); 50 } 51 52 @Override 53 protected void onDraw(Canvas canvas) { 54 } 55 }
我们加入了下面代码行
12行声明了线程是私有的
19行我们实例化了这个线程
In the surfaceCreated method we set the running flag to true and we start up the thread (lines 30 and 31). By the time the this method is called the surface is already created and the game loop can be safely started.
Take a look at the surfaceDestroyed method.
在surfacecreated的方法中 我们设置了running为true,然后我们让线程开始运行(30和31行)。当surface被创建的时候,游戏循环可以安全的开始运行了
看一下surfaceDestroy方法
01 public void surfaceDestroyed(SurfaceHolder holder) { 02 // tell the thread to shut down and wait for it to finish 03 // this is a clean shutdown 04 boolean retry = true; 05 while (retry) { 06 try { 07 thread.join(); 08 retry = false; 09 } catch (InterruptedException e) { 10 // try again shutting down the thread 11 } 12 } 13 }
这个方法在surface被销毁前被调用,这里不是设置running标识的地方,但是这里的代码保证了线程被干净的关闭了,我们只是阻塞线程,等待它的死亡
如果在模拟器运行,我们啥也看不这,但是我们可以打一些log来测试,不要担心,后面会告诉你是怎么回事的,更多的请参考Android site.
加入和屏幕的交互我们会关闭程序当我们按屏幕下方的时候,如果我们点别的地方,我们只是记录坐标位置
在mainThread类中 我们加入如下行
1 private SurfaceHolder surfaceHolder; 2 private MainGamePanel gamePanel; 3 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) { 4 super(); 5 this.surfaceHolder = surfaceHolder; 6 this.gamePanel = gamePanel; 7 }
我们声明了变量gamepanel和surfaceHolder,在构造函数中实例化了他们
我们拥有他们是非常重要的,不仅仅是gamepanel,因为我们需要锁住surface来画图,而这个操作只能通过surfaceHolder
改变在构造函数中的方法
我们传递了当前的holder和panel,所以线程可以访问他们,我们稍后会新建一个游戏更新的函数在game panel中,在线程中也会触发它,但是现在我们保持现状
TAG 常量是android log函数的第一个参数
打log的笔记打开log的视图,
Now you should see the LogCat view. This is nothing more than a console where you can follow Android’s log. It’s a great tool as you can filter for logs containing a specific text or logs with a certain tag which is quite useful.
回到代码,MainThread.java现在是这样了
01 package net.obviam.droidz; 02 03 import android.util.Log; 04 import android.view.SurfaceHolder; 05 06 public class MainThread extends Thread { 07 08 private static final String TAG = MainThread.class.getSimpleName(); 09 10 private SurfaceHolder surfaceHolder; 11 private MainGamePanel gamePanel; 12 private boolean running; 13 public void setRunning(boolean running) { 14 this.running = running; 15 } 16 17 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) { 18 super(); 19 this.surfaceHolder = surfaceHolder; 20 this.gamePanel = gamePanel; 21 } 22 23 @Override 24 public void run() { 25 long tickCount = 0L; 26 Log.d(TAG, "Starting game loop"); 27 while (running) { 28 tickCount++; 29 // update game state 30 // render state to the screen 31 } 32 Log.d(TAG, "Game loop executed " + tickCount + " times"); 33 } 34 }
在8行 我们定义了 log的tag
在run函数中我们定义tickcount,当游戏循环被执行,它会加1
让我们回到MainGamePanel.java类,我们修改OnTOuchEvent,来处理触摸消息
01 public boolean onTouchEvent(MotionEvent event) { 02 if (event.getAction() == MotionEvent.ACTION_DOWN) { 03 if (event.getY() > getHeight() - 50) { 04 thread.setRunning(false); 05 ((Activity)getContext()).finish(); 06 } else { 07 Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY()); 08 } 09 } 10 return super.onTouchEvent(event); 11 }
同样也修改了DroidzActivity
01 package net.obviam.droidz; 02 03 import android.app.Activity; 04 import android.os.Bundle; 05 import android.util.Log; 06 import android.view.Window; 07 import android.view.WindowManager; 08 09 public class DroidzActivity extends Activity { 10 /** Called when the activity is first created. */ 11 12 private static final String TAG = DroidzActivity.class.getSimpleName(); 13 14 @Override 15 public void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 // requesting to turn the title OFF 18 requestWindowFeature(Window.FEATURE_NO_TITLE); 19 // making it full screen 20 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 21 // set our MainGamePanel as the View 22 setContentView(new MainGamePanel(this)); 23 Log.d(TAG, "View added"); 24 } 25 26 @Override 27 protected void onDestroy() { 28 Log.d(TAG, "Destroying..."); 29 super.onDestroy(); 30 } 31 32 @Override 33 protected void onStop() { 34 Log.d(TAG, "Stopping..."); 35 super.onStop(); 36 } 37 }
运行程序,在程序上部点击几下,然后点击下部,程序应该退出
LogCat
目前做的事情
1 创建了一个全屏程序
2 有一个独立的线程控制程序
3 解析基本手势 例如触摸手势
4 优雅的关闭程序
代码大家可以去这里下载