Android Listview的行为不符合预期
我有一个活动,我在后台播放媒体,我有一个列表视图,其中我有特定于歌词的行,整个歌词都在一个数组中。现在,我希望当媒体播放器到达特定时间时,相关歌词(行)滚动到listview的中心,并以不同的阴影突出显示这一行。为此,我在getview方法中使用smoothScrollto()函数。然而,一旦if-else条件执行,我的列表就会以一种不稳定的方式上下滚动,其重复性太大以至于无法读取。下面是我的代码: 类级别变量:Android Listview的行为不符合预期,android,android-listview,Android,Android Listview,我有一个活动,我在后台播放媒体,我有一个列表视图,其中我有特定于歌词的行,整个歌词都在一个数组中。现在,我希望当媒体播放器到达特定时间时,相关歌词(行)滚动到listview的中心,并以不同的阴影突出显示这一行。为此,我在getview方法中使用smoothScrollto()函数。然而,一旦if-else条件执行,我的列表就会以一种不稳定的方式上下滚动,其重复性太大以至于无法读取。下面是我的代码: 类级别变量: String [] LyricsE; String [] LyricsH; L
String [] LyricsE;
String [] LyricsH;
ListView listView;
private ArrayAdapter dataAdapter;
dataAdapter = new arrayAdapter(MainActivity.this, LyricsH);
listView.setAdapter(dataAdapter);
public class arrayAdapter extends ArrayAdapter<String[]> {
private final Context context;
private final String[] lyrics;
public arrayAdapter(Context context, String[]lyrics ) {
super(context, R.layout.list);
this.context = context;
this.lyrics = lyrics;
}
public int getCount() {
return lyrics.length;
}
public String[] getItem(int position) {
return (lyrics);
}
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list, parent, false);
}
TextView textView = ((TextView) convertView.findViewById(R.id.textView2));
textView.setText(lyrics[position]);
if(mediaPlayer.getCurrentPosition()/1000 > 0 && mediaPlayer.getCurrentPosition()/1000 < 20){
listView.smoothScrollToPosition(3);
System.out.println("FIrst if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(4);
System.out.println("2 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 54 && mediaPlayer.getCurrentPosition()/1000 < 67){
listView.smoothScrollToPosition(5);
System.out.println("3 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 67 && mediaPlayer.getCurrentPosition()/1000 < 75){
listView.smoothScrollToPosition(6);
System.out.println("4 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(7);
System.out.println("5 if");
}
return convertView;
}
}
onCreate:
String [] LyricsE;
String [] LyricsH;
ListView listView;
private ArrayAdapter dataAdapter;
dataAdapter = new arrayAdapter(MainActivity.this, LyricsH);
listView.setAdapter(dataAdapter);
public class arrayAdapter extends ArrayAdapter<String[]> {
private final Context context;
private final String[] lyrics;
public arrayAdapter(Context context, String[]lyrics ) {
super(context, R.layout.list);
this.context = context;
this.lyrics = lyrics;
}
public int getCount() {
return lyrics.length;
}
public String[] getItem(int position) {
return (lyrics);
}
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list, parent, false);
}
TextView textView = ((TextView) convertView.findViewById(R.id.textView2));
textView.setText(lyrics[position]);
if(mediaPlayer.getCurrentPosition()/1000 > 0 && mediaPlayer.getCurrentPosition()/1000 < 20){
listView.smoothScrollToPosition(3);
System.out.println("FIrst if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(4);
System.out.println("2 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 54 && mediaPlayer.getCurrentPosition()/1000 < 67){
listView.smoothScrollToPosition(5);
System.out.println("3 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 67 && mediaPlayer.getCurrentPosition()/1000 < 75){
listView.smoothScrollToPosition(6);
System.out.println("4 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(7);
System.out.println("5 if");
}
return convertView;
}
}
自定义类:
String [] LyricsE;
String [] LyricsH;
ListView listView;
private ArrayAdapter dataAdapter;
dataAdapter = new arrayAdapter(MainActivity.this, LyricsH);
listView.setAdapter(dataAdapter);
public class arrayAdapter extends ArrayAdapter<String[]> {
private final Context context;
private final String[] lyrics;
public arrayAdapter(Context context, String[]lyrics ) {
super(context, R.layout.list);
this.context = context;
this.lyrics = lyrics;
}
public int getCount() {
return lyrics.length;
}
public String[] getItem(int position) {
return (lyrics);
}
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list, parent, false);
}
TextView textView = ((TextView) convertView.findViewById(R.id.textView2));
textView.setText(lyrics[position]);
if(mediaPlayer.getCurrentPosition()/1000 > 0 && mediaPlayer.getCurrentPosition()/1000 < 20){
listView.smoothScrollToPosition(3);
System.out.println("FIrst if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(4);
System.out.println("2 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 54 && mediaPlayer.getCurrentPosition()/1000 < 67){
listView.smoothScrollToPosition(5);
System.out.println("3 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 67 && mediaPlayer.getCurrentPosition()/1000 < 75){
listView.smoothScrollToPosition(6);
System.out.println("4 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(7);
System.out.println("5 if");
}
return convertView;
}
}
公共类arrayAdapter扩展了arrayAdapter{
私人最终语境;
私人最终字符串[]歌词;
公共arrayAdapter(上下文,字符串[]歌词){
超级(上下文、右布局、列表);
this.context=上下文;
歌词=歌词;
}
public int getCount(){
返回歌词长度;
}
公共字符串[]getItem(int位置){
返回(歌词);
}
公共长getItemId(int arg0){
返回arg0;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
LayoutFlater充气器=(LayoutFlater)context.getSystemService(context.LAYOUT\u充气器\u服务);
如果(convertView==null){
convertView=充气机充气(R.layout.list,父项,false);
}
TextView TextView=((TextView)convertView.findViewById(R.id.textView2));
setText(歌词[位置]);
如果(mediaPlayer.getCurrentPosition()/1000>0&&mediaPlayer.getCurrentPosition()/1000<20){
listView.smoothScrollToPosition(3);
System.out.println(“第一个if”);
}else if(mediaPlayer.getCurrentPosition()/1000>20&&mediaPlayer.getCurrentPosition()/1000<54){
listView.smoothScrollToPosition(4);
系统输出打印项次(“2如果”);
}else if(mediaPlayer.getCurrentPosition()/1000>54&&mediaPlayer.getCurrentPosition()/1000<67){
listView.smoothScrollToPosition(5);
系统输出打印项次(“3如果”);
}else if(mediaPlayer.getCurrentPosition()/1000>67&&mediaPlayer.getCurrentPosition()/1000<75){
listView.smoothScrollToPosition(6);
系统输出打印项次(“4如果”);
}else if(mediaPlayer.getCurrentPosition()/1000>20&&mediaPlayer.getCurrentPosition()/1000<54){
listView.smoothScrollToPosition(7);
系统输出打印项次(“5如果”);
}
返回视图;
}
}
从getView()
方法中取出您的条件,它不是适合它们的地方
您提到过,您有一个处理程序,该处理程序经常轮询媒体播放器的当前状态。用它-这是正确的方法
您还说过,您需要它位于getView()
内,因为您希望您的“选定”行更改其背景。那不是真的。您知道要滚动到的位置,对吗?因此,您可以从列表视图
中获取此特定的视图
,并根据需要进行更改
使用getChildAt()
方法在特定位置获取视图。请记住,getChildAt(0)
将返回第一个可见元素,而不是整个列表中的第一个。以下是此问题的解决方案:
编辑:
String [] LyricsE;
String [] LyricsH;
ListView listView;
private ArrayAdapter dataAdapter;
dataAdapter = new arrayAdapter(MainActivity.this, LyricsH);
listView.setAdapter(dataAdapter);
public class arrayAdapter extends ArrayAdapter<String[]> {
private final Context context;
private final String[] lyrics;
public arrayAdapter(Context context, String[]lyrics ) {
super(context, R.layout.list);
this.context = context;
this.lyrics = lyrics;
}
public int getCount() {
return lyrics.length;
}
public String[] getItem(int position) {
return (lyrics);
}
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list, parent, false);
}
TextView textView = ((TextView) convertView.findViewById(R.id.textView2));
textView.setText(lyrics[position]);
if(mediaPlayer.getCurrentPosition()/1000 > 0 && mediaPlayer.getCurrentPosition()/1000 < 20){
listView.smoothScrollToPosition(3);
System.out.println("FIrst if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(4);
System.out.println("2 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 54 && mediaPlayer.getCurrentPosition()/1000 < 67){
listView.smoothScrollToPosition(5);
System.out.println("3 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 67 && mediaPlayer.getCurrentPosition()/1000 < 75){
listView.smoothScrollToPosition(6);
System.out.println("4 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(7);
System.out.println("5 if");
}
return convertView;
}
}
根据你提到的第二个问题——当你改变一个元素的颜色时,另一个元素也在改变它的颜色。这种行为的原因是,为了高效地工作,创建元素试图重用其他元素。大多数情况下,它工作正常,因为我们通常希望所有元素都具有相同的样式-这样,它不必单独创建每个元素,而是使用现有的元素。它发生在Adapter
中的getView()
方法中,并以convertView
的形式出现
无论如何,这意味着您更希望在创建元素之后,在getView()
中更改元素的样式。这也意味着您需要再次使用自定义适配器。:)
我为您编写了一个简单的适配器:
public class LyricsAdapter extends BaseAdapter {
private final static int NOT_SELECTED_ID = 0;
private final static int SELECTED_ID = 1;
private LayoutInflater mInflater;
private int mSelectedItem;
private int selectedItemLayoutId, unselectedItemLayoutId;
private String [] mList;
public LyricsAdapter(Context context, String [] lyrics) {
mInflater = LayoutInflater.from(context);
this.mList = lyrics;
}
public View getView(int position, View convertView, ViewGroup parent) {
boolean selected = (((LyricsAdapter)((ListView)parent).getAdapter()).getSelectedItem() == position);
if (convertView == null) {
if(selected) {
convertView = mInflater.inflate(R.layout.selected_item_layout, parent, false);
convertView.setId(SELECTED_ID);
} else {
convertView = mInflater.inflate(R.layout.unselected_item_layout, parent, false);
convertView.setId(NOT_SELECTED_ID);
}
} else {
if(selected && (convertView.getId() == NOT_SELECTED_ID)) { // If it's selected, but still uses not-selected layout
convertView = mInflater.inflate(R.layout.selected_item_layout, parent, false);
convertView.setId(SELECTED_ID);
} else if(!selected && (convertView.getId() == SELECTED_ID)) { // If it's not selected, but still uses selected layout
convertView = mInflater.inflate(R.layout.unselected_item_layout, parent, false);
convertView.setId(NOT_SELECTED_ID);
}
}
return convertView;
}
public int getCount() {
return mList.length;
}
public Object getItem(int position) {
return mList[position];
}
public long getItemId(int position) {
return position;
}
public void setSelectedItem(int pos) {
mSelectedItem = pos;
}
public int getSelectedItem() {
return mSelectedItem;
}
}
我还没有测试过它,所以它可能有一些问题。但我希望你能明白。现在,基本上您要做的就是在代码中调用:
listView.smoothScrollToPosition(position);
您还必须拨打:
// Inform adapter which item is selected
((LyricsAdapter)listView.getAdapter()).setSelectedItem(position);
// Refresh ListView's element so that selected one will update it's layout (or in other words - call `getView()` for all items again)
((LyricsAdapter)listView.getAdapter()).notifyDataSetChanged();
listView.refreshDrawableState();
listView.invalidate();
从getView()
方法中获取您的条件,它不是适合它们的地方
您提到过,您有一个处理程序,该处理程序经常轮询媒体播放器的当前状态。使用它-这是正确的方法
您还说过,您需要它位于getView()
内,因为您希望您的“选定”行更改其背景。那不是真的。您知道要滚动到的位置,对吗?因此,您可以从列表视图
中获取此特定的视图
,并根据需要进行更改
使用getChildAt()
方法在特定位置获取视图。请记住,getChildAt(0)
将返回第一个可见元素,而不是整个列表中的第一个。以下是此问题的解决方案:
编辑:
String [] LyricsE;
String [] LyricsH;
ListView listView;
private ArrayAdapter dataAdapter;
dataAdapter = new arrayAdapter(MainActivity.this, LyricsH);
listView.setAdapter(dataAdapter);
public class arrayAdapter extends ArrayAdapter<String[]> {
private final Context context;
private final String[] lyrics;
public arrayAdapter(Context context, String[]lyrics ) {
super(context, R.layout.list);
this.context = context;
this.lyrics = lyrics;
}
public int getCount() {
return lyrics.length;
}
public String[] getItem(int position) {
return (lyrics);
}
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.list, parent, false);
}
TextView textView = ((TextView) convertView.findViewById(R.id.textView2));
textView.setText(lyrics[position]);
if(mediaPlayer.getCurrentPosition()/1000 > 0 && mediaPlayer.getCurrentPosition()/1000 < 20){
listView.smoothScrollToPosition(3);
System.out.println("FIrst if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(4);
System.out.println("2 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 54 && mediaPlayer.getCurrentPosition()/1000 < 67){
listView.smoothScrollToPosition(5);
System.out.println("3 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 67 && mediaPlayer.getCurrentPosition()/1000 < 75){
listView.smoothScrollToPosition(6);
System.out.println("4 if");
}else if(mediaPlayer.getCurrentPosition()/1000 > 20 && mediaPlayer.getCurrentPosition()/1000 < 54){
listView.smoothScrollToPosition(7);
System.out.println("5 if");
}
return convertView;
}
}
根据你提到的第二个问题——当你改变一个元素的颜色时,另一个元素也在改变它的颜色。这种行为的原因是,为了高效地工作,创建元素试图重用其他元素。大多数情况下,它工作正常,因为我们通常希望所有元素都有相同的样式-这样,它不必单独创建每个元素,而是