Android开发5、6周——Criminallntent项目(二)

上接Android开发3、4周——Criminallntent项目

  第5、6周,继续Criminalintent项目的开发。上次写到图形界面,用布局与组件创建了用户界面。这次开始使用ViewPager,对话框,工具栏和数据库。

使用ViewPager

  布局示意图如图所示:

  其中使用了CrimePagerActivity的新建Activity取代了CrimeActivity。CrimePagerActivity的布局由一个ViewPager组成。

ViewPager与PagerAdapter

  ViewPager在某种程度上类似于RecyclerView。RecyclerView需借助于Adapter提供视图。同样地,ViewPager也需要PagerAdapter的支持。

  FragmentStatePagerAdapter化繁为简,提供了两个有用的方法:getCount()和getItem(int)。调用getItem(int)方法,获取并显示crime数组中指定位置的crime时,它会返回配置过的CrimeFragment来完成显示任务。

代码如下:

复制代码
mViewPager = (ViewPager) findViewById(R.id.activity_crime_pager_view_pager);
        mCrimes = CrimeLab.get(this).getCrimes();
        FragmentManager fragmentManager = getSupportFragmentManager();
        mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
            @Override
            public Fragment getItem(int position) {
                Crime crime = mCrimes.get(position);
                return CrimeFragment.newInstance(crime.getmId());
            }
            @Override
            public int getCount() {
                return mCrimes.size();
            }
        });
复制代码

FragmentStatePagerAdapter与FragmentPagerAdapter

  FragmentPagerAdapter是另外一种可用的PagerAdapter,其用法与FragmentStatePagerAdapter基本一致。唯一的区别在于:卸载不再需要的fragment时,各自采用的处理方法有所不同。

  FragmentStatePagerAdapter会销毁不需要的fragment。事务提交后,activity的FragmentManager中的fragment会被彻底移除。

       FragmentStatePagerAdapter类名中的“state”表明:在销毁fragment时,可在onSaveInstanceState(Bundle)方法中保存fragment的Bundle信息。用户切换回来时,保存的实例状态可用来恢复生成新的fragment。

如图所示:

  相比之下,FragmentPagerAdapter有不同的做法。对于不再需要的fragment,FragmentPagerAdapter会选择调用事务的detach(Fragment)方法来处理它,而非remove(Fragment)方法。

       也就是说,FragmentPagerAdapter只是销毁了fragment的视图,fragment实例还保留在FragmentManager中。因此,FragmentPagerAdapter创建的fragment永远不会被销毁。

如图所示:

对话框

  对话框是AlertDialog类的一个实例。实际开发中,AlertDialog类是个常用的多用途Dialog子类。

  要使用对话框要先使用AppCompat兼容库,要使用兼容库就要先添加为依赖库,这取决于项目创建的方式。

  打开项目结构窗口(File → Project Structure...),选择app模块并点击Dependencies选项页。如果看不到AppCompat,请点击+按钮,然后从依赖项列表中选择appcompat-v7完成添加。

选择内容如图所示:

  这里注意,使用的是android.support.v7.app.AlertDialog。

  各个对象之间的关系如图所示:

fragment间的数据传递

  CrimeFragment和DatePickerFragment之间的数据传递如图所示:

  为了返回新日期给CrimeFragment,并更新模型层以及对应视图,需将日期打包为extra并附加到Intent上,然后调用CrimeFragment.onActivityResult(...)方法,并传入准备好的Intent参数。

如图所示:

  

  要传递crime记录日期给DatePickerFragment,需将它保存在DatePickerFragment的argumentbundle中。这样,DatePickerFragment便可直接获取到它。

代码如下:

复制代码
private static final String ARG_DATE = "date";
private DatePicker mDatePicker;
public static DatePickerFragment newInstance(Date date) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_DATE,date);
        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setArguments(args);
        return fragment;
    }
复制代码

工具栏

  在上面已经添加过AppCompat依赖项,这里我们要完全整合AppCompat库。

  先要使用AppCompat主题,在res/values/styles.xml中修改代码。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

  并且在res/values/string.xml中添加字符串资源。

<string name="new_crime">New Crime</string>
    <string name="show_subtitle">Show Subtitle</string>
    <string name="hide_subtitle">Hide Subtitle</string>
    <string name="subtitle_format">%1$d crimes</string>

  在XML文件中定义菜单。在项目工具窗口中,右键单击res目录,选择New → Android resource file菜单项。在弹出的窗口界面,选择Menu资源类型,并命名资源文件为fragment_crime_list,点击OK按钮确认。

如图所示:

  在新建的文件中,加入的代码如下:

xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_item_new_crime"
        android:icon="@drawable/ic_menu_add"
        android:title="@string/new_crime"
        app:showAsAction="ifRoom|withText"/>

  层级导航的工作原理如图所示:

SQLite数据库

  首先要定义Schema,创建CrimeDbSchema.java类,加入代码如下:

复制代码
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";
            public static final String SUSPECT = "suspect";
        }
    }
}
复制代码

  然后创建数据库,创建CrimeBaseHelper.java类,加入代码如下:

复制代码
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 + "," + CrimeTable.Cols.SUSPECT + ")");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
复制代码

  编写SQL创建初始代码的时候,需要导入Add import for ‘com.bignerdranch.android.criminalintent.database.CrimeDbSchema.CrimeTable’可选项。

如图所示:

  然后Android Studio会自动导语句:

import database.CrimeDbSchema.CrimeDbSchema.CrimeTable;
posted @ 2017-10-15 20:57  隰桑有糖  阅读(260)  评论(0编辑  收藏  举报