滚动后无序的RecycleView列表 [英] An unordered RecycleView list after scrolling

查看:71
本文介绍了滚动后无序的RecycleView列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用鼠标滚轮滚动此列表RecycleView,则列表中的项目看起来像是无序的. 我不明白为什么?

If I scroll this list RecycleView with the mouse wheel my items in the list look like unordered. I do not understand , why?

点击错误的项目来自RecycleView的新活动

我试图创建单独的类CrimeAdapter extends RecyclerView.Adapter<CrimeAdapter.CrimeHolder>class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener在单独的文件中,但我做对了. 不幸的是,我对此没有足够的经验.

I have tried to create the separate class CrimeAdapter extends RecyclerView.Adapter<CrimeAdapter.CrimeHolder> and class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener in the separate file, but I couldn't do it right. Unfornuntely, I do not have enough experience for this.

我不知道如何在方法public void onClick(View v)

Crime.java

package com.bignerdranch.android.criminalintent;

import java.util.Date;
import java.util.UUID;

public class Crime{

    private UUID mId;
    private String mTitle;
    private Date mDate;
    private boolean mSolved;
    private boolean mRequiresPolice;

    public Crime() {
        // Generate unique identifier
        this(UUID.randomUUID());
    }

    public Crime(UUID id) {
        mId = id;
        mDate = new Date();
    }

    public UUID getId() {
        return mId;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public Date getDate() {
        return mDate;
    }

    public void setDate(Date date) {
        mDate = date;
    }

    public boolean isSolved() {
        return mSolved;
    }

    public void setSolved(boolean solved) {
        mSolved = solved;
    }

    public boolean isRequiresPolice() {
        return mRequiresPolice;
    }

    public void setRequiresPolice(boolean requiresPolice) {
        mRequiresPolice = requiresPolice;
    }
}

CrimeLab.java

package com.bignerdranch.android.criminalintent;

import android.content.Context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;


public class CrimeLab {

    private static CrimeLab sCrimeLab;
    private List<Crime> mCrimes;

    public static CrimeLab get(Context context) {
        if (sCrimeLab == null) {
            sCrimeLab = new CrimeLab(context);
        }
        return sCrimeLab;
    }

    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); 
            if (i % 4 == 0 ) {crime.setRequiresPolice(true);}
            else {crime.setRequiresPolice(false);}
            mCrimes.add(crime);
        }

    }

    public List<Crime> getCrimes() {
        return mCrimes;
    }

    public  Crime getCrime(UUID id){

        for (Crime crime : mCrimes){
            int rez = id.compareTo(crime.getId());
            if (crime.getId().equals(id)){
                return crime;
            }
        }
        return null;
    }

}

CrimeListFragment.java

package com.bignerdranch.android.criminalintent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.LayoutRes;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Date;
import java.util.List;

public class CrimeListFragment extends Fragment {

    private static final int REQUEST_CRIME = 1;

    private static final int NOT_REQUIRES_POLICE = 0;
    private static final int REQUIRES_POLICE = 1;

    private RecyclerView mCrimeRecyclerView;
    private CrimeAdapter mAdapter;
    private TextView mTitleTextView;
    private TextView mDateTextView;
    private ImageView mSolvedImageView;
    private Button mButtonCallPolice;
    private Crime mCrime;
    private CharSequence mDateFormat;
    private  int layout;

    @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 class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {


         public CrimeHolder(int layout, LayoutInflater inflater, ViewGroup parent ) {


            super(inflater.inflate(layout, parent, false));

            mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
            mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
            mSolvedImageView = (ImageView) itemView.findViewById(R.id.crime_solved);

            if (itemView.findViewById(R.id.call_police)!=null) {
                mButtonCallPolice = (Button) itemView.findViewById(R.id.call_police);
            }

            itemView.setOnClickListener(this);
        }

        public void bind(Crime crime) {

            mCrime = crime;
            mTitleTextView.setText(mCrime.getTitle());
            mDateFormat = DateFormat.format("EEE, MMM dd, yyyy", mCrime.getDate());

            mDateTextView.setText(mDateFormat);
            mSolvedImageView.setVisibility(mCrime.isSolved() ? View.VISIBLE :
                    View.GONE);

            if(mCrime.isRequiresPolice()){
                mButtonCallPolice.setEnabled(true);
            }
        }

        @Override
        public void onClick(View view) {

            Intent intent = CrimePagerActivity.newIntent(getActivity(),
                    CrimeLab.get(requireActivity()).getCrimes().get((getAdapterPosition())).getId());

            startActivityForResult(intent, REQUEST_CRIME);
        }

    }

    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) {

            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());

            if (viewType==1) { layout =  R.layout.list_item_crime_police;}

            else {             layout =  R.layout.list_item_crime;       }

            return new CrimeHolder (layout, 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();
        }


        public int getItemViewType(int position) {

            Crime crime = mCrimes.get(position);

            return (crime.isRequiresPolice()) ? 1 : 0;

        }

    }


    @Override
    public void onResume() {
        super.onResume();
        updateUI();
    }

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

            mAdapter.notifyDataSetChanged();

        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == REQUEST_CRIME) {
            // Обработка результата
        }

    }

    public void returnResult() {
        getActivity().setResult(Activity.RESULT_OK, null);
    }

}

CrimePagerActivity.java

package com.bignerdranch.android.criminalintent;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;

import androidx.viewpager.widget.ViewPager;

import java.util.List;
import java.util.UUID;

public class CrimePagerActivity extends AppCompatActivity {

    private static final String EXTRA_CRIME_ID = "com.bignerdranch.android.criminalintent.crime_id";

    private ViewPager mViewPager;
    private List<Crime> mCrimes;
    MyAdapter mAdapter;

    public static Intent newIntent(Context packageContext, UUID crimeId) {
        Intent intent = new Intent(packageContext, CrimePagerActivity.class);
        intent.putExtra(EXTRA_CRIME_ID, crimeId);
        return intent;
    }

    @Override
    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime_pager);

        UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);

        mViewPager = (ViewPager) findViewById(R.id.crime_view_pager);

        mCrimes = CrimeLab.get(this).getCrimes();

        mAdapter = new MyAdapter(getSupportFragmentManager(),mCrimes);
        mViewPager.setAdapter(mAdapter);

        for (int i = 0; i < mCrimes.size(); i++) {
            if (mCrimes.get(i).getId().equals(crimeId)) {
                mViewPager.setCurrentItem(i);
                break;
            }
        }

    }

    public static class MyAdapter extends FragmentStatePagerAdapter {

        private List<Crime> mCrimesCopy;

        public MyAdapter(FragmentManager fm, List<Crime> mCrimesParametr) {
            //super(fm);
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            this.mCrimesCopy = mCrimesParametr;

        }

        @Override
        public int getCount() {
            return mCrimesCopy.size();
        }

        @Override
        public Fragment getItem(int position) {
            Crime crime = mCrimesCopy.get(position);
            return CrimeFragment.newInstance(crime.getId());
        }
    }
}

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"/>

fragment_crime.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:orientation="vertical">
    <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"
        android:inputType=""
        android:autofillHints="" />
    <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"/>
    <CheckBox
        android:id="@+id/crime_solved"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_solved_label"/>
</LinearLayout>

list_item_crime_police.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/crime_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:text="@string/crime_title"
        android:textColor="@android:color/black"
        android:textSize="18sp"
        app:layout_constraintEnd_toStartOf="@+id/crime_solved"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/crime_date"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="@string/crime_date"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/crime_solved" />

    <Button
        android:id="@+id/call_police"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="@string/call_police"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/crime_date" />

    <ImageView
        android:id="@+id/crime_solved"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        android:contentDescription="@string/todo"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_solved" />

</androidx.constraintlayout.widget.ConstraintLayout>

list_item_crime.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

        <TextView
            android:id="@+id/crime_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:text="@string/crime_title"
            android:textColor="@android:color/black"
            android:textSize="18sp"
            app:layout_constraintEnd_toStartOf="@+id/crime_solved"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/crime_date"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:text="@string/crime_date"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/crime_solved" />

        <ImageView
            android:id="@+id/crime_solved"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_solved"
            android:contentDescription="@string/todo" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_crime_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/crime_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</androidx.viewpager.widget.ViewPager>

activity_fragment.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" />

推荐答案

我认为RecyclerView中的项目是无序的,因为在list_item_crime_police.xmllist_item_crime.xml布局文件中存在的对views的引用是声明为CrimeListFragment的类成员,而不在CrimeHolder类中声明为:

I think the items in the RecyclerView are unordered because the references for views which are present in your list_item_crime_police.xml or list_item_crime.xml layout file is declared as class members of CrimeListFragment and not inside CrimeHolder class as :

public class CrimeListFragment extends Fragment {

    // your other views and variables related declarations
    // these are problematic declaration that keeps on being reused
    private TextView mTitleTextView;
    private TextView mDateTextView;
    private ImageView mSolvedImageView;
    private Button mButtonCallPolice;
    // your other declarations

    // your other code
}

这就是为什么对于每个CrimeHolder实例都重复使用相同的view实例,例如mTitleTextViewmDateTextViewmSolvedImageViewmButtonCallPolice等,从而导致列表中项目的无序排列. 现在,为了解决此问题,您只需将这些行作为类变量移动到CrimeHolder类中,即可确保每个新的CrimeHolder实例都具有上述视图的单独实例为:

That's why, the same view instances such as mTitleTextView, mDateTextView, mSolvedImageView, mButtonCallPolice, etc. are being reused for every CrimeHolder instances causing the unordering of the items in the list. Now, in order to fix this problem, you can simply move these lines to code to CrimeHolder class as class variable which would ensures that every new CrimeHolder instance will have separate instances of above-mentioned views as :

private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
         // declare all of them here so there will be unique instances of these views for unique viewholder
         private TextView mTitleTextView;
         private TextView mDateTextView;
         private ImageView mSolvedImageView;
         private Button mButtonCallPolice;

         public CrimeHolder(int layout, LayoutInflater inflater, ViewGroup parent ) {

            View itemView = inflater.inflate(layout, parent, false));
            super(itemView);

            mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
            mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
            mSolvedImageView = (ImageView) itemView.findViewById(R.id.crime_solved);

            if (itemView.findViewById(R.id.call_police)!=null) {
                mButtonCallPolice = (Button) itemView.findViewById(R.id.call_police);
            }

            itemView.setOnClickListener(this);
        }

        public void bind(Crime crime) {

            mCrime = crime;
            mTitleTextView.setText(mCrime.getTitle());
            mDateFormat = DateFormat.format("EEE, MMM dd, yyyy", mCrime.getDate());

            mDateTextView.setText(mDateFormat);
            mSolvedImageView.setVisibility(mCrime.isSolved() ? View.VISIBLE :
                    View.GONE);

            if(mCrime.isRequiresPolice()){
                mButtonCallPolice.setEnabled(true);
            }
        }

        @Override
        public void onClick(View view) {

            Intent intent = CrimePagerActivity.newIntent(getActivity(),
                    CrimeLab.get(requireActivity()).getCrimes().get((getAdapterPosition())).getId());

            startActivityForResult(intent, REQUEST_CRIME);
        }

    }  

它解决了我的问题,希望它也能解决您的问题.

It fixed my problem and I hope it will fix yours too.

这篇关于滚动后无序的RecycleView列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆