私はRecyclerViewを持っています。各行には、再生ボタン、テキストビュー、およびプログレスバーがあります。再生ボタンをクリックすると、SDカードからオーディオを再生し、プログレスバーを進行する必要があります問題は、recyclerviewを下にスクロールすると、次の行のプログレスバーを変更することです6行目にスクロールすると、6行目のシークバーが突然変わります。
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);
}}
これを試してください
ListView
を使用している場合-以下のメソッドをオーバーライドします。
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
RecycyclerView
を使用している場合-getItemViewType()
メソッドのみをオーバーライドします。
@Override
public int getItemViewType(int position) {
return position;
}
アダプターコンストラクターにsetHasStableIds(true);
を追加し、アダプターのこれら2つのメソッドをオーバーライドします。
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
名前が示すように、RecyclerView
のビューは、下にスクロールするとリサイクルされます。これは、バッキングモデルの各アイテムの状態(この場合はHistoryitem
)を保持し、onBindViewHolder
に復元する必要があることを意味します。
1)位置、最大、およびモデルのProgressBar
の状態を保存するために必要な他の変数を作成します。
2)バッキングモデルのデータに基づいてProgressBar
の状態を設定します。クリックすると、アイテムの位置をFileDownload
/StartMediaPlayer
メソッドに渡します。
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)バッキングモデルを更新し、変更されたことを通知することにより、進行状況バーを更新します。
stethitems.get(position).setPosition(mPlayer.getCurrentPosition());
notifyItemChanged(position);
recylerView
のNestedScroll View
にXML
を入れて、プロパティnestedScrollingEnabled = false
を追加します。
そして、アダプターにonBindViewHolder
この行を追加します
final MyViewHolder viewHolder = (MyViewHolder)holder;
このviewHolder
オブジェクトをビューでsetText
に使用するか、あらゆる種類のクリックイベントを実行します。
例:viewHolder.txtSubject.setText("Example");
行要素としてedittexとチェックボックスを含むrecyclerviewを実装しようとしたときに、同じ問題に直面しました。アダプタークラスに次の2行を追加するだけで、スクロール値の変更の問題を解決しました。
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
それが解決策になることを願っています。ありがとう
この行は、各バインドで進行状況を0に変更します
myViewHolder.progressplay.setProgress(0);
その状態をどこかに保存してから、この同じ行にロードします。
これを試して
@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); }
このように試してみませんか、
HashMap<String, Integer> progressHashMap = new HashMap<>();
//...
if(!progressHashMap.containsKey(downloadpath)){
progressHashMap.put(downloadpath, mPlayer.getCurrentPosition());
}
progressbar.setProgress(progressHashMap.get(downloadpath));
私は多くのデータを処理しているときに同じ問題を抱えていましたが、5で機能します。これは、画面に表示される5つの要素をレンダリングしますが、より多くの要素をprobに与えるためです。事は..
RecyclerViewとlistViewは、データの入力をスキップする場合があります。スクロール中にRecyclerViewバインディング機能がスキップされる場合、recyclerViewアダプターをデバッグしようとすると、onBindを毎回呼び出すため正常に動作します。また、公式のGoogle開発者のビューを見ることができます listView の世界。約20分から30分で、位置ごとのgetViewが毎回呼び出されることを想定できないことを説明します。
だから、私は使用することをお勧めします
藤原悟が作成したRecyclerView DataBinder
または
RecyclerView MultipleViewTypesバインダはyqritcによって作成されました。
簡単に回避できる場合は、これらのバインダーを利用できます。
これは、MultipleViewタイプを処理する方法、または大量のデータを使用している場合に使用します。これらのバインダーは、それを修正するドキュメントを丁寧に読むのに役立ちます。