在BB10 Cascades中,如果我们希望向QML页面添加一个多选框,使用的是CheckBox组件。
在QML编辑界面中,开发人员可以直接从右下角的组件栏中将CheckBox组件拖拽到QML页面中的Container中。
CheckBox有两个主要的属性,一个是text,是CheckBox旁边显示的文字,一个是checked,用于指定该选择项是否被选中
如下面的代码创建了一个CheckBox组件,文字是"is important",状态是选中状态:
CheckBox { id: isImportantCheckBox text: "is important" checked: true }
然后CheckBox有CheckedChanged事件,通过onCheckedChanged方法响应,当该CheckBox的选中状态改变时会触发CheckedChanged事件。
在onCheckedChanged方法中有参数checked,可以用于判断当前是否为选中状态,checked的值为true则当前为选中状态,如果checked的值为false则当前状态为未选中。
像下面的代码创建了一个文字为"is new"的CheckBox,当选中状态改变时会根据checked的值修该组件isNewLabel的text属性:
CheckBox { text: "is new" horizontalAlignment: HorizontalAlignment.Fill onCheckedChanged: { if (checked) { isNewLabel.text = "it is new"; } else { isNewLabel.text = "it is old"; } } }
此外,如果我们尝试在QML中加入以上的CheckBox,会发现文字太长时,CheckBox组件会自动隐藏部分文字。
为了显示所有文字,我们需要根据需要调整CheckBox的大小。
同时,因为CheckBox经常多个一块使用,用于组成多选框,所以我们也可以将多个CheckBox放入一个Container中,将CheckBox的horizongtalAlignment属性设置成HorizontalAligment.Fill,然后通过调整Container的大小统一调整Container内所有CheckBox的大小。
还有,CheckBox的checked属性是可以通过方法setChecked来设置的,setChecked(false)将CheckBox设置为未选中状态,setChecked(true)将CheckBox设置为选中状态。
如下面的代码创建了一个按钮,点击时根据isImportantCheckBox组件的check状态对它进行修改,选中的就改为未选中,未选中就改为选中:
Button { horizontalAlignment: HorizontalAlignment.Center onClicked: { if (isImportantCheckBox.checked) { isImportantCheckBox.setChecked(false); } else { isImportantCheckBox.setChecked(true); } } text: "change Value" }
下面是一个使用CheckBox的完整样例:
// Default empty project template import bb.cascades 1.0 // creates one page with a label Page { Container { Container { preferredWidth: 400.0 horizontalAlignment: HorizontalAlignment.Center CheckBox { id: isImportantCheckBox text: "is important" checked: true onCheckedChanged: { if (checked) { isImportantLabel.text = "it is important"; } else { isImportantLabel.text = "it is NOT important"; } } horizontalAlignment: HorizontalAlignment.Fill } CheckBox { text: "is new" horizontalAlignment: HorizontalAlignment.Fill onCheckedChanged: { if (checked) { isNewLabel.text = "it is new"; } else { isNewLabel.text = "it is old"; } } } } Label { id: isImportantLabel horizontalAlignment: HorizontalAlignment.Center text: "it is important" } Label { id: isNewLabel horizontalAlignment: HorizontalAlignment.Center text: "it is old" } Button { horizontalAlignment: HorizontalAlignment.Center onClicked: { if (isImportantCheckBox.checked) { isImportantCheckBox.setChecked(false); } else { isImportantCheckBox.setChecked(true); } } text: "change Value" } } }
下面是以上代码执行的效果。
首先,先看我写的简单小例子
界面代码,xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="24dp" android:layout_marginTop="72dp" android:layout_toRightOf="@+id/start" android:text="@string/pause" /> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/pause" android:layout_alignBottom="@+id/pause" android:layout_centerHorizontal="true" android:text="@string/start" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/start" android:layout_alignBottom="@+id/start" android:layout_marginRight="24dp" android:layout_toLeftOf="@+id/start" android:text="@string/stop" /> <ImageView android:id="@+id/singlecycle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/start" android:layout_marginTop="111dp" android:layout_toRightOf="@+id/stop" android:src="/blog_article/@drawable/singlecycle/index.html" /> </RelativeLayout>主类
public class MainActivity extends Activity { //第一种(即资源文件放在项目中) MediaPlayer player; //第二种(资源文件放在sd卡中) // MediaPlayer player = new MediaPlayer(); Button stop, start, pause; ImageView singlecycle; boolean isSinglecycle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initControl(); } private void initControl(){ //将音乐文件放入项目中的raw文件夹中 player = MediaPlayer.create(this, R.raw.fly); // /*try { //将音乐文件放在sd卡中 player.setDataSource( Environment.getExternalStorageDirectory().getPath() + "/fly.mp3"); player.prepare(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }*/ stop = (Button) findViewById(R.id.stop); start = (Button) findViewById(R.id.start); pause = (Button) findViewById(R.id.pause); singlecycle = (ImageView) findViewById(R.id.singlecycle); stop.setOnClickListener(new ControlListener()); start.setOnClickListener(new ControlListener()); pause.setOnClickListener(new ControlListener()); singlecycle.setOnClickListener(new ControlListener()); //监听定位,检测定位是否完成 player.setOnSeekCompleteListener(new OnSeekCompleteListener() { @Override public void onSeekComplete(MediaPlayer mp) { Toast.makeText(MainActivity.this, "SeekCompleteListener complete", Toast.LENGTH_SHORT).show(); } }); //监听是否进入prepare状态 player.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { Toast.makeText(MainActivity.this, "PreparedListener complete", Toast.LENGTH_SHORT).show(); } }); //当执行stop时,然后再次执行start时,会启动该监听器 player.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() { @Override public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { player.seekTo(0);//如果不这么设置,再次start的时候会接着stop之前的时间播放 } }); //当播放完成时,会启动该监听器 player.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Toast.makeText(MainActivity.this, "OnCompletionListener complete", Toast.LENGTH_SHORT).show(); } }); } class ControlListener implements OnClickListener{ @Override public void onClick(View v) { if(v == stop){ //停止播放 //判断是否在播放,如果有则停止,无则不做该操作 if(player.isPlaying()){ player.stop(); try { player.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }else{ Toast.makeText(MainActivity.this, "stop " + player.isPlaying(), 1000).show(); } }else if(v == start){ //开始播放 player.start(); }else if(v == pause){ //暂停播放 if(player.isPlaying()){ player.pause(); Toast.makeText(MainActivity.this, " " + player.isPlaying(), 1000).show(); }else{ Toast.makeText(MainActivity.this, "pause " + player.isPlaying(), 1000).show(); } }else if(v == singlecycle){ //设置是否单曲循环 if(!isSinglecycle){ singlecycle.setImageResource(R.drawable.singlecycle1); isSinglecycle = true; player.setLooping(true); }else{ singlecycle.setImageResource(R.drawable.singlecycle); isSinglecycle = false; player.setLooping(false); } } }} }
运行效果图
小结:
1、获得MediaPlayer对象的两种方法
第一种:通过new实例化得到
MediaPlayer player = new MediaPlayer();
第二种:使用create方法
MediaPlayer player = MediaPlayer.create(this, R.raw.fly);
注意:
第一种方式:
①成功调用后MediaPlayer将处于Idle状态
②setDataSource对String(path)、Uri、FileDescripor格式的资源路径的支持
③后续需要手动调用prepare()才能进行播放
第二种方式:
①成功调用后,MediaPlayer将处于Prepare状态
②create提供了对int(resID)和URi格式的的资源路径的支持
③无需(也不能再次调用)prepare(),就能直接播放
2、注意stop方法的处理
stop之后立刻让其调用prepare方法,避免再次调用start的时候发生错误
3、release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。
seekTo()方法是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播 放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设 置监听器来处理的。
prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方 法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
其他的代码上有解释,认真看代码,和前面一章的生命周期的讲解。
@interface Player : NSManagedObject @property (nonatomic, retain) NSNumber * age; @property (nonatomic, retain) NSString * name; @end @implementation Player @dynamic age; @dynamic name; @end
NSArray *teamArray = [self fetchTeamList]; if (teamArray) { for (Team *teamObject in teamArray) { NSLog(@"Team info : %@, %@\n", teamObject.name, teamObject.city); } }
Team *teamObject = [NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:self.managedObjectContext]; teamObject.name = teamName; teamObject.city = teamCity;
- (BOOL)insertTeamWithName:(NSString *)teamName city:(NSString *)teamCity { if (!teamName || !teamCity) { return NO; } Team *teamObject = [self getTeamInfoByName:teamName]; if (nil == teamObject) { teamObject = [NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:self.managedObjectContext]; } teamObject.name = teamName; teamObject.city = teamCity; return YES; } - (Team *)getTeamInfoByName:(NSString *)teamName { Team *teamObject = nil; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *teamEntity = [NSEntityDescription entityForName:@"Team" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:teamEntity]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", teamName]; [fetchRequest setPredicate:predicate]; [fetchRequest setFetchLimit:1]; NSError *error = NULL; NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; if (error) { NSLog(@"Error : %@\n", [error localizedDescription]); } if (array && [array count] > 0) { teamObject = [array objectAtIndex:0]; } [fetchRequest release], fetchRequest = nil; return teamObject; }