Ich habe eine RecyclerView. Jede Zeile verfügt über eine Wiedergabetaste, eine Textansicht und eine Fortschrittsleiste. Wenn Sie auf die Wiedergabetaste klicken, müssen Sie Audio von meiner SD-Karte abspielen und fortschreiten. Fortschrittsbalken Das Problem ist, wenn ich in der Recycling-Ansicht nach unten scrolle, ändern Sie den Fortschrittsbalken in der nächsten Zeile. Das bedeutet, ich kann 5 Elemente gleichzeitig auf den Bildschirm bringen. Wenn ich zur Suchleiste der 6. und 6. Zeile scrolle, ändert sich diese plötzlich.
public class ListAdapter extends RecyclerView.Adapter {
private List<Historyitem> stethitems;
public Context mContext;
public Activity activity;
public Handler mHandler;
static MediaPlayer mPlayer;
static Timer mTimer;
public ListAdapter(Activity activity,Context mContext,List<Historyitem> stethitems) {
this.stethitems = stethitems;
this.mContext = mContext;
this.activity = activity;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View rootView = LayoutInflater.
from(mContext).inflate(R.layout.stethoscopeadapteritem, null, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(lp);
mHandler = new Handler();
return new MyViewHolder(rootView);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
final Historyitem dataItem = stethitems.get(position);
final MyViewHolder myViewHolder = (MyViewHolder) viewHolder;
myViewHolder.progressplay.setProgress(0);
myViewHolder.stethdatetime.setText(dataItem.getReported_Time());
myViewHolder.stethhosname.setText(dataItem.getdiv());
if(dataItem.getPatient_Attribute().replaceAll(" ","").equals("")){
myViewHolder.stethdoctorname.setText(dataItem.getunit());
} else {
myViewHolder.stethdoctorname.setText(dataItem.getPatient_Attribute());
}
myViewHolder.stethstreamplay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FileDownload(dataItem.getmsg(),
myViewHolder.progressplay);
}
});
}
@Override
public int getItemCount() {
return stethitems.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
final CustomTextRegular stethdatetime;
final CustomTextView stethhosname;
final CustomTextBold stethdoctorname;
final ImageButton stethstreamplay;
final NumberProgressBar progressplay;
public MyViewHolder(View itemView) {
super(itemView);
stethdatetime = (CustomTextRegular)
itemView.findViewById(R.id.stethdatetime);
stethhosname = (CustomTextView)
itemView.findViewById(R.id.stethhosname);
stethdoctorname = (CustomTextBold)
itemView.findViewById(R.id.stethdoctorname);
stethstreamplay = (ImageButton)
itemView.findViewById(R.id.stethstreamplay);
progressplay= (NumberProgressBar)
itemView.findViewById(R.id.progressplay);
}
}
public void FileDownload(final String downloadpath,
final NumberProgressBar progressplay) {
new AsyncTask<NumberProgressBar, Integer, NumberProgressBar>() {
NumberProgressBar progress;
@Override
protected void onPreExecute() {
super.onPreExecute();
try {
if(mPlayer!=null){
mPlayer.stop();
}
}catch (Exception e){
}
try {
if(mTimer != null){
mTimer.purge();
mTimer.cancel();
}
}catch (Exception e){
}
}
@Override
protected NumberProgressBar doInBackground(NumberProgressBar... params) {
int count;
progress = progressplay;
try {
final List<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("pid",id));
URL url = new URL(Config.requestfiledownload + "?path=" +
downloadpath);
URLConnection connection = url.openConnection();
connection.connect();
int lenghtOfFile = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory() +
"record.wav");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int) (total * 100 / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
return progress;
}
@Override
protected void onPostExecute(final NumberProgressBar numberProgressBar) {
super.onPostExecute(numberProgressBar);
try {
StartMediaPlayer(numberProgressBar);
} catch (Exception e){
e.printStackTrace();
}
}
}.execute();
}
public void StartMediaPlayer(final NumberProgressBar progressbar){
Uri playuri = Uri.parse("file:///sdcard/record.wav");
mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.reset();
try {
mPlayer.setDataSource(mContext, playuri);
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalStateException e) {
} catch (Exception e) {
}
try {
mPlayer.prepare();
} catch (Exception e) {
}
mPlayer.start();
progressbar.setMax(mPlayer.getDuration());
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if(mPlayer!=null) {
mPlayer.release();
progressbar.setProgress(0);
}
if(mTimer != null){
mTimer.purge();
mTimer.cancel();
}
}
});
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
progressbar.setProgress(mPlayer.getCurrentPosition());
}
});
}
},0,500);
}}
Antworten:
Bitte versuchen Sie dies
Wenn Sie verwenden,
ListView
überschreiben Sie die folgenden Methoden.@Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; }
Wenn Sie die Methode "
RecyclerView
Nur überschreiben"getItemViewType()
verwenden.@Override public int getItemViewType(int position) { return position; }
quelle
getItemViewType
kommt zurückposition
? Neugierig auf diese Antwort.Fügen Sie
setHasStableIds(true);
Ihren Adapterkonstruktor hinzu und überschreiben Sie diese beiden Methoden im Adapter. Es hat auch funktioniert, wenn jemand einRecyclerView
Inside a verwendet,ViewPager
das sich auch in einem befindetNestedScrollView
.@Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return position; }
quelle
Wie der Name schon sagt, werden die Ansichten in a beim
RecyclerView
Scrollen nach unten wiederverwendet. Dies bedeutet, dass Sie den Status jedes Elements in Ihrem Hintergrundmodell, in diesem Fall einHistoryitem
, beibehalten und in Ihrem wiederherstellen müssenonBindViewHolder
.1) Erstellen Sie Position, Maximum und alle anderen Variablen, die Sie zum Speichern des Status
ProgressBar
in Ihrem Modell benötigen .2) Legen Sie den Status Ihrer
ProgressBar
Daten anhand der Daten in Ihrem Hintergrundmodell fest. Übergeben Sie beim Klicken die Position des Elements an IhreFileDownload
/StartMediaPlayer
Methoden.public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) { final Historyitem dataItem = stethitems.get(position); final MyViewHolder myViewHolder = (MyViewHolder) viewHolder; myViewHolder.progressplay.setMax(dataItem.getMax()); myViewHolder.progressplay.setProgress(dataItem.getPosition()); ... myViewHolder.stethstreamplay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FileDownload(dataItem.getmsg(), position); } });
3) Aktualisieren Sie den Fortschrittsbalken, indem Sie das Hintergrundmodell aktualisieren und benachrichtigen, dass es geändert wurde.
stethitems.get(position).setPosition(mPlayer.getCurrentPosition()); notifyItemChanged(position);
quelle
Ich hatte das gleiche Problem, als ich versuchte, eine Recycling-Ansicht zu implementieren, die ein Edittex und ein Kontrollkästchen als Zeilenelemente enthält. Ich habe das Problem der Änderung des Bildlaufwerts gelöst, indem ich der Adapterklasse die folgenden zwei Zeilen hinzugefügt habe.
@Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return position; }
Ich hoffe, es wird eine mögliche Lösung sein. Vielen Dank
quelle
Geben Sie
recylerView
einNestedScroll View
in IhrXML
und fügen Sie die Eigenschaft hinzunestedScrollingEnabled = false
.Und
onBindViewHolder
fügen Sie auf Ihrem Adapter diese Zeile hinzufinal MyViewHolder viewHolder = (MyViewHolder)holder;
Verwenden Sie dieses
viewHolder
Objekt mit Ihren Ansichten für KlickereignissesetText
oder führen Sie diese aus.z.B
viewHolder.txtSubject.setText("Example");
quelle
recyclerview.setItemViewCacheSize(YourList.size());
quelle
Wenn wir
RecyclerView
Elemente dynamisch ändern (dh wenn wir die Hintergrundfarbe eines bestimmtenRecyclerView
Elements ändern), kann dies das Erscheinungsbild der Elemente beim Scrollen auf unerwartete Weise ändern, da die ElementeRecyclerView
wiederverwendet werden.Um jedoch zu vermeiden, dass es möglich ist, das Scrollen
android.support.v4.widget.NestedScrollView
umRecyclerView
denNestedScrollView
Griff zu wickeln und den Griff zu lassen.<android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> </android.support.v4.widget.NestedScrollView>
Und dann können Sie im Code das verschachtelte Scrollen deaktivieren, um das Scrollen
RecyclerView
zu glätten, indem Sie nur dasNestedScrollView
Scrollen zulassen.ViewCompat.setNestedScrollingEnabled(recyclerView, false);
quelle
Ich hatte das gleiche Problem beim Umgang mit vielen Daten, es funktioniert mit 5, weil es die fünf Elemente rendert, die auf dem Bildschirm sichtbar sind, aber das Prob mit mehr Elementen gibt. Die Sache ist ..
Manchmal überspringen RecyclerView und listView nur das Auffüllen von Daten. Wenn die RecyclerView-Bindungsfunktion beim Scrollen übersprungen wird, aber wenn Sie versuchen, den recyclerView-Adapter zu debuggen, funktioniert er einwandfrei, da er jedes Mal onBind aufruft. Sie können auch die offizielle Google-Entwickleransicht The World of listView anzeigen . Etwa 20 bis 30 Minuten erklären sie, dass Sie niemals davon ausgehen können, dass getView by position jedes Mal aufgerufen wird.
Also werde ich vorschlagen, zu verwenden
RecyclerView DataBinder erstellt von satorufujiwara.
oder
RecyclerView MultipleViewTypes Binder erstellt von yqritc.
Dies sind andere Ordner, die verfügbar sind, wenn Sie diese leicht zu umgehen finden.
Auf diese Weise können Sie mit MultipleView-Typen umgehen oder wenn Sie große Datenmengen verwenden. Diese Ordner können Ihnen helfen, die Dokumentation sorgfältig zu lesen, um das Problem zu beheben.
quelle
Warum versuchst du es nicht so?
HashMap<String, Integer> progressHashMap = new HashMap<>(); //... if(!progressHashMap.containsKey(downloadpath)){ progressHashMap.put(downloadpath, mPlayer.getCurrentPosition()); } progressbar.setProgress(progressHashMap.get(downloadpath));
quelle
Versuche dies
@Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) { @Override public PointF computeScrollVectorForPosition(int targetPosition) { return LinearLayoutManager.this .computeScrollVectorForPosition(targetPosition); } }; linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); }
siehe auch das
quelle
Diese Zeile ändert den Fortschritt bei jeder Bindung auf 0
myViewHolder.progressplay.setProgress(0);
Speichern Sie den Status irgendwo und laden Sie ihn in dieselbe Zeile.
quelle
Überschreiben Sie die Methode getItemViewType im Adapter. in Kotlin verwenden
override fun getItemViewType(position: Int): Int { return position }
quelle
Wenn Ihr Recyclerview ViewHolder mehr Logik oder eine andere Ansicht hat, sollten Sie Folgendes versuchen:
**order_recyclerView.setItemViewCacheSize(x);**
Dabei ist x die Größe der Liste. Das obige funktioniert für mich, ich hoffe es funktioniert auch für Sie.
quelle
Dies ist das erwartete Verhalten von recyclerView. Da die Ansicht recycelt wird, werden Ihre Artikel möglicherweise in zufällige Ansichten verschoben. Um dies zu überwinden, müssen Sie selbst angeben, welches Element in welche Ansicht gebracht wird. Diese Informationen können in einem SparseBooleanArray gespeichert werden. Sie können ein SparseBooleanArray in Ihrem Adapter wie folgt erstellen
SparseBooleanArray selectedItems = new SparseBooleanArray();
Wenn sich Ihre Ansicht ändert, gehen Sie wie folgt vor:
selectedItems.put(viewItemIndex,true);
Jetzt in Ihrem onBindViewHolder tun
if(selectedItems.get(position, false)){ //set progress bar of related to the view to desired position } else { //do the default }
Dies ist die Grundlage, um Ihr Problem zu lösen. Sie können diese Logik in recyclerView an jedes ähnliche Problem anpassen.
quelle
stethitems.get(position)
wie in Ihrem Code verwenden.if(selectedItems.get(position, true))
zuif(selectedItems.get(position, false))
. Ich werde die ursprüngliche Antwort bearbeiten.Ich hatte das ähnliche Problem und suchte viel nach der richtigen Antwort. Grundsätzlich handelt es sich eher um ein Design der Recycler-Ansicht, bei dem die Ansicht auf der Schriftrolle aktualisiert wird, da die Ansicht aktualisiert wird.
Alles, was Sie tun müssen, ist, zum Bindezeitpunkt anzuweisen, es nicht zu aktualisieren.
So sollte Ihr onBindViewHolder aussehen
@Override @SuppressWarnings("unchecked") public void onBindViewHolder(final BaseViewHolder holder, final int position) { holder.bind(mList.get(position)); // This is the mighty fix of the issue i was having // where recycler view was updating the items on scroll. holder.setIsRecyclable(false); }
quelle