CriminalIntent项目的强大完善
CriminalIntentAPP的又一次革命
经过了前面五章代码的编写与结构的梳理,这款app的界面已基本成型。接下来,我会对后面三章的内容进行分析,帮助同学们进一步地完善相关的功能,相信你们一定会喜欢后续的改变的。
第十二章:日期对话框,fragment数据传递
1、使用 DialogFragment
AppCompat兼容库能通过支持库的方式将部分最新系统的特色功能移植到Android旧版本系统中。
所以需要在 Porject Structure 中添加 appcompat-v7 的依赖!
2、创建 DialogFragment
建议将 AlertDialog 封装在 DialogFragment (Fragment的子类)实例中使用;
通过使用 FragmentManager 管理对话框,可以更灵活地显示对话框。
首先需要一个针对 dialog 的布局文件,如 DatePicker 作为根元素的 Dialog 用于选择日期。
<?xml version="1.0" encoding="utf-8"?> <DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_date_date_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:calendarViewShown="false"> </DatePicker>
然后新建一个父类是 DialogFragment 的类 DatePickerFragment,重写其中的 onCreateDialog 方法,返回一个AlertDialog
@Override public Dialog onCreateDialog(Bundle savedInstanceState) { // 使用 LayoutInflater 引用布局文件创建用于显示 Dialog 的 View View v = LayoutInflater.from(getActivity()) .inflate(R.layout.dialog_date, null); return new AlertDialog.Builder(getActivity()) .setView(v) // 设置视图 .setTitle(R.string.date_picker_title) //设置标题 // 设置 OK 按钮,OnClickListener 暂时留空 .setPositiveButton(android.R.string.ok, null) // 使用 Builder 的 create() 方法创建 Dialog 并返回 .create(); }
在使用 DialogFragment 时,使用成员方法 show 来显示 dialog:
// 在 Fragment 中为 DatePickerFragment 添加一个 Tag private static final String DIALOG_DATE = "DialogDate"; …… // 在 Fragment 内部获取 FragmentManager FragmentManager manager = getFragmentManager(); DatePickerFragment dialog = new DatePickerFragment(); // 显示对话框 dialog.show(manager, DIALOG_DATE);
3、将数据传递到对话框
需要在 DatePickerFragment 中建立获取实例的 newInstance 方法,其中需要的参数是传递的信息即可,示例如下
// DatePickerFragment.java public static DatePickerFragment newInstance(Date date) { // 新建一个 Bundle 对象用于存放数据 Bundle args = new Bundle(); args.putSerializable(ARG_DATE, date); DatePickerFragment fragment = new DatePickerFragment(); // 使用 fragment arguments 来传递参数 fragment.setArguments(args); return fragment; }
4、从对话框回传数据
设置目标 fragment,传递数据给目标 Fragment
处理由同一 activity 托管的两个 fragment 间的数据返回时,可借用Fragment.onActivityResult(...)
方法。因此,直接调用目标 fragment 的Fragment.onActivityResult(...)
方法,,就能实现数据的回传。
// DatePickerFragment.java public static final String EXTRA_DATE = "com.kniost.criminalintent.date"; …… private void sendResult(int resultCode, Date date) { // 防止出错 if (getTargetFragment() == null) { return; } Intent intent = new Intent(); // 放置数据到 Intent 中 intent.putExtra(EXTRA_DATE, date); // 获取目标 fragment,调用其 onActivityResult 方法,其中 RequestCode 是用 getTargetRequestCode 方法获取的,resultCode 是传入参数,intent 包含了数据 getTargetFragment() .onActivityResult(getTargetRequestCode(), resultCode, intent); } // CrimeFragment.java @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // 如果一切正常,调用 sendResult 的方法时传入的参数应该就是 Activity.RESULT_OK,所以不会直接 return if (resultCode != Activity.RESULT_OK) { return; } // 如此判断方便有多个回传时使用 if (requestCode == REQUEST_DATE) { Date date = (Date) data .getSerializableExtra(DatePickerFragment.EXTRA_DATE); mCrime.setDate(date); mDateButton.setText(mCrime.getDate().toString()); } }
第十三章:工具栏,菜单,层级式导航
1、在 XML 文件中定义菜单
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_item_new_crime" android:icon="@android:drawable/ic_menu_add" android:title="@string/new_crime" app:showAsAction="ifRoom|withText"/> </menu>
2、实例化菜单
在CrimeListFragment.java中,覆盖onCreateOptionsMenu(Menu, MenuInflater)方法,实例化fragment_crime_list.xml中定义的菜单,如下:
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.fragment_crime_list, menu); }
3、让菜单发挥作用
在初始化菜单后,我们已经能在应用界面上看到菜单了,现在需要让菜单能够有实际的作用,比如新增一个 Crime,要达到这个目的,我们需要做下面几件事:
- 在 Model 层增加一个新增的函数
-
在 Controller 层增加菜单监听
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_item_new_crime: Crime crime = new Crime(); CrimeLab.get(getActivity()).addCrime(crime); Intent intent = CrimePagerActivity .newIntent(getActivity(), crime.getId()); startActivity(intent); return true; default: super.onOptionsItemSelected(item); } }
第十四章:SQLite数据库的使用
基本框架:
其中基本步骤:
定义 CrimeTable 内部类数据、表字段(CrimeDbSchema.java)
package edu.niit.software.criminalintent.database; /** * Created by 666 on 2017/9/29. */ public class CrimeDbSchema { public static final class CrimeTable{ public static final String NAME = "crimes"; public static final class Cols{ public static final String UUID = "uuid"; public static final String TITLE = "title"; public static final String DATE = "date"; public static final String SOLVED = "solved"; } } }
创建 CrimeBaseHelper 类(CrimeBaseHelper.java)
package edu.niit.software.criminalintent.database; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import edu.niit.software.criminalintent.database.CrimeDbSchema.CrimeTable; /** * Created by 666 on 2017/9/29. */ public class CrimeBaseHelper extends SQLiteOpenHelper { private static final int VERSION = 1; private static final String DATABASE_NAME = "crimeBase.db"; public CrimeBaseHelper(Context context){ super(context , DATABASE_NAME , null , VERSION); } @Override public void onCreate(SQLiteDatabase db){ db.execSQL("create table " + CrimeTable.NAME + "(" + "_id integer primary key autoincrement ," + CrimeTable.Cols.UUID + "," + CrimeTable.Cols.TITLE + "," + CrimeTable.Cols.DATE + "," + CrimeTable.Cols.SOLVED + ")" ); } @Override public void onUpgrade(SQLiteDatabase db , int oldVersion , int newVersion){ } }
通过这些代码与逻辑的整理,这款App的界面功能还能更强大哦
:
是不是很靓眼,最后祝大家在代码编写的途中都可以持之以恒,未来很美好,要努力哦!