问题描述
我是 Android 开发新手,正在创建音乐播放器应用。我已经完成了逻辑部分。现在我专注于应用程序的外观。我想要做的一件事是在单击行中相应的“播放”按钮时突出显示一行。
预期效果:当点击一行的播放按钮时,该行会突出显示(背景颜色发生变化),同时最后点击的行的背景会重置。
尝试:我尝试存储之前选择的视图并在当前和之前的视图中进行必要的更改。
(相关代码写在按钮的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,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 会回收视图。因此,我没有访问不同的行,而是同时对多行进行更改。
问题:
谢谢。
编辑:
经过大量研究,从相关问题中尝试了几种方法,我仍然没有想出一种方法来达到预期的效果。我尝试过的所有方法都会导致多行在单击一个按钮时突出显示,这又是由于视图的回收。如果您正在寻找替代解决方案,您可以:
-
从列表中移除所有类型的按钮,创建一个列表项选择器并将其设置为你的list_item 的背景。按照此处提到的步骤操作:Reset background color in a ListView。这是我现在用于我的应用程序的一个。
解决方法
将其设置为所有 ListView 项目的 Layout 具有相应的边界或具有透明颜色的任何内容。访问该特定项目后,只需将该小部件的颜色更改为其他颜色即可。一旦任务完成,不要忘记将颜色改回透明。您可以设置多个边界/随心所欲提供它是一个 ListView 项目而不是多个。还有其他方法可以解决这个问题,但在大多数情况下,这不是一个好的设计模式。
,停止检查 convertView 是否为 null 将停止 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,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,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,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);
}
}
}