Android,滚动时动态 Listview 布局发生变化

Android, dynamic Listview layout changing on scroll

我的应用程序中有一个对话模式,我希望为一个用户加载一个布局,为另一个用户加载另一个布局。它不需要总是交替,因此我不能使用简单的“%2”来实现它。 基于一个标志,我正在分配一个动态布局,这是有效的。我的问题是,当我滚动布局时,布局会变形,user_1 的对话将变为 layout_2 或 user_2 的对话将变为 layout_1,完全随机。

我做了类似于我在此处看到的答案的操作:

有几篇关于随机数据的帖子。这不是我的问题,列表项的顺序不会改变,但是布局是随机应用的。我读到 view + 1 中的项目保存在临时内存中,对此我注意到的另一件事是:当我不断添加项目时,当我在可见性之外添加第二个项目时,滚动条会出现在图片中,它往往会获得布局可见的最顶层项目(第一项)。稍后滚动会给我看似随机的结果。

public class ConversationAdapter extends BaseAdapter
{
    private LayoutInflater inflater;
    private ArrayList<ConversationContent> objects;
    ImageView user;
    static int ind = 0;

    private class ViewHolder
    {
        TextView textView1;
        TextView textView2;
        TextView textView3;
    }

    public ConversationAdapter(Context context, ArrayList<ConversationContent> objects)
    {
        inflater = LayoutInflater.from(context);
        this.objects = objects;
    }

    public int getCount()
    {
        return objects.size();
    }

    public ConversationContent getItem(int position)
    {
        return objects.get(position);
    }

    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder = null;
        if(convertView == null)
        {
            holder = new ViewHolder();
            if (Main_Page3.convFlag == 1)
            {
                convertView = inflater.inflate(R.layout.conversation_item_1, null);
            }
            else
            {
                convertView = inflater.inflate(R.layout.conversation_item_2, null);
            }

            holder.textView1 = (TextView) convertView.findViewById(R.id.trans);
            holder.textView1.setTypeface(Main_Activity.fontC);
            holder.textView2 = (TextView) convertView.findViewById(R.id.lang);
            holder.textView2.setTypeface(Main_Activity.fontC);
            holder.textView3 = (TextView) convertView.findViewById(R.id.user);
            holder.textView3.setTypeface(Main_Activity.fontC);
            convertView.setTag(holder);
        } 
        else
        {
            holder = (ViewHolder) convertView.getTag();     
        }

        holder.textView1.setText(objects.get(position).getTranslatedText());
        holder.textView2.setText(objects.get(position).getTranslationString());
        SpannableString originalTextString = new SpannableString("\n" + objects.get(position).getOriginalText());
        originalTextString.setSpan(new RelativeSizeSpan(0.5f), 0, originalTextString.length(), 0);
        holder.textView1.append(originalTextString);
        holder.textView3.setText(objects.get(position).getUser());

        return convertView;
    }
}

所以,这就是我编写的代码。我想到的一个可能的解决方案是,如果我使用一组视图并相应地加载它们,它可能会起作用吗?我真的不确定我应该怎么做 - 我对 Android 还是很陌生。 我搜索了一下,但找不到有用的解决方案。请指导我找到一个有用的解决方案,或者,一个有效的答案将是最可取的。谢谢。

For listview adapter, if you want to show different layout, 

喜欢转换模式。你最好覆盖以下两个方法:

//set your layout type here

public int getItemViewType(int position)
{
    return 0;
}

//the layout count in your adapter

public int getViewTypeCount()
{
    return 0;
}


Here is an example you can refer to:

public class ChatMessageAdapter extends BaseAdapter
{
    private LayoutInflater mInflater;
    private List<ChatMessage> mDatas;

    public ChatMessageAdapter(Context context, List<ChatMessage> mDatas)
    {
        mInflater = LayoutInflater.from(context);
        this.mDatas = mDatas;
    }

    @Override
    public int getCount()
    {
        return mDatas.size();
    }

    @Override
    public Object getItem(int position)
    {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public int getItemViewType(int position)
    {
        ChatMessage chatMessage = mDatas.get(position);
        if (chatMessage.getType() == Type.INCOMING)
        {
            return 0;
        }
        return 1;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ChatMessage chatMessage = mDatas.get(position);
        ViewHolder viewHolder = null;
        if (convertView == null)
        {

            if (getItemViewType(position) == 0)
            {
                convertView = mInflater.inflate(R.layout.item_from_msg, parent,
                        false);
                viewHolder = new ViewHolder();
                viewHolder.mDate = (TextView) convertView
                        .findViewById(R.id.id_form_msg_date);
                viewHolder.mMsg = (TextView) convertView
                        .findViewById(R.id.id_from_msg_info);
            } else
            {
                convertView = mInflater.inflate(R.layout.item_to_msg, parent,
                        false);
                viewHolder = new ViewHolder();
                viewHolder.mDate = (TextView) convertView
                        .findViewById(R.id.id_to_msg_date);
                viewHolder.mMsg = (TextView) convertView
                        .findViewById(R.id.id_to_msg_info);
            }
            convertView.setTag(viewHolder);
        } else
        {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        //set data here
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        viewHolder.mDate.setText(df.format(chatMessage.getDate()));
        viewHolder.mMsg.setText(chatMessage.getMsg());
        return convertView;
    }

    private final class ViewHolder
    {
        TextView mDate;
        TextView mMsg;
    }

}

我认为实现你想要的最好方法是放置标志以确定要在你的 ConversationContent 对象上使用哪种布局,然后覆盖 getViewTypeCount()getItemViewType(int position) 之类的东西这个:

@Override
int getViewTypeCount() {
    return 2;
}

@Override
int getItemViewType(int position) {
    if (objects.get(position).isReply()) {  //isReply can be whatever you want to determine whether to change layout
        return 1;
    }
    return 0;
}


@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder holder = null;
    if(convertView == null)
    {
        holder = new ViewHolder();
        if (getItemViewType(position) == 1)
        {
            convertView = inflater.inflate(R.layout.conversation_item_1, null);
        }
        else
        {
            convertView = inflater.inflate(R.layout.conversation_item_2, null);
        }

        holder.textView1 = (TextView) convertView.findViewById(R.id.trans);
        holder.textView1.setTypeface(Main_Activity.fontC);
        holder.textView2 = (TextView) convertView.findViewById(R.id.lang);
        holder.textView2.setTypeface(Main_Activity.fontC);
        holder.textView3 = (TextView) convertView.findViewById(R.id.user);
        holder.textView3.setTypeface(Main_Activity.fontC);
        convertView.setTag(holder);
    } 
    else
    {
        holder = (ViewHolder) convertView.getTag();     
    }

    holder.textView1.setText(objects.get(position).getTranslatedText());
    holder.textView2.setText(objects.get(position).getTranslationString());
    SpannableString originalTextString = new SpannableString("\n" + objects.get(position).getOriginalText());
    originalTextString.setSpan(new RelativeSizeSpan(0.5f), 0, originalTextString.length(), 0);
    holder.textView1.append(originalTextString);
    holder.textView3.setText(objects.get(position).getUser());

    return convertView;
}