ListView项目背景根据滚动位置而变化

时间:2013-04-01 22:04:08

标签: android listview background-color baseadapter

我遇到了一个非常奇怪的ListView行为。我有一个简单的聊天应用程序,它使用ListView和BaseAdapter的自定义实现来显示消息。

我的想法是将来自“本地”用户灰色的消息设置为阴影,并将来自“远程”用户的消息设置为白色,以帮助用户区分这两者。 下面的两个屏幕截图显示了正在发生的事情。第二个是完全相同的活动,xml等,只需向下滚动一点。

向上滚动:

scrolled up image

向下滚动:

scrolled down image

查看“我”发送的消息@ 23:05。当它在顶部时与它的邻居没有对比,但当它滚动到底部时,差异很明显。 这发生在4.2.2上的nexus 4和7,以及运行4.1.2的GS3上。

以下是其中一个ListView项的XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_view_conversation_message_list_item_wrapper"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="2dp"
    android:paddingLeft="5dp"
    android:paddingRight="10dp" >


    <ImageView
        android:id="@+id/activity_view_conversation_message_list_item_user_image"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="5dp"
        android:src="@drawable/default_user_image" />

    <TextView
        android:id="@+id/activity_view_conversation_message_list_item_heading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="1dp"
        android:layout_toRightOf="@+id/activity_view_conversation_message_list_item_user_image"
        android:text="Martyn"
        android:textColor="#000000"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/activity_view_conversation_message_list_item_contents"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/activity_view_conversation_message_list_item_heading"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="2dp"
        android:layout_toLeftOf="@+id/activity_view_conversation_message_list_item_ack"
        android:layout_toRightOf="@+id/activity_view_conversation_message_list_item_user_image"
        android:text="Hello this is some text"
        android:textColor="#333333"
        android:textIsSelectable="true"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/activity_view_conversation_message_list_item_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="2dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:paddingTop="2dp"
        android:text="12:08"
        android:textSize="14sp" />

    <ImageView
        android:id="@+id/activity_view_conversation_message_list_item_ack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/activity_view_conversation_message_list_item_time"
        android:layout_marginRight="2dp"
        android:layout_marginTop="8dp"
        android:layout_toLeftOf="@+id/activity_view_conversation_message_list_item_time"
        android:src="@drawable/red_dot_8dp" />

</RelativeLayout>

这里是我设置RelativeLayout颜色的地方:

if(localUserId.equals(remoteUserId)){
    itemLayout.setBackgroundColor(Color.parseColor("#F9F9F9"));
}

该代码在我的适配器的getView()方法内运行。

我用谷歌搜索了一下并且没有发现任何内容,关于android:cacheColorHint问题有很多SO问题,但我不认为这就是这里发生的事情。

有没有人遇到过这个?我很难过!

编辑:这是baseadapter代码:

public class MessageListAdapter extends BaseAdapter {
    private ArrayList<Message> messageList;
    Context context;

    /**
     * Constructor
     * @param newConversationsList  An ArrayList of Conversation objects that this adapter will use
     * @param newContext            The context of the activity that instantiated this adapter
     */
    MessageListAdapter(ArrayList<Message> newMessageList, Context newContext){
        messageList = newMessageList;
        //reload();
        context = newContext;
    }

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

    public Object getItem(int position) {
        return messageList.get(position);
    }

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

    /**
     * Adds a message to the chat list
     * @param message       A Message object containing all the message's information
     */
    public void add(Message message){
        //nMessagesToShow++;        //A new message has been added, so increase the number to show by one
        Log.d(TAG, "COUNT: "+getCount());
        //refresh();
    }

    public void refresh(){
        this.notifyDataSetChanged();
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;

        if(view!=null){
            //return view;
        }

        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //Get the Message object from the list
        Message message = messageList.get(position);

        //Get the data from the message
        String senderId = message.getFromUser();
        int messageType = message.getType();

        String senderFirstName;

        ImageView userImage, messageImage;
        TextView messageHeading, messageBody;

        switch(messageType){
        case Message.MESSAGE_TYPE_TEXT:             //Standard text message
            //The layout we inflate for this list item will vary depending on whether this message has the same sender as the previous
            if(position>0 && senderId.equals(messageList.get(position-1).getFromUser())){       //True if this is not the first message AND the sender id matches that of the previous message              
                view = vi.inflate(R.layout.activity_view_conversation_message_list_item_alternate, null);       //Inflate an alternate version of the list item which has no heading or user image
            }
            else{       //This is the first message OR the sender id is different to the previous               
                view = vi.inflate(R.layout.activity_view_conversation_message_list_item, null);                 //Inflate the standard version of the layout

                userImage = (ImageView) view.findViewById(R.id.activity_view_conversation_message_list_item_user_image);
                messageHeading = (TextView) view.findViewById(R.id.activity_view_conversation_message_list_item_heading);

                //Use the sender's ID to get the sender's image and first name
                Contact contact = database.getContact(senderId);
                if(senderId.equals(localUserId)){       //True if the local user sent this message
                    senderFirstName = "Me";
                }
                else{
                    senderFirstName = contact.getFirstName();
                }
                userImage.setImageBitmap(contact.getImageBitmap(100, 100, 6));
                messageHeading.setText(senderFirstName);
            }

            messageBody = (TextView) view.findViewById(R.id.activity_view_conversation_message_list_item_contents);
            messageBody.setText(message.getContents(null));

            break;              
        case Message.MESSAGE_TYPE_IMAGE:            //Image message
            view = vi.inflate(R.layout.activity_view_conversation_message_list_item_image, null);       //Inflate a list item template for displaying an image
            userImage = (ImageView) view.findViewById(R.id.activity_view_conversation_message_list_item_user_image);

            //Sender's first name
            messageHeading = (TextView) view.findViewById(R.id.activity_view_conversation_message_list_item_heading);
            Contact contact = database.getContact(senderId);
            if(senderId.equals(localUserId)){       //True if the local user sent this message
                senderFirstName = "Me";
            }
            else{
                senderFirstName = contact.getFirstName();
            }
            messageHeading.setText(senderFirstName);
            messageImage = (ImageView) view.findViewById(R.id.activity_view_conversation_message_list_item_image);
            String imageResourceId = null;
            //The message is a JSON object containing several fields, one of which is the file name which we will use to get the image
            try {
                JSONObject messageJSON = new JSONObject(message.getContents(null));
                String imagePath = Environment.getExternalStorageDirectory()+"/epicChat/resources/"+messageJSON.getString("fileName");
                int imageWidth = messageJSON.getInt("width");       //We want the dimensions in order to calculate the aspect ratio of the image
                int imageHeight = messageJSON.getInt("height");
                if(messageJSON.has("resourceId")){
                    imageResourceId = messageJSON.getString("resourceId");  //This is used when opening the image gallery
                }
                int displayWidth = 300;
                int displayHeight = (int) ((float) imageHeight / (float) imageWidth * (float) displayWidth);
                String imagePathFull = imagePath+displayWidth+displayHeight;            //For the caching
                Bitmap originalImage = null;
                //Check the bitmap cache exists. If not, reinstantiate it
                if(MainActivity.bitmapCache==null){                 //Cache is null
                    MainActivity.loadBitmapCache();
                }
                else{                                               //Cache is not null, so check it to see if this image is in it
                    originalImage = MainActivity.bitmapCache.get(imagePathFull);
                }
                if(originalImage==null){        //True if the bitmap was not in the cache. So we must load from disk instead
                    new Utils.LoadBitmapAsync(imagePath, messageImage, displayWidth, displayHeight, MainActivity.bitmapCache).execute();
                    messageImage.getLayoutParams().height = displayHeight;
                }
                else{
                    messageImage.setImageBitmap(originalImage);
                }
            }
            catch (JSONException e) {
                Log.e(TAG, "Error reading image JSON: "+e.toString());
            }
            if(imageResourceId!=null){      //Only attach the listener if we got a valid resource ID
                final String recourceIdFinal = imageResourceId;
                final String conversationIdFinal =  message.getUserList();
                messageImage.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent showConversationImageGalleryIntent = new Intent(context, ViewConversationImageGalleryActivity.class);
                        showConversationImageGalleryIntent.putExtra("conversationId", conversationIdFinal);
                        showConversationImageGalleryIntent.putExtra("resourceId", recourceIdFinal);
                        startActivityForResult(showConversationImageGalleryIntent, ACTION_SHOW_CONVERSATION_IMAGE_GALLERY);
                    }
                });
            }
            userImage.setImageBitmap(contact.getImageBitmap(100, 100, 6));
            break;
        case Message.MESSAGE_TYPE_INVALID:
        default:
            break;
        }

        //Some layout items are present in all layouts. Typically these are the status indicator and the message time
        RelativeLayout itemLayout = (RelativeLayout) view.findViewById(R.id.activity_view_conversation_message_list_item_wrapper);
        //If the message is from the local user, give it a subtle grey background
        if(localUserId.equals(message.getFromUser())){
            itemLayout.setBackgroundColor(Color.parseColor("#E9E9E9"));
        }
        else{
            itemLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));
        }
        TextView messageTimeText = (TextView) view.findViewById(R.id.activity_view_conversation_message_list_item_time);
        messageTimeText.setText(message.getFormattedTime());

        ImageView messageStatusImage = (ImageView) view.findViewById(R.id.activity_view_conversation_message_list_item_ack);
        //Set the status image according to the status of the message
        switch(message.getStatus()){
        case Message.MESSAGE_STATUS_PENDING:        //Pending messages should have a red dot
            messageStatusImage.setImageResource(R.drawable.red_dot_8dp);
            messageStatusImage.setVisibility(View.VISIBLE);
            break;
        case Message.MESSAGE_STATUS_ACK_SERVER:     //Messages that reached the server should have an orange dot
            messageStatusImage.setImageResource(R.drawable.orange_dot_8dp);
            messageStatusImage.setVisibility(View.VISIBLE);
            break;
        case Message.MESSAGE_STATUS_ACK_RECIPIENT:  //Messages that reached the recipient should have an green dot
            messageStatusImage.setImageResource(R.drawable.green_dot_8dp);
            messageStatusImage.setVisibility(View.VISIBLE);
            break;
        case Message.MESSAGE_STATUS_NOT_SET:        //Not set typically means the message came from another user, in which case the status image should be hidden
        default:                                    //Also default here
            messageStatusImage.setVisibility(View.INVISIBLE);
            break;
        }           
        return view;
    }
}

1 个答案:

答案 0 :(得分:1)

由于没有其他声明与if匹配,这可能是由于查看回收。当ListView中的项目滚动离开屏幕时,操作系统会将其删除并以与删除时相同的状态将其移回适配器。这意味着您需要在不是本地用户的消息时设置背景颜色。