Android开发34周——Criminallntent项目

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发34周——Criminallntent项目相关的知识,希望对你有一定的参考价值。

CriminalIntent项目开发

1.fragment的引入

采用fragment而不是activity来管理应用UI,可绕开android系统activity使用规则的限制。

fragment是一种控制器对象,activity可委派它完成一些任务。

这些任务通常就是管理用户界面。受管的用户界面可以是一整屏或是整屏的一部分。管理用户界面的fragment又称为UI fragment。

它自己也有产生于布局文件的视图。fragment视图包含了用户可以交互的可视化UI元素。

利用fragment,可轻松实现选择不同的列表项就显示对应的明细视图Activity负责以一个明细fragment替换另一个明细fragment,如图1.1所示。

这样,视图切换的过程中,就不用销毁activity了。

技术分享

                                                                                         图1.1

2.fragment与支持库

我们要用到两个重要的支持库类,一个是Fragment类( android.support.v4.app.Fragment )。

另一个是FragmentActivity类( android.support.v4.app.Fragment- Activity )。

使用fragment的前提是:activity知道如何管理fragment、FragmentActivity类知道如何管理支持版本的fragment。

3.定义容器视图

创建fragment容器布局(activity_crime.xml)如下

<
FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />

4.定义CrimeFragment布局

CrimeFragment视图将显示包含在Crime类实例中的信息。

该布局包括一个垂直LinearLayout布局(含有一个EditText组件)。

EditText组件有一块区域,可供用户添加或编辑文字信息。

fragment视图的布局文件(fragment_crime.xml)如下

技术分享
<
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <
EditText android:id="@+id/crime_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/crime_title_hint" /> </LinearLayout>
技术分享

5.创建CrimeFragment类

继承Fragment类(CrimeFragment.java)如下

public class CrimeFragment extends Fragment {
}

修改代码继承Fragment类时 ,我们需要选择Fragment(android.support.v4.app)包

6.实现fragment生命周期

覆盖Fragment.onCreate(Bundle)方法(CrimeFragment.java)如下

技术分享
public class CrimeFragment extends Fragment {
private Crime mCrime;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrime = new Crime();
}
}
技术分享

Fragment.onCreate(Bundle)是公共方法,而Activity.onCreate(Bundle)是保护方法。

这是因为只有Fragment.onCreate(...)方法及其他Fragment生命周期方法是公共方法,托管fragment的activity才能调用它们。

7.覆盖onCreateView(...)方法(CrimeFragment.java)如下

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_crime, container, false);
return v;
}

在onCreateView(...)方法中,fragment的视图是直接通过调用LayoutInflater.inflate(...)方法并传入布局的资源ID生成的。

第二个参数是视图的父视图,因为我们通常需要父视图来正确配置组件。

第三个参数告知布局生成器是否将生成的视图添加给父视图(这里,我们传入了false参数,因为我们将以activity代码的方式添加视图。)

8.在fragment中关联组件

生成并使用EditText组件(CrimeFragment.java)如下

public class CrimeFragment extends Fragment {
private Crime mCrime;
private EditText mTitleField;
技术分享
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
  View v = inflater.inflate(R.layout.fragment_crime, container, false);
  mTitleField = (EditText)v.findViewById(R.id.crime_title);
  mTitleField.addTextChangedListener(new TextWatcher() {
  @Override
  public void beforeTextChanged(
  CharSequence s, int start, int count, int after) {
  // This space intentionally left blank
}
@Override
public void onTextChanged(
CharSequence s, int start, int before, int count) {
mCrime.setTitle(s.toString());
}

@Override
public void afterTextChanged(Editable s) {
// This one too
}
});
return v;
}
}
技术分享

Fragment.onCreateView(...)方法中的组件引用几乎等同于Activity.onCreate(...)方法的处理。唯一的区别是我们调用了fragment视图的View.findViewById(int)方法。

9.添加UI fragment到FragmentManager

FragmentManager 类具体管理的是:

? fragment队列;

? fragment事务回退栈。

获取FragmentManager(CrimeActivity.java)如下

FragmentManager fm = getSupportFragmentManager();

添加一个CrimeFragment(CrimeActivity.java)如下

技术分享
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = new CrimeFragment();
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
技术分享

fragment事务被用来添加、移除、附加、分离或替换fragment队列中的fragment。这是使用fragment在运行时组装和重新组装用户界面的关键。

FragmentManager管理着fragment事务回退栈。

10.使用布局与组件创建用户界面

打开Crime.java文件,新增两个实例变量。

Date变量表示crime发生的时间,boolean变量表示crime是否已得到处理。

添加更多变量(Crime.java)如下

private Date mDate;
private boolean mSolved;
public Crime() {
mId = UUID.randomUUID();
mDate = new Date();
}

添加新组件(fragment_crime.xml)如下

为CrimeFragment的布局添加四个组件:两个TextView组件、一个Button组件以及一个CheckBox组件

技术分享
<
TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_title_label" style="?android:listSeparatorTextViewStyle" /> <
EditText android:id="@+id/crime_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:hint="@string/crime_title_hint" /> <
TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/crime_details_label" style="?android:listSeparatorTextViewStyle" /> <
Button android:id="@+id/crime_date" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" /> <CheckBox android:id="@+id/crime_solved" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:text="@string/crime_solved_label" />
技术分享

添加字符串资源(strings.xml)如下

<string name="crime_title_label">Title</string>
<string name="crime_details_label">Details</string>
<string name="crime_solved_label">Solved</string>

添加组件实例变量(CrimeFragment.java)如下

接下来,要让CheckBox显示Crime是否已得到处理。用户勾选清除CheckBox时,Crime的mSolved变量的状态值也需得到相应的更新。

private Button mDateButton;
private CheckBox mSolvedCheckBox;

设置Button上的文字显示(CrimeFragment.java)如下

mDateButton = (Button)v.findViewById(R.id.crime_date);
mDateButton.setText(mCrime.getDate().toString());
mDateButton.setEnabled(false);

禁用按钮可以确保它不响应用户的单击事件。禁用后,按钮的外观样式也会发生改变(变为灰色),表明它已处于禁用状态。

侦听CheckBox状态的变化(CrimeFragment.java)如下

技术分享
mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Set the crime‘s solved property
mCrime.setSolved(isChecked);
}
});
技术分享

创建OnCheckedChangeListener时需要导入android.widget.CompoundButton的包。

11.使用RecyclerView

首先要导入recyclerview-v7支持库

在布局文件中添加RecyclerView视图(fragment_crime_list.xml)如下

<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/crime_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

为CrimeListFragment配置视图(CrimeListFragment.java)如下

技术分享
private RecyclerView mCrimeRecyclerView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_crime_list, container, false);
mCrimeRecyclerView = (RecyclerView) view
.findViewById(R.id.crime_recycler_view);
mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return view;
}
技术分享

RecyclerView类的任务就是回收再利用以及定位屏幕上的TextView视图。

实际上,定位的任务被委托给了LayoutManager。

除了在屏幕上定位列表项,LayoutManager还负责定义屏幕滚动行为。

因此,没有LayoutManager,RecyclerView也就无法正常工作了。

12.从fragment中启动activity

在CrimeListFragment的CrimeHolder类里,用启动CrimeActivity实例的代码,替换Toast消息处理代码。

启动CrimeActivity(CrimeListFragment.java)如下

Intent intent = new Intent(getActivity(), CrimeActivity.class);
startActivity(intent);

13.使用ViewPager

为UI添加ViewPager后,用户可滑动屏幕,切换查看不同列表项的明细页面。

创建ViewPager(CrimePagerActivity.java)如下

技术分享
public class CrimePagerActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crime_pager);
}
}
技术分享

注意:必须使用ViewPager的包名全称(android.support.v4.view.ViewPager)。如图13.1所示。

技术分享

 

                                                       图13.1

设置pager adapter(CrimePagerActivity.java)如下

技术分享
public class CrimePagerActivity extends FragmentActivity {
  private ViewPager mViewPager;
  private List<Crime> mCrimes;
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_crime_pager);
  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.getId());
  }
@Override
  public int getCount() {
return mCrimes.size();   } }); } }
技术分享

在activity视图中找到ViewPager后,我们从CrimeLab中(crime的List)获取数据集,然后获取activity的FragmentManager实例。

设置adapter为FragmentStatePagerAdapter的一个匿名实例。创建Fragment-StatePagerAdapter实例需要FragmentManager。

创建newIntent方法(CrimePagerActivity.java)如下

private static final String EXTRA_CRIME_ID =
"com.bignerdranch.android.criminalintent.crime_id";
public static Intent newIntent(Context packageContext, UUID crimeId) {
Intent intent = new Intent(packageContext, CrimePagerActivity.class);
intent.putExtra(EXTRA_CRIME_ID, crimeId);
return intent;
}
UUID crimeId = (UUID) getIntent()
.getSerializableExtra(EXTRA_CRIME_ID);

然后需要修改CrimeListFragment,使得用户单击某个列表项时,CrimeListFragment启动的是CrimePagerActivity实例。

配置启动CrimePagerActivity(CrimeListFragment.java)

Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getId());








以上是关于Android开发34周——Criminallntent项目的主要内容,如果未能解决你的问题,请参考以下文章

2017-08-014 第34周计划

第十二周总结

20189217 2018-2019-2 《移动平台开发实践》第10周学习总结

20165320 毕业设计 第一周总结

20189217 2018-2019-2 《移动平台开发实践》第6周学习总结

20172305 2017-2018-2 《程序设计与数据结构》第十一周学习总结