Blog of CodeJELLOW’S ENGINEERING NOTES
← 返回文章

Java安卓学习总结(十七)

Java安卓学习总结(十七)第十三章 工具栏

本文目录 ⌄
  1. 第十三章 工具栏

第十三章 工具栏

有关工具栏菜单

定义资源

在XML中创建菜单资源,资源类型是Menu,且这个资源处于一个新的命名空间res\menu中。其中可以用Android Asset Studio来根据系统资源来创建自己想要的资源目标。

创建菜单

要用到三个方法。

TEXT
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
}
public boolean onOptionsItemSelected(MenuItem item)

第一个方法是绑定视图资源;第二个是让这个Fragment接受调用菜单栏的指令;第三个是响应菜单项的选择事件。

有关实现层级式导航

层级式导航就是规定一个activity有一个上级activity,只要点击工具栏左边的按钮就可以向上导航。定义上层activity是在AndroidMainfest.xml添加android:parentActivityName:

TEXT
<activity android:name=".CrimePagerActivity"
    android:parentActivityName=".CrimeListActivity"></activity>

有关可选菜单项(次标题)

过程大致上和创建第一个菜单的相同。其中用到这样几个方法:

设置次标题

TEXT
AppCompatActivity activity=(AppCompatActivity) getActivity();activity.getSupportActionBar().setSubtitle(subtitle);

重建OptionsMenu

TEXT
invalidateOptionsMenu();

这个方法的作用是使原填充的菜单项无效,当用户再次访问菜单时,再次调用onCreateOptionsMenu(Menu menu)。此外还有一个onPrepareOptionsMenu()方法,可以看这里。

更新菜单项

这一步是使得菜单项的名称发送改变。

TEXT
MenuItem subtitleItem=menu.findItem(R.id.show_subtitle);if (mSubtitleVisible){    subtitleItem.setTitle(R.string.hide_subtitle);}else{    subtitleItem.setTitle(R.string.show_subtitle);}

有关挑战练习 删除crime记录

过程和新建一个crime差不多,要在crimeLab中新建一个delete方法。onOptionsItemSelected内对应的代码是

TEXT
case R.id.delete_crime:

    CrimeLab crimeLab=CrimeLab.get(getActivity());
    crimeLab.deleteCrime(mCrime);
    getActivity().finish();
    return true;

由于之前用hashMap优化过crime的查询方式,所以crimeLab.add()和delete()方法都要对其hashMap进行即是更新,否则会导致查询不到或下标越界的错误。

当我创建了多个crime时删除非最后一个,程序就会崩溃

TEXT
 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{1006c628 position=1 id=-1, oldPos=1, pLpos:-1 scrap tmpDetached no parent}

原因是最后一个crime的View Holder的位置和Adapter不匹配,导致RecyclerView出现了问题。上网查询之后找到了解决方法。

我用的是第一个方法,写了LinearLayoutManager的继承类。

TEXT
class WrapContentLinearLayoutManager extends LinearLayoutManager {


    public WrapContentLinearLayoutManager(Context context) {
        super(context);
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }
}
...
mCrimeRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getActivity()));

很迷为什么只要继承一下之后就可以用了。

有关挑战练习 复数字符串资源

这么样定义字符串:

TEXT
<plurals name="subtitle_plurals">    <item quantity="one">%1$d crime</item>    <item quantity="zero">%1$d crime</item>    <item quantity="other">%1$d crime</item></plurals>

这样调用:

TEXT
int crimeCount=crimeLab.getCrimes().size();String subtitle=getResources().getQuantityString(R.plurals.subtitle_plurals,crimeCount,crimeCount,crimeCount);

其中第二个参数开始每一个都对应第一种的每一行。

有关挑战练习 用于RecyclerView的空视图

我总感觉我写的做法不是题目要求的,但是效果是实现了。

在一个视图资源文件中包含recyclerView和空视图,在onCreateView中分别绑定。在空视图里的按钮设置监听器以创建新crime。

TEXT
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState)
{

    View view=inflater.inflate(R.layout.fragment_crime_list,container,false);

    mCrimeRecyclerView=(RecyclerView)view.findViewById(R.id.crime_recycler_view);
    mCrimeRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getActivity()));

    mDefaultLayoutView=(LinearLayout) view.findViewById(R.id.default_layout_view);
    mDefaultButton=(Button)view.findViewById(R.id.default_button);
    mDefaultButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Crime crime=new Crime();
            CrimeLab.get(getActivity()).addCrime(crime);
            Intent intent=CrimePagerActivity.newIntent(getActivity(),crime.getId());
            startActivity(intent);

        }
    });
    ...
    return view;
}

这两个视图只能二选一地显示,所以在onResume()中根据当前已经有的crime数量来选择使用哪一个。

TEXT
@Overridepublic void onResume() {    super.onResume();    if (CrimeLab.get(getActivity()).getCrimes().size()==0)    {        mCrimeRecyclerView.setVisibility(View.GONE);        mDefaultLayoutView.setVisibility(View.VISIBLE);    }    else    {        mCrimeRecyclerView.setVisibility(View.VISIBLE);        mDefaultLayoutView.setVisibility(View.GONE);        updateUI();    }}

效果应该是实现了。

通过 RSS 订阅更新 →