用户界面
XML布局文件和Activity类
Android布局文件XML是在res/layout文件夹下的xml文件,里面可以放一些组件
启动Activity时, Android 框架会调用 Activity 中的 onCreate() 回调方法,从而加载应
用代码中的布局资源;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
事件处理
三个对象:事件源(例:button)、事件监听器(事件处理方法)、事件(系统生成)
基于监听事件的处理方法的实现
1. 在布局文件里绑定
2. Activity做事件监听器(实现接口,重写方法)
3. 匿名内部类(new 接口)
4.内部类实现接口
5. 外部类
多选的事件监听
radioGroup = (RadioGroup)findViewById(R.id.MusicSelect);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
selectRadioBtn();
}
});
private void selectRadioBtn(){
radioButton = (RadioButton) findViewById(radioGroup.getCheckedRadioButtonId());
text = radioButton.getText().toString();
}
页面切换与数据传递
使用intent
出发的Activity
Intent intent = new Intent(MainActivity.this, OfflineActivity.class);
intent.putExtra("Music",text);
startActivity(intent);
到达的Activity
String MusicSelect = getIntent().getStringExtra("Music");
图形处理与绘制
Color类
Paint类和Canvas类的方法,自己在网上搜吧,这里有用到一个canvas锁
在绘制的逻辑中通过lockCanvas()方法
获取Canvas对象进行绘制,通过
unlockCanvasAndPost(mCanvas)方法 对画布内容进行提交。
//绘制开始
canvas = mSurfaceHolder.lockCanvas();
......
//绘制结束后
mSurfaceHolder.unlockCanvasAndPost(canvas);
游戏开发的视图
如何使用SurfaceView
1. 创建自定义SurfaceView继承自SurfaceView并实现两个接口:
public abstract class BaseGame extends SurfaceView implements SurfaceHolder.Callback, Runnable{
2. 在构造函数里初始化如下成员变量
boolean mbLoop; //控制绘画线程的标志位
private final SurfaceHolder mSurfaceHolder;
private Canvas canvas; //绘图的画布
private final Paint mPaint;
mbLoop = true;
mPaint = new Paint(); //设置画笔
mSurfaceHolder = this.getHolder();
mSurfaceHolder.addCallback(this);
this.setFocusable(true);
3. 实现SurfaceHolder.Callback接口
create里创建线程并启动
@Override
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
/*TODO*/
mbLoop = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
GameActivity.screenWidth = i1;
GameActivity.screenHeight = i2;
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
/*TODO*/
mbLoop = false;
}
4. 实现Runnable接口
@Override
public void run() {
/*TODO*/
while(mbLoop){
//run 函数一直跑
//绘制对手分数
if(partner) {
//Log.d()
actionOver();
}
draw();
if(gameOverFlag) continue;
action();
}
}
数据存储
APP内部文件存储的实现方式
Context是抽象类,Android提供了该抽象类的具体实现类;通过它,我们可以获取应用程序的资源。
需要使用Context
➢ 四大组件的交互,包括启动 Activity、Broadcast、Service,获取 ContentResolver 等。
➢ 获取系统/应用资源,包括 AssetManager、PackageManager、 Resources、System Service 以及 color、string、drawable 等。
➢ 文件,包括获取缓存文件夹、删除文件、SharedPreference 相关等。
➢ 数据库(SQLite)相关,包括打开数据库、删除数据库、获取数据库路径等
数据展示:使用适配器和适配器控件展示和处理数据的方法
适配器控件ListView
- 以表格形式展示数据
- 处理用户对表格的操作
在xml文件里加入ListView
<ListView
android:id="@+id/playerListView"
android:layout_width="358dp"
android:layout_height="533dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.545" />
在Activity内对ListView进行操作
- 绑定adapter
- 监听
//获取ListView
ListView listview = (ListView) findViewById(R.id.playerListView);
//添加并且显示
listview.setAdapter(listItemAdapter);
//添加事件监听器
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
showDeleteDialog(arg0,arg1,arg2,arg3,listItemAdapter,listview);
}
});
适配器SimpleAdapter
向ListView里面放数据
要学习创建SimpleAdapter的要传入的参数,根据参数要求去转换自己的数据格式
学习链接:AndroidStudio中ListView的使用方法之SimpleAdapter适配器-CSDN博客
与用户的交互:掌握AlertDialog的使用
对话框
比较深:Android———最详细的系统对话框(AlertDialog)详解 - Jetictors - 博客园 (cnblogs.com)
Handler的工作机制
掌握子线程通过主线程Handler更新主线程UI的方法
(子线程对UI线程的操作是不安全的,为解决子线程与UI线程的信息交互)
BaseGame是SurfaceView的子类,游戏绘制运行在子线程,无法直接更新UI。
游戏结束后BaseGame发消息给GameActivity,由GameActivity加载展示排行榜页面
先来介绍要用到的三个类
工作流程
Looper类及里面的MessageQueue类都是线程帮我们创建好的
子线程通知UI更新UI步骤
class MyHandler extends Handler {
//复写handlerMessage
@Override
public void handleMessage(Message msg) {
// 根据不同线程发送过来的消息,执行不同的UI操作
// 根据 Message对象的what属性 标识不同的消息
if(msg.what == 1 && msg.obj.toString().equals("over")) {
// BaseGame 发消息过来了,游戏结束,进入排行榜页面
/** 页面跳转 **/
Log.d(TAG, "BaseGame 发消息过来了,游戏结束,进入排行榜页面");
if (partner) {
Intent intent = new Intent(GameActivity.this, PartnerScoreActivity.class);
intent.putExtra("gameLever", gameType);
startActivity(intent);
}else {
Intent intent = new Intent(GameActivity.this, PlayerListActivity.class);
intent.putExtra("gameLever", gameType);
startActivity(intent);
}
}
}
}
Handler mHandler = new MyHandler();