第二个项目CriminalIntent应用开发阶段总结(一)

第二个项目CriminalIntent应用开发阶段总结(一)

fragment的使用

采用fragment而不是activity来管理应用UI,可绕开Android系统activity使用规则的限制。fragment必须依赖activity使用,fragment是一种控制器对象,activity可委派它执行任务。

  • 创建fragment容器布局
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fragment_container">
</FrameLayout>
  • 定义用户界面布局文件
<TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_title_label"/>

    <EditText
        android:id="@+id/crime_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/crime_title_hint"/>

    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_details_label"/>

    <Button
        android:id="@+id/crime_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="80dp"/>

    <CheckBox
        android:id="@+id/crime_solved"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_solved_label"/>
  • 创建fragment类并设置其视图为定义的布局
//继承Fragment类
public class CrimeFragment extends Fragment{}
//覆盖Fragment.onCreate(Bundle)方法
private Crime mCrime;
@Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
   }
//覆盖onCreateView(...)方法
@Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
          Bundle savedInstanceState){
       View v = inflater.inflate(R.layout.fragment_crime,container,false);
       return v;
  }
  • 实例化组件
//生成并使用EditText组件
private EditText mTitleField;
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
            }
        });
//设置Button文字
private Button mDateButton;
mDateButton = (Button) v.findViewById(R.id.crime_date);
mDateButton.setText(mCrime.getDate().toString());
mDateButton.setEnabled(false);
//监听CheckBox的变化
private CheckBox mSolvedCheckBox;
mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
mSolvedCheckBox.setOnCheckedChangeListener(
    new CompoundButton.OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(
            CompoundButton buttonView, boolean isChecked) {
             mCrime.setSolved(isChecked);
         }
     });
  • 向FragmentManager添加UI fragment
//获取FragmentManager
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == null){
            fragment = createFragment();
            fm.beginTransaction()
                    .add(R.id.fragment_container,fragment)
                    .commit();
        }

fragment的生命周期

fragment的生命周期类似于activity的生命周期,它具有停止,暂停以及运行状态,也拥有可以覆盖的方法,用来在关键节点完成一些任务。

fragment生命周期与activity生命周期的一个关键区别就在于,fragment的生命周期方法由托管activity而不是操作系统调用。

RecyclerView显示列表

单例

crime数组对象将存储在一个单例里。单例是特殊的java类,在创建实例时,一个单例类仅允许创建一个实例。应用能在内存里活多久,单例就能活多久。因此将对象列表保存在单例里的话,就能随时获取crime数据,不管activity和fragment的生命周期怎么变化。

//创建单例
public class CrimeLab {
    private static CrimeLab sCrimeLab;
    public static CrimeLab get(Context context) {
    if (sCrimeLab == null){
        sCrimeLab = new CrimeLab(context);
        }
    return sCrimeLab;
    }
    private CrimeLab(Context context){}
}
//创建可容纳Crime对象的List
private List<Crime> mCrimes;
mCrimes = new ArrayList<>();
public List<Crime> getCrimes() {
        return mCrimes;
    }
    public Crime getCrime(UUID id){
        for (Crime crime:mCrimes){
            if (crime.getId().equals(id)){
                return crime;
            }
        }
        return null;
    }

RecyclerView,ViewHolder和Adapter

RecyclerView是ViewGroup的子类,每一个列表项都是作为一个View子对象显示的。RecyclerView只创建刚好充满屏幕的View,而不是100个。用户滑动屏幕切换视图时,上一个视图会回收利用。

  • ViewHolder和Adapter
    RecyclerView的任务仅限于回收和定位屏幕上的View。列表项View能够显示数据还离不开另外两个类的支持:ViewHolder子类和Adapter子类。

    ViewHolder只做一件事:容纳View视图

    Adapter是一个控制器对象,从模型层获取数据,然后提供给RecyclerView显示,是沟通的桥梁。

  • 使用RecyclerView

//在布局文件中添加RecyclerView视图
<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">
</android.support.v7.widget.RecyclerView>
//为CrimeListFragment配置视图
private RecyclerView mCrimeRecyclerView;
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(getContext()));
        return view;
    }
  • 实现ViewHolder和Adapter
//定义ViewHolder内部类
private class CrimeHolder extends RecyclerView.ViewHolder{
    public CrimeHolder(LayoutInflater inflater,ViewGroup parent) {
        super(inflater.inflate(R.layout.list_item_crime,parent,false));
      }
    }
//创建Adapter内部类
private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder>{
          private List<Crime> mCrimes;

          public CrimeAdapter(List<Crime> crimes){
              mCrimes = crimes;
          }
    }
//武装CrimeAdapter
@Override
            public CrimeHolder onCreateViewHolder(ViewGroup parent,int viewType){
                LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
                return new CrimeHolder(layoutInflater,parent);
            }

            @Override
            public void onBindViewHolder(CrimeHolder holder,int position){
                Crime crime = mCrimes.get(position);
                holder.bind(crime);

            }

            @Override
            public int getItemCount(){
                return mCrimes.size();
            }
//设置Adapter
private CrimeAdapter mAdapter;
updareUI();
private void updareUI() {
       CrimeLab crimeLab = CrimeLab.get(getActivity());
       List<Crime> crimes = crimeLab.getCrimes();

       if (mAdapter == null){
           mAdapter = new CrimeAdapter(crimes);
           mCrimeRecyclerView.setAdapter(mAdapter);
       }else {
           mAdapter.notifyDataSetChanged();
       }
       updateSubtitle();
   }
  • 绑定列表项
//在构造方法中实例化视图组件
private TextView mTitleTextView;
private TextView mDateTextView;
mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
//实现bind(Crime)方法
private Crime mCrime;
public void bind(Crime crime){
    mCrime = crime;
    mTitleTextView.setText(mCrime.getTitle());
    mDateTextView.setText(mCrime.getDate().toString());
}
//调用bind(Crime)方法
@Override
public void onBindViewHolder(CrimeHolder holder,int position){
         Crime crime = mCrimes.get(position);
         holder.bind(crime);
     }
  • 响应点击
private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{}
itemView.setOnClickListener(this);

使用图形布局工具布局

图形布局工具界面的中间区域是布局的界面预览窗口。右边紧挨的是蓝图视图。它能显示各个组件视图的轮廓。可以看出各个组件视图的大小比例。

posted @ 2017-09-29 22:58  黄杰1234  阅读(331)  评论(0编辑  收藏  举报