创建BeatBox应用
1.在Android Studio中,选择File → New → New Project…菜单项创建新项目,项目名称是BeatBox
2.新建一个名为BeatBoxActivity的空activity,其余默认项保持不变,完成项目创建。
3.首先创建RecyclerView布局文件。向导产生的res/layout/activity_beat_box.xml没用,因此直接改名为fragment_beat box.xml。然后,修改代码完成布局定义
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</layout>
4.现在,在com.bignerdranch.android.beatbox包中,创建名为BeatBoxFragment的新Fragment, 代码如下
public class BeatBoxFragment extends Fragment {
public static BeatBoxFragment newInstance() {
return new BeatBoxFragment();
}
5.然后,清空BeatBoxActivity类中的所有内容,改为继承SingleFragmentActivity类,并覆盖createFragment()方法
public class BeatBoxFragment extends Fragment(
public static BeatBoxFragment newInstance()£
return new BeatBoxFragment()
数据绑定
6.在应用的build.gradle文件里启用数据绑定,代码如下所示。
versionCode 1
versionName"1.0"
testinstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt').
'proguard-rules.pro'
}
}
dataBinding {
enabled = true
}
}
dependencies {
7.一般布局改为数据绑定布局
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler view"
android:layout width=match parent"
android:layout_height="match_parent"/>
</layout>
8.实例化绑定类(BeatBoxFragment.java)
public class BeatBoxFragment extends Fragment
public static BeatBoxFragment newinstance(){
return new BeatBoxFragment();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)(
FragmentBeatBoxBinding binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_beat_box, container, false);return binding.getRoot()
9.配置RecyclerView(BeatBoxFragment.java)
public class BeatBoxFragment extends Fragment f
public static BeatBoxFragment newinstance()
return new BeatBoxFragment();
Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)(
FragmentBeatBoxBinding binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_beat_box, container, false);
binding.recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),
3));
return binding.getRoot();
10.接下来,创建按钮布局文件res/layout/list_item_sound.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<Button
android:layout_width="match_parent"
android:layout_height="120dp"
tools:text="Sound name"/>
</layout>
11.创建SoundHolder(BeatBoxFragment.java)
public class Beatboreueament newinstance{
public static BeatBoxFragment newinstance(){
return new BeatBoxFragment()
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
private class SoundHolder extends RecyclerView.ViewHolder{ f private ListItemSoundBinding mBinding;
private SoundHolder(ListItemSoundBinding binding)
super{binding.getRoot()};
mBinding = binding;
}
12.创建SoundAdapter(BeatBoxFragmentjava)
public class BeatBoxFragment extends Fragment {
private class SoundHolder extends RecyclerView.ViewHolder{}
private class SoundAdapter extends RecyclerView.Adapter<SoundHolder> {@Override
public SoundHolder onCreateViewHolder(ViewGroup parent, int viewType){ LayoutInflater inflater = LayoutInflater.from(getActivity()}; ListItemSoundBinding binding = DataBindingUtil
.inflate(inflater, R.layout,list_item_sound, parent, false); returnnew SoundHolder(binding);
}
@Override 20
public void onBindViewHolder(SoundHolder holder, int position){}
@Override
public intgetItemCount(){
return 0;
}
}
}
13. 使用SoundAdapter (BeatBoxFragmentjava)
@Override
public View onCreateView(layoutinflater inflater, ViewGroup container,
Bundle savedinstanceState){
FragmentBeatBoxBinding binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_beat_box, container, false);binding.recyclerView.setlayoutManager(new GridlayoutManager(getActivity(),3));binding.recyclerView.setAdapter(new SoundAdapter());
return binding.getRoot()
}
导入assets
14.首先创建assets目录。右键单击app模块,选择New→Folder→AssetsFolder菜单项,弹出如图所示的画面。不勾选Change Folder Location选项,保持Target Source
Set的main选项不变,单击Finish按钮完成。
接着,右键单击assets目录,选择New→Directory菜单项,为声音资源创建sample_sounds子
15.下载并解压语音文件至assets/sample sounds目录,如图所示
处理assets
16.新建一个名为BeatBox的资源管理类。代码如下所示,在com.bignerdranch.android.beatbox包中创建这个类,并
添加两个常量:一个用于日志记录,另一个用于存储声音资源文件目录名。
public class BeatBox {
private static final String TAG =“BeatBox";
private static final String SOUNDS_FOLDER =“sample_sounds";
}
17.添加一个带Context参数的构造函数获取并留存它,如代码所示
public class BeatBox {
private static final String TAG ="BeatBox";
private static final String SOUNDS_FOLDER ="sample_sounds";private AssetManager mAssets;
public BeatBox(Context context) {
mAssets = context.getAssets();
}
}
18.查看assets资源(BeatBox.java)
public BeatBox(Context context) {
mAssets = context.getAssets();
LoadSounds();
}
private void loadSounds(){
String[] soundNames;
try {
soundNames = mAssets.list(SOUNDS_FOLDER);
Log.i(TAG,"Found"+ soundNames.length +" sounds");
} catch (IOException ioe){
Log.e(TAG, "Could not list assets", ioe);
return;
}
}
19.创建BeatBox实例(BeatBoxFragmentjava)
public class BeatBoxFragment extends Fragment{
private BeatBox mBeatBox;
public static BeatBoxFragment newInstance(){
return new BeatBoxFragment();
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mBeatBox = new BeatBox(getActivity());
}
}
使用assets
20.创建一个Sound管理类,代码如下所示
public class Sound {
private String mAssetPath;
private String mName;
public Sound(String assetPath) {
mAssetPath = assetPath;
String[] components = assetPath.split("/");
String filename = components [components.length - 1];
mName= filename.replace(".wav","");
}
public String getAssetPath(){
return mAssetPath;
}
public String getName() {
return mName;
}
}
21.接下来,在BeatBox.loadSounds()方法中创建一个Sound列表
public class BeatBox {
private AssetManager mAssets;
private List<Sound> mSounds = new ArrayList>();
public BeatBox(Context context){
}
private void loadSounds() {
String[] soundNames;
try {
} catch(I0Exception ioe){
}
for (String filename : soundNames){
String assetPath = SOUNDS_FOLDER +"/”+ filename;
Sound sound = new Sound(assetPath);
mSounds.add(sound);
}
}
public List<Sound> getSounds(){
return mSounds;
}
}
22.绑定Sound列表(BeatBoxFragment.java)
private class SoundAdapter extends RecyclerView.Adapter<SoundHolder> { private List<Sound> mSounds;
public SoundAdapter(List<Sound> sounds) {
mSounds = sounds;
...}
@Override
public void onBindViewHolder(SoundHolder soundHolder, int position){
}
@Override
public int getItemCount(){
return mSounds.size();
}
}
创建视图模型
23.创建一个名为SoundViewModel的新类,然后添加两个属性:一个Sound对象,一个播放声音文件的BeatBox对象,代码如下所示
public class SoundViewModel {
private Sound mSound;
private BeatBox mBeatBox;
public SoundViewModel(BeatBox beatBox){
mBeatBox = beatBox;
}
public Sound getSound(){
return mSound;
}
public void setSound(Sound sound) {
mSound = sound;
}
}
24.添加绑定方法(SoundViewModel.java)
public class SoundViewModel {
private Sound mSound;
private BeatBox mBeatBox;
public SoundViewModel(BeatBox beatBox){
mBeatBox = beatBox;
}
public String getTitle(){
return mSound.getName();
}
public Sound getSound(){
return mSound;
绑定至视图模型
25.声明视图模型属性(list item sound.xml)
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.bignerdranch.android.beatbox.SoundViewModel"/>
</data>
<Button
26.绑定按钮文件名(list_item sound.xml)
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.bignerdranch.android.beatbox.SoundViewModel"/>
</data>
<Button
android:layout width="match_parent"
android:layout_height="120dp"
android:text="@[viewModel.title】"
tools:text="Sound name"/>
</layout>
27.关联使用视图模型(BeatBoxFragment.java)
private class SoundHolder extends RecyclerView.ViewHolder{
private listitemSoundBinding mBinding;
private SoundHolder(listitemSoundBinding binding){
super(binding.getRoot());
mBinding = binding;
mBinding.setViewModel(new SoundViewModel(mBeatBox));
}
public void bind(Sound sound) {
mBinding.getViewModel().setSound(sound);
mBinding.executePendingBindings();
}
}
28.调用bind(Sound)方法(BeatBoxFragmentjava)
return new SoundHolder(binding);
}
@Override
public void onBindViewHolder(SoundHolder holder, int position){
Sound sound = mSounds.get(position);
holder.bind(sound);
}
@Override
public int getitemCount(){
return mSounds.size();
}
29.运行结果如下图所示