在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;
}