2015-04-18 4 views
1

Я совершенно новичок в Android. В следующем классе данные извлекаются из базы данных и отображаются в ListView, который имеет два разных макета. Хотя он работает так, как ожидалось, проблема в том, что прокрутка не является гладкой, потому что текстовые изображения назначаются снова и снова. Я не мог понять, как их назначить только один раз. Пожалуйста, помогите мне с этим. Спасибо заранее. Извинения за код, я знаю, он выглядит плохо.Android Listview ArrayAdapter с двумя макетами

public class FragmentVerses extends ListFragment { 

Typeface font; 
ViewHolder viewHolder = new ViewHolder(); 
ViewHolderHeader viewHolderHeader = new ViewHolderHeader(); 
DatabaseHelper db; 

public List<VersesModel> verses; 
public List<ChapterModel> chapterName; 
ArrayAdapter<VersesModel> adapter; 

public FragmentVerses() { 
} 

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.verses_fragment, container, false); 

    db = new DatabaseHelper(getActivity()); 
    try { 
     db.createDatabase(); 
    } catch (IOException e) { 
     Toast.makeText(getActivity(), "Error Creating Database", Toast.LENGTH_LONG) 
       .show(); 
    } 

    verses = db.getVerses(" WHERE " + getActivity().getIntent().getStringExtra(MainActivity.CONDITION)); 
    chapterName = db.getChapter(); 
    adapter = new MyListAdapter(); 
    setListAdapter(adapter); 
    return view; 
} 

private class MyListAdapter extends ArrayAdapter<VersesModel> { 
    public MyListAdapter() { 
     super(getActivity(), R.layout.verses_custom_list, verses); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     VersesModel currentVerse = verses.get(position); 
     if (convertView == null) { 
      convertView = getActivity().getLayoutInflater().inflate(
        R.layout.verses_custom_list, parent, false); 
      font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf"); 
      viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse); 
      viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation); 
      viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber); 
      viewHolder.textView.setTypeface(font); 
      viewHolder.imageView = (ImageView) convertView.findViewById(R.id.versesImageView); 
      convertView.setTag(viewHolder); 
     } else { 
      if (currentVerse.getVerseNumber() != 0) { 
       convertView = getActivity().getLayoutInflater().inflate(
         R.layout.verses_custom_list, parent, false); 
       viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse); 
       viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber); 
       viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation); 
       viewHolder.textView.setTypeface(font); 
       viewHolder.textView.setText(currentVerse.getVerseText() + "", true); 
       viewHolder.textViewTranslation.setText(currentVerse.getVerseTranslation()); 
       viewHolder.nView.setText(currentVerse.getVerseNumber() + ""); 
       convertView.setTag(viewHolder); 
      } else { 
       convertView = getActivity().getLayoutInflater().inflate(
         R.layout.verses_custom_list_header, parent, false); 
       ChapterModel chapterModel = chapterName.get(currentVerse.getChapterNumber() - 1); 
       if (viewHolderHeader.textViewChapter == null) viewHolderHeader.textViewBismillah = (TextView) convertView.findViewById(R.id.textView_Verse_Bismillah); 
        viewHolderHeader.textViewChapter = (TextView) convertView.findViewById(R.id.textView_Verse_ChapterName); 
        viewHolderHeader.textViewChapter.setText("سورة " + chapterModel.getChapterText()); 
        viewHolderHeader.textViewBismillah.setTypeface(font); 
        viewHolderHeader.textViewChapter.setTypeface(font); 
       } else { 
        viewHolderHeader = (ViewHolderHeader) convertView.getTag(); 
       } 
       convertView.setTag(viewHolderHeader); 

      } 
     } 
     return convertView; 
    } 
} 
+0

Почему вы так много раздуваете представление. вы только раздуваете один раз, и система перерабатывает представления по мере необходимости. Это является причиной того, что ваши списки настолько вялые. Посмотрите на создание списков с помощью ArrayAdapters. – Ichthyocentaurs

ответ

1

адаптер Android обеспечивает возможность использования нескольких макетов в одном адаптере.

Во-первых, сказать адаптер, сколько макетов вам нужно:

public int getViewTypeCount() 
{ 
    return 2; 
} 

Затем дает некоторую логику, чтобы сказать, какой макет должен быть использован для текущего элемента:

public int getItemViewType(int position) 
{ 
    if (verses.get(position).getVerseNumber() != 0) 
    { 
     return 0; 
    } 

    return 1; 
} 

Наконец, в вашем построить подходящий вид:

public View getView(int position, View convertView, ViewGroup parent) 
{ 
    if (this.getItemViewType(position) == 0) 
    { 
     // TODO Build the appropriate view 
     return view; 
    } 

    // TODO Build the appropriate other view 
    return view; 
} 
+0

Спасибо @Gaetan, с небольшой модификацией он работал для меня. Хотя я все еще чувствую себя немного отстающим. – Aalem

0

Есть две вещи, которые необходимо внести в изменение кода: низкое это даст вам идею. Вы не должны раздуть макет каждый раз, и нет необходимости называть findViewById каждый раз, а также посмотреть на примеры кода ниже

ViewHolder holder; 
    if ((convertView == null)) { 
     convertView = layoutInflater 
       .inflate(R.layout.list_item, 
         viewGroup, false); 
     holder = new ViewHolder(); 
     holder.itemImage = (ImageView) convertView 
       .findViewById(R.id.logo); 
     holder.itemName = ((TextView) convertView 
       .findViewById(R.id.title_product_search)); 
     convertView.setTag(holder); 

    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    //assign text and images to controls after this 
    holder.itemName.setText("text"); 
    imageLoader.displayImage(item.imageUrl, holder.itemImage, 
       options); 
0

Вот что я сделал.

private class MyListAdapter extends ArrayAdapter<VersesModel> { 
    public MyListAdapter() { 
     super(getActivity(), R.layout.verses_custom_list, verses); 
    } 

    @Override 
    public int getViewTypeCount() { 
     return 2; 
    } 

    @Override 
    public int getItemViewType(int position) { 
     if (verses.get(position).getVerseNumber() != 0) { 
      return 0; 
     } 
     return 1; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     VersesModel currentVerse = verses.get(position); 


     if (convertView == null) { 
      viewHolder = new ViewHolder(); 
      switch (getItemViewType(position)) { 
       case 0: 
        convertView = getActivity().getLayoutInflater().inflate(
          R.layout.verses_custom_list, parent, false); 
        viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse); 
        viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_verseNumber); 
        viewHolder.textViewTranslation = (TextView) convertView.findViewById(R.id.textView_VerseTranslation); 
        font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf"); 
        viewHolder.textView.setTypeface(font); 
        Toast.makeText(getActivity(), "" + position, Toast.LENGTH_SHORT).show(); 
        break; 
       case 1: 
        convertView = getActivity().getLayoutInflater().inflate(
          R.layout.verses_custom_list_header, parent, false); 
        chapterModel = chapterName.get(currentVerse.getChapterNumber() - 1); 
        viewHolder.textView = (TextViewEx) convertView.findViewById(R.id.textView_Verse_Bismillah); 
        viewHolder.nView = (TextView) convertView.findViewById(R.id.textView_Verse_ChapterName); 
        font = Typeface.createFromAsset(convertView.getContext().getAssets(), "Quran_Taha.ttf"); 
        viewHolder.textView.setTypeface(font); 
        viewHolder.nView.setTypeface(font); 
        break; 
      } 
      convertView.setTag(viewHolder); 
     } else { 
      viewHolder = (ViewHolder) convertView.getTag(); 
     } 
     switch (getItemViewType(position)) { 
      case 0: 
       viewHolder.textView.setText(currentVerse.getVerseText() + "", true); 
       viewHolder.textViewTranslation.setText(currentVerse.getVerseTranslation()); 
       viewHolder.nView.setText(currentVerse.getVerseNumber() + ""); 
       break; 
      case 1: 
       viewHolder.nView.setText("سورة " + chapterModel.getChapterText()); 
       break; 
     } 
     return convertView; 
    } 
} 

Тост отображает 3 раза, когда список загружается, а прокрутка в начале происходит медленнее.

+0

Вы делаете это для каждого вида и каждого вида вида: 'font = Typeface.createFromAsset (convertView.getContext(). GetAssets()," Quran_Taha.ttf ");'. Возможно, вы можете загрузить его только один раз в конструкторе адаптера. Не уверен, что это изменит вашу скорость. –

+0

Спасибо @ Gaëtan. – Aalem

2

Я знаю, что это сообщение устарело, но только для справки в будущем ... В этом случае вы должны использовать шаблон ViewHolder.

Если вы хотите использовать 2 макета, просто создайте два ViewHolder и переключитесь между ними в методе getView.

Довольно похоже на принятый ответ, но с лучшей производительностью.

Объявление видов.

private final int VIEW_TYPE_EXAMPLE = 0; 
private final int VIEW_TYPE_EXAMPLE_TWO = 1; 

Возвратите как можно больше типов, указанных выше.

@Override 
public int getViewTypeCount() { 
    return 2; 
} 

Переключение при возврате viewType, когда элемент находится в положении X. В этом случае я только изменить тип, когда элемент является первым в списке.

@Override 
public int getItemViewType(int position) { 
    return (position == 0) ? VIEW_TYPE_EXAMPLE : VIEW_TYPE_EXAMPLE_TWO; 
} 

Создайте держатели, соответствующие вашим макетам. Они будут хранить ваши данные.

class SecondViewHolder { 
      TextView mDate; 
      TextView mDescription; 
      TextView mObservations; 

      public SecondViewHolder(View view) { 
       mDate = (TextView) view.findViewById(R.id.txt_date); 
       mDescription = (TextView) view.findViewById(R.id.txt_description); 
       mObservations = (TextView) view.findViewById(R.id.txt_observations); 
      } 
     } 

class FirstViewHolder { 
      ImageView mPhoto; 
      TextView mName; 
      TextView mAge; 

      public FirstViewHolder(View view) { 
       mPatientPhoto = (ImageView)view.findViewById(R.id.img_photo); 
       mPatientName = (TextView)view.findViewById(R.id.txt_name); 
       mPatientAge = (TextView)view.findViewById(R.id.txt_age); 
      } 
     } 

Переключиться между тем в методе getView.

 @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 

      int viewType = getItemViewType(position); 

      switch (viewType) { 

       case VIEW_TYPE_EXAMPLE: { 
        FirstViewHolder firstViewHolder = null; 

        if(convertView == null){ 
         convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_example, parent, false); 
         firstViewHolder = new FirstViewHolder(convertView); 
         convertView.setTag(firstViewHolder); 
        } 
        else firstViewHolder = (FirstViewHolder)convertView.getTag(); 

        firstViewHolder.mName.setText("Your name"); 
        firstViewHolder.mAge.setText("20 years old"); 

        break; 
       } 

       case VIEW_TYPE_EXAMPLE_TWO: { 
        SecondViewHolder holder = null; 

        if(convertView == null){ 
         convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_example_two, parent, false); 
         holder = new SecondViewHolder(convertView); 
         convertView.setTag(holder); 
        } 
        else holder = (SecondViewHolder)convertView.getTag(); 

        holder.mDate.setText("01/01/2016"); 
        holder.mDescription.setText("Description"); 
        holder.mObservations.setText("Obs"); 


        break; 
       } 
      } 

      return convertView; 
     } 

Но я не могу игнорировать тот факт, что в данном конкретном вопросе, вы должны использовать CursorAdapter, потому что вы запрашиваете из базы данных.

Вы также не должны напрямую обращаться к базе данных. Вместо этого следует создать загрузчик (выполняет задачу async, но не привязан к действию).

И если вы хотите следовать рекомендациям и сэкономить некоторое время, создайте ContentProvider для управления вашей базой данных SQLite.

Но это слишком много коды для меня, чтобы положить в этом ответе:/

Надеется, что это помогает кому-то.

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