2013-09-21 4 views
1

У меня есть активность, в которой я проигрываю медиа в фоновом режиме, у меня есть список, в котором у меня есть строки, специфичные для текстов, вся лирика находится в массиве. Теперь я хочу, чтобы, когда медиаплеер достигает определенного времени, связанная лирика (Row) будет прокручиваться до центра списка, и эта строка будет выделена в другом оттенке. Для этого я использую функцию smoothScrollto() внутри метода getview. Однако, как только условия if else выполняются, мой список прокручивается вверх и вниз в неустойчивом порядке и повторяется настолько, что он не читается. Ниже мой код:Listview не ведет себя как ожидалось

Переменные уровня Класс:

String [] LyricsE; 
String [] LyricsH; 
ListView listView; 
private ArrayAdapter dataAdapter; 

OnCreate:

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; 
     } 
    } 
+2

Прежде всего, почему у вас есть текущие положения вашего медиаплеера внутри метода 'getView()'? Он не может работать, поскольку 'getView()' вызывается только тогда, когда 'ListView 'обновляет его элементы. –

+1

Я ранее использовал обработчик для проверки прогресса медиаплеера и, соответственно, прокручивает строки в списке. Но теперь, когда я хочу другой оттенок для одной конкретной строки, мне нужно manuplate это внутри метода get view. Это очень важный момент, я смотрел, как парень Ромен предупреждает об этом, но почему-то забыл об этом. Большое спасибо, чтобы напомнить мне об этом. –

ответ

3

Получите ваши условия из getView() метода, это не подходящее место для них.

Вы упомянули, что у вас есть обработчик, который часто просматривает медиа-плеер о его текущем состоянии. Используйте его - это правильный путь.

Вы также сказали, что вам нужно, чтобы он находился внутри getView(), потому что вы хотите, чтобы ваша выбранная строка изменила свой фон. Это не правда. Вы знаете позицию, которую хотите прокрутить, не так ли? Таким образом, вы можете получить этот конкретный View с вашего ListView и изменить его как хотите.

Используйте getChildAt() способ получить View в определенном положении. Помните, что getChildAt(0) вернет элемент FIRST VISIBLE, а не первый из всего списка. Вот решение этой проблемы: ListView getChildAt returning null for visible children

EDIT:

По второй проблеме вы говорили, - что при изменении цвета одного элемента, другая также меняется его цвет. Причиной такого поведения является то, что ListView, для того, чтобы работать эффективно, для создания элемента пытается повторно использовать другой элемент. Большую часть времени он отлично работает, потому что мы обычно хотим иметь одинаковый стиль для всех элементов - таким образом, он не должен создавать каждый элемент отдельно, а вместо этого использует существующий. Это происходит в getView() методе в Adapter, и он приходит как 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(); 
+0

Можете ли вы подробнее остановиться на третьем пункте, который вы сделали? В частности, где я это делаю? –

+0

@HereticMonk Вы имеете в виду, что 'getChildAt()' вещь? В месте, где у вас есть ваш 'listView.smoothScrollToPosition (5)', например, и сразу после этого вы пишете 'View element = listView.getChildAt (5)' и вы меняете фон 'element'. Это понятно или нет? Если нет, я попытаюсь объяснить это более четко. –

+0

Это помощник, я реализую это сейчас в двух висячих хвостах ягнят. –

1

listView.smoothScrollToPosition() и т.д. не ListAdapter «s работа, чтобы решить. Весь такой код должен идти внутри класса, который содержит ссылку на экземпляр ListView, что, вероятно, является классом Activity/Fragment.

+0

Согласен, это было плохо. Теперь позвольте мне перефразировать вопрос. –

Смежные вопросы