RecycleView无法正确显示?

问题描述 投票:1回答:2

我正在关注Big Nerd Ranch Guide(2015年版)。我们从片段开始。本章介绍了RecycleView

目标是使用Crime显示100个RecycleView,如下所示:enter image description here

作者正在使用Crime作为数据对象(带有字段:id,标题,已解决,日期)。

我们有一个称为Activity的超类SingleFragmentActivity

    public abstract class SingleFragmentActivity extends FragmentActivity {

    protected abstract Fragment createFragment();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment); //container for different fragments...

        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();
        }
    }
}

伴随布局(如您在SingleFragmentActivity中看到的是fragment_container.xml:]

<?xml version="1.0" encoding="utf-8"?>
<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" />

然后我们有一个子类,称为CrimeListActivity

public class CrimeListActivity extends SingleFragmentActivity {
    @Override
    protected Fragment createFragment() {
        return new CrimeListFragment();
    }
}

CrimeListFragment是一个具有ViewHolderAdapter所需的内部类RecycleView的片段,以创建必要的Views并对其进行回收。

public class CrimeListFragment extends Fragment {
    private RecyclerView mCrimeRecyclerView;
    private CrimeAdapter mAdapter;

    @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()));

        updateUI();

        return view;
    }

    private void updateUI() {
        CrimeLab crimeLab = CrimeLab.get(getActivity());
        List<Crime> crimes = crimeLab.getCrimes();
        mAdapter = new CrimeAdapter(crimes);
        mCrimeRecyclerView.setAdapter(mAdapter);
    }

    private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private Crime mCrime;
        private TextView mTitleTextView;
        private TextView mDateTextView;
        private CheckBox mSolvedCheckBox;

        public CrimeHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            mTitleTextView = (TextView)
                    itemView.findViewById(R.id.list_item_crime_title_text_view);
            mDateTextView = (TextView)
                    itemView.findViewById(R.id.list_item_crime_date_text_view);
            mSolvedCheckBox = (CheckBox)
                    itemView.findViewById(R.id.list_item_crime_solved_check_box);
        }

        public void bindCrime(Crime crime) {
            mCrime = crime;
            mTitleTextView.setText(mCrime.getTitle());
            mDateTextView.setText(mCrime.getDate().toString());
            mSolvedCheckBox.setChecked(mCrime.isSolved());
        }

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

    private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {
        private List<Crime> mCrimes;
        public CrimeAdapter(List<Crime> crimes) {
            mCrimes = crimes;
        }
        @Override
        public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            /*onCreateViewHolder is called by the RecyclerView when it needs a new View to display an item. In
            this method, you create the View and wrap it in a ViewHolder. The RecyclerView does not expect that
            you will hook it up to any data yet.
            For the View, you inflate a layout from the Android standard library called simple_list_item_1. This
            layout contains a single TextView, styled to look nice in a list. Later in the chapter, you will make a
            more advanced View for the list items*/
            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());

            View view = layoutInflater.inflate(R.layout.list_item_crime, parent, false);

            return new CrimeHolder(view);

        }
        @Override
        public void onBindViewHolder(CrimeHolder holder, int position) {
            /*onBindViewHolder: This method will bind a ViewHolder’s View to your model object. It receives
            the ViewHolder and a position in your data set. To bind your View, you use that position to find the
            right model data. Then you update the View to reflect that model data.
            In your implementation, that position is the index of the Crime in your array. Once you pull it out, you
            bind that Crime to your View by sending its title to your ViewHolder’s TextView.*/
            Crime crime = mCrimes.get(position);
            holder.bindCrime(crime);
        }
        @Override
        public int getItemCount() {
            return mCrimes.size();
        }
    }




}

此片段的伴随布局自然是XML格式的RecycleView,名为fragment_crime_list.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.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"/>

[最后,以ViewItem绑定数据的实际Adapter形式为两个TextViews(一个为Crime的日期,一个为Crime的标题)和一个CheckBox标记已解决犯罪。

它名为list_item_crime.xml,看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <CheckBox
        android:id="@+id/list_item_crime_solved_check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:padding="4dp"/>

    <TextView
        android:id="@+id/list_item_crime_title_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/list_item_crime_solved_check_box"
        android:textStyle="bold"
        android:padding="4dp"
        tools:text="Crime Title"/>

    <TextView
        android:id="@+id/list_item_crime_date_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/list_item_crime_solved_check_box"
        android:layout_below="@id/list_item_crime_title_text_view"
        android:padding="4dp"
        tools:text="Crime Date"/>

</RelativeLayout>

现在,这是书中的内容,我仔细检查了所有内容,希望我不会错过任何事情。我的Crime项目仅出现在屏幕顶部,我需要向下滚动到屏幕底部,并且仅显示第二个Crime项目。像这样:

enter image description here

有人知道我在这里想念什么吗?我过去三天一直在寻找解决方案。其实问这是我最后的希望:)

android android-fragments android-recyclerview recycler-adapter android-viewholder
2个回答
4
投票

这个问题很难解决。仔细看看您的list_item_crime.xml文件。特别是在这一行:

android:layout_height="match_parent"

您将单个项目的高度设置为整个可用高度。如果尝试滚动,则应该看到下面的其他项目占据相同的高度。简单修复,更改为:

android:layout_height="wrap_content"

[当我刚开始使用Android时,我讨厌RecyclerView,因为它有很多问题。这不止一次发生在我身上:-)


1
投票

没有足够的时间来阅读所有这些内容,但我认为将recyclerview list_item_crime.xml的viewholder的父布局高度设置为wrap_content

即类似这样的东西

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <CheckBox
        android:id="@+id/list_ite.....
© www.soinside.com 2019 - 2024. All rights reserved.