Android编程权威指南(第三版)第8章挑战练习

写在前面:


欢迎所有人给我提出任何意见和建议
请注意每一次的程序都是没有承接之前的挑战练习
如果有疑问或者意见的可以在下方评论
谢谢!

由于不经常上线,此处留下我的QQ:623614154 欢迎共同探讨问题


下载区:

第8章挑战练习–>Link
后续还有其他方式提供没有积分的小伙伴下载


目录


挑战练习8.8:RecyclerView ViewType

请在RecyclerView中创建两类列表项:一般性crime,以及需警方介入的crime。
要完成这个挑战,你需要用到RecyclerView.Adapter的视图类别功能(view type)。在Crime对象里,再添加一个mRequiresPolice实例变量,使用它并借助getItemViewType(int)方法
(developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#getItemViewType(int)),确定该加载哪个视图到CrimeAdapter。
在onCreateViewHolder(ViewGroup, int)方法里,基于getItemViewType(int)方法返
回的viewType值,需要返回不同的ViewHolder。如果是一般性crime,就仍然使用原始布局;如果是需警方介入的crime,就使用一个带联系警方按钮的新布局。

  • 题目太长,不想看的话,简单解释,就是部分需要警方介入的罪犯,给一个按钮报警。

step 1:添加list_item_police_crime.xml

  • 此举是为了添加一个新的布局,预览图长这样↓(可以自己命名,但是要对应上)
  • 代码list_item_police_crime.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:orientation="horizontal">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_weight="7">
        <TextView
            android:id="@+id/crime_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Crime Title"
            />
        <TextView
            android:id="@+id/crime_date"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Crime Date"/>
    </LinearLayout>
    <Button

        android:id="@+id/call_police"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="40dp"
        android:padding="0dp"
        android:layout_marginTop="0dp"
        android:text="联系警察"/>
</android.support.v7.widget.LinearLayoutCompat>

step 2:Crime中添加变量mRequiresPolice

  • 如题目所讲的,加入mRequiresPolice,当一个罪犯需要警察的时候,这个变量设置为True
  • 代码Crime.java
public class Crime {

private boolean mRequiresPolice;//按要求加入变量标记需要警察的
...
    public void setSolved(boolean solved) {
        mSolved = solved;
    }

    //下面加入get/set方法
    public void setRequiresPolice(boolean requiresPolice) {
        mRequiresPolice = requiresPolice;
    }

    public boolean isRequiresPolice() {
        return mRequiresPolice;
    }
}

step 3:初始化设置需要警察的Crime

  • 既然加入了变量,就应该初始化。此处设置所有偶数个的Crime都需要警察(可以不一样,测试到就可以)。
  • 代码CrimeLab.java
private CrimeLab(Context context){
    mCrimes = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        Crime crime = new Crime();
        crime.setTitle("Crime #" + i);
        crime.setSolved(i % 2 == 0); 
        //第偶数个Crime设置为True
        if(i % 2 == 0)
            crime.setRequiresPolice(true);
        else
            crime.setRequiresPolice(false);
        mCrimes.add(crime);
    }
}

step 4:创建一个新的Holder—PoliceHolder

  • 在CrimeListFragment里面新建一个Holder内部类,容纳新的布局,名字可以自己取。
  • 代码CrimeListFragment.java
/**
 * 新建一个内部类,类似CrimeHolder
 */
private class PoliceHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    private TextView mTitleTextView;
    private TextView mDateTextView;
    private Crime mCrime;
    private Button mCallPolice;

    public PoliceHolder(LayoutInflater inflater, ViewGroup parent) {

        super(inflater.inflate(R.layout.list_item_police_crime, parent, false));
        itemView.setOnClickListener(this);
        mTitleTextView = (TextView)itemView.findViewById(R.id.crime_title);
        mDateTextView = (TextView)itemView.findViewById(R.id.crime_date);
        //绑定按钮
        mCallPolice = (Button)itemView.findViewById(R.id.call_police);
        //点击的时候显示一段文字
        mCallPolice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getActivity(),"已经联系了警察了",Toast.LENGTH_SHORT).show();
            }
        });
    }


    @Override
    public void onClick(View view) {
        Toast.makeText(getActivity(),mCrime.getTitle() + " clicked!", Toast.LENGTH_SHORT).show();
    }

    public void bind(Crime crime){
        mCrime = crime;
        mTitleTextView.setText(mCrime.getTitle());
        mDateTextView.setText(mCrime.getDate().toString());
    }
}

step 5:利用ViewType判断显示不同布局

  • 1. 为了显示不同的布局,首先要判断当前罪犯是否需要警察,所以要isRequiresPolice()检查,如果True那么就是需要的,返回1,否则返回0。
  • 代码CrimeListFragment
private class CrimeAdapter extends RecyclerView.Adapter {
    ...
    /**
    *
    * @param position
    * @return 返回 1 说明设置了这个罪犯是要警察才行,对应crime里面的是mRequiresPolice==True
    *         返回 0 说明设置了这个罪犯是不需要警察,对应crime里面的是mRequriesPolice==false
    */
    @Override
    public int getItemViewType(int position) {
       if(mCrimes.get(position).isRequiresPolice() == true){
           return 1;
       }
       else{
           return 0;
       }
    }
    ...
}
  • 2. 将不同crime绑定对应的holder
  • 代码CrimeListFragment
private class CrimeAdapter extends RecyclerView.Adapter {
...
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            Crime crime = mCrimes.get(position);
            //得到ViewType 绑定不同的holder
            if(this.getItemViewType(position) == 1) {
                ((PoliceHolder)holder).bind(crime);
            }
            else{
                ((CrimeHolder)holder).bind(crime);
            }

        }
}

step 6:最重要的一步,根据不同的ViewType新建不同Holder实例

  • 这里要将返回类型改为更加通用的RecyclerView.ViewHolder,不能是CrimeHolder了,因为你不确定用哪一个holder显示
  • 代码
private class CrimeAdapter extends RecyclerView.Adapter {
    ...
    /**
     *
     * @return 返回类型改为RecyclerView.ViewHolder
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        //根据getViewType函数里面的设置的viewType的值,调用不同的holder
        if(viewType == 1){
            return new PoliceHolder(layoutInflater, parent);
        }
        else{
            return new CrimeHolder(layoutInflater, parent);
        }
    }
    @Override
    public int getItemCount() {
        return mCrimes.size();
    }
}

结果

  • 我在step3中,设置的第偶数个罪犯是需要联系警察的,所以可以看到,最终结果如下
    挑战练习8.8
  • 点击联系警察按钮会弹出Toast,That’s It 结束了。
    挑战练习8.8

猜你喜欢

转载自blog.csdn.net/lo_heng/article/details/80208455