[英]Highlighting a row in ListView on click of a button in the row
我是 Android 開發的新手,我正在創建一個音樂播放器應用程序。 我已經完成了邏輯部分。 現在我專注於應用程序的外觀。 我想做的一件事是在單擊行中相應的“播放”按鈕時突出顯示該行。
期望的效果:當點擊一行的播放按鈕時,該行被突出顯示(背景顏色改變),同時最后點擊的行的背景被重置。
嘗試:我嘗試存儲之前選擇的視圖並在當前和之前的視圖中進行必要的更改。
以下是我在自定義適配器中為 ListView 編寫的代碼:
(相關代碼寫在按鈕的onClickListener()中)
package com.example.mediaplayer;
import android.app.Activity;
import android.content.ContentUris;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
public class MusicAdapter extends ArrayAdapter<Music> {
private MediaPlayer mp;
private ArrayList<Integer> Lengths = new ArrayList<>();
private int mCurrentPosition = 0;
private LinearLayout mpreviousView = null;
private LinearLayout mitemView = null;
private IAdapterToFragment listener;
private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
Lengths.set(mCurrentPosition, 0);
mitemView.setBackgroundColor(Color.parseColor("#FDBCA8"));
}
};
public interface IAdapterToFragment {
void onSuccess(String songName);
}
public MusicAdapter(Activity context, ArrayList<Music> songs, IAdapterToFragment listener) {
super(context, 0, songs);
for(int i = 0; i < songs.size(); i ++) {
Lengths.add(0);
}
this.listener = listener;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
mpreviousView = mitemView;
View musicItemView = convertView;
if(musicItemView == null) {
musicItemView = LayoutInflater.from(getContext()).inflate(
R.layout.music_item, parent, false);
}
Music currentSong = getItem(position);
LinearLayout itemView = musicItemView.findViewById(R.id.item);
mitemView = itemView;
TextView songnameView = musicItemView.findViewById(R.id.song_name);
songnameView.setText(currentSong.getMusicName());
Button stop = (Button) musicItemView.findViewById(R.id.stop_button);
Button pause = (Button) musicItemView.findViewById(R.id.pause_button);
Button play = (Button) musicItemView.findViewById(R.id.play_button);
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
releaseMediaPlayer();
if(listener != null)
listener.onSuccess(currentSong.getMusicName());
mCurrentPosition = position;
itemView.setBackgroundColor(Color.parseColor("#FAA185"));
long songID = currentSong.getMusicResourceId();
Uri uri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
songID);
mp = MediaPlayer.create(getContext(), uri);
mp.start();
mp.seekTo(Lengths.get(position));
mp.setOnCompletionListener(mCompletionListener);
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null)
listener.onSuccess("Play another song!");
releaseMediaPlayer();
itemView.setBackgroundColor(Color.parseColor("#FDBCA8"));
Lengths.set(position, 0);
}
});
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int currentPosition = 0;
if(mp != null) {
currentPosition = mp.getCurrentPosition();
mp.stop();
Lengths.set(position, currentPosition);
releaseMediaPlayer();
// mp.setOnCompletionListener(mCompletionListener);
}
}
});
return musicItemView;
}
private void releaseMediaPlayer() {
if (mp != null) {
mp.release();
mp = null;
if(mpreviousView != null)
mpreviousView.setBackgroundColor(Color.parseColor("#FDBCA8"));
// mp.abandonAudioFocus(mOnAudioFocusChangeListener);
}
}
}
然而這不起作用,因為 ListView 回收視圖。 因此,我沒有訪問不同的行,而是同時對多行進行更改。
問題:
有沒有辦法可以唯一地訪問適配器 class 本身的 ListView 中的一行?
有沒有更簡單的方法來達到預期的效果?
謝謝你。
編輯:
經過大量研究並從相關問題中嘗試了幾種方法后,我仍然沒有想出一種獲得預期效果的方法。 由於視圖的回收,我嘗試過的所有方法都會導致在單擊一個按鈕時突出顯示多行。 如果您正在尋找替代解決方案,您可以:
(不是最佳的)用一些不回收視圖的布局替換 ListView。 這樣,即使滾動過去,恰好一個項目也會突出顯示並保持突出顯示。
從列表中刪除所有類型的按鈕,創建一個列表項選擇器並將其設置為您 list_item 的背景。 請按照此處提到的步驟操作: 在 ListView 中重置背景顏色。 這是我現在用於我的應用程序的那個。
設置它,使所有 ListView 項目的布局都具有相應的邊界或任何具有透明顏色的邊界。 訪問該特定項目后,只需將該小部件的顏色更改為其他顏色即可。 任務完成后不要忘記將顏色改回透明。 只要它是一個 ListView 項目而不是多個,你可以做多個邊界/任何你想要的。 還有其他方法可以處理這個問題,但在大多數情況下,這不是一個好的設計模式。
停止檢查 null 的 convertView 將停止 ListView 回收項目視圖,因此更改:
View musicItemView = convertView;
if(musicItemView == null) {
musicItemView = LayoutInflater.from(getContext()).inflate(
R.layout.music_item, parent, false);
}
至
View musicItemView = LayoutInflater.from(getContext()).inflate(R.layout.music_item, parent, false);
然后用新視圖創建每一行。
試試這個適配器代碼:
public class MusicAdapter extends ArrayAdapter<Music> {
private MediaPlayer mp;
private ArrayList<Integer> Lengths = new ArrayList<>();
private int mCurrentPosition = -1; //Changed
//private LinearLayout mpreviousView = null;
private LinearLayout mitemView = null;
private IAdapterToFragment listener;
private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
Lengths.set(mCurrentPosition, 0);
mitemView.setBackgroundColor(Color.parseColor("#FDBCA8"));
mitemView = null; //Added
mCurrentPosition = -1; //Added
}
};
public interface IAdapterToFragment {
void onSuccess(String songName);
}
public MusicAdapter(Activity context, ArrayList<Music> songs, IAdapterToFragment listener) {
super(context, 0, songs);
for(int i = 0; i < songs.size(); i ++) {
Lengths.add(0);
}
this.listener = listener;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//mpreviousView = mitemView;
//View musicItemView = convertView;
//if(musicItemView == null) {
View musicItemView = LayoutInflater.from(getContext()).inflate(R.layout.music_item, parent, false);
//}
Music currentSong = getItem(position);
LinearLayout itemView = musicItemView.findViewById(R.id.item);
mitemView = itemView;
TextView songnameView = musicItemView.findViewById(R.id.song_name);
songnameView.setText(currentSong.getMusicName());
if (mCurrentPosition == position) itemView.setBackgroundColor(Color.parseColor("#FAA185")); //Added
Button stop = (Button) musicItemView.findViewById(R.id.stop_button);
Button pause = (Button) musicItemView.findViewById(R.id.pause_button);
Button play = (Button) musicItemView.findViewById(R.id.play_button);
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
releaseMediaPlayer();
if(listener != null)
listener.onSuccess(currentSong.getMusicName());
mCurrentPosition = position;
itemView.setBackgroundColor(Color.parseColor("#FAA185"));
mitemView = itemView; //Added
long songID = currentSong.getMusicResourceId();
Uri uri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
songID);
mp = MediaPlayer.create(getContext(), uri);
mp.start();
mp.seekTo(Lengths.get(position));
mp.setOnCompletionListener(mCompletionListener);
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null)
listener.onSuccess("Play another song!");
releaseMediaPlayer();
itemView.setBackgroundColor(Color.parseColor("#FDBCA8"));
Lengths.set(position, 0);
mitemView = null; //Added
}
});
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int currentPosition = 0;
if(mp != null) {
currentPosition = mp.getCurrentPosition();
mp.stop();
Lengths.set(position, currentPosition);
releaseMediaPlayer();
// mp.setOnCompletionListener(mCompletionListener);
}
}
});
return musicItemView;
}
private void releaseMediaPlayer() {
if (mp != null) {
mp.release();
mp = null;
if (mitemView != null) //Changed
mitemView.setBackgroundColor(Color.parseColor("#FDBCA8")); //Changed
// mp.abandonAudioFocus(mOnAudioFocusChangeListener);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.