Android Listview的行为不符合预期

Android Listview的行为不符合预期,android,android-listview,Android,Android Listview,我有一个活动,我在后台播放媒体,我有一个列表视图,其中我有特定于歌词的行,整个歌词都在一个数组中。现在,我希望当媒体播放器到达特定时间时,相关歌词(行)滚动到listview的中心,并以不同的阴影突出显示这一行。为此,我在getview方法中使用smoothScrollto()函数。然而,一旦if-else条件执行,我的列表就会以一种不稳定的方式上下滚动,其重复性太大以至于无法读取。下面是我的代码: 类级别变量: String [] LyricsE; String [] LyricsH; L

我有一个活动,我在后台播放媒体,我有一个列表视图,其中我有特定于歌词的行,整个歌词都在一个数组中。现在,我希望当媒体播放器到达特定时间时,相关歌词(行)滚动到listview的中心,并以不同的阴影突出显示这一行。为此,我在getview方法中使用smoothScrollto()函数。然而,一旦if-else条件执行,我的列表就会以一种不稳定的方式上下滚动,其重复性太大以至于无法读取。下面是我的代码:

类级别变量:

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;
        }
    } 
根据你提到的第二个问题——当你改变一个元素的颜色时,另一个元素也在改变它的颜色。这种行为的原因是,为了高效地工作,创建元素试图重用其他元素。大多数情况下,它工作正常,因为我们通常希望所有元素都有相同的样式-这样,它不必单独创建每个元素,而是