Comment changer la couleur d'arrière-plan de chaque élément dans un ListView?


hlbak:

Je développe une application dotée d'une interface de messagerie texte (quelque chose comme Facebook Messenger, Whatsapp, etc.). Je veux pouvoir changer la couleur d'arrière-plan de toutes les bulles de discussion (a ListViewde TextViews) envoyées par l'utilisateur lorsqu'il choisit une nouvelle couleur (en a NavigationView).

Cependant, avec le code actuel que j'ai, je ne peux changer la couleur qu'après avoir EditTextcliqué à nouveau sur le bouton utilisé pour composer le message. Ou je ne peux modifier que la première bulle envoyée, mais dès que la couleur est modifiée.

Voici ce que j'ai essayé:

ItemColor1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v){

        Toast.makeText(activity, "Couleur mise à jour", Toast.LENGTH_SHORT).show();
        currentTheme = position;
        SharedPreferences.Editor editor = pref.edit();
        editor.putInt("indexColorSelected",currentTheme);
        editor.apply();
        chatAdapter.notifyDataSetChanged();
        //the following changes only the first message sent     
        for(int i=0; i<chatAdapter.getCount(); i++){
            ChatData message = chatMessageList.get(position);
            TextView msg = activity.findViewById(R.id.text);
            msg.setText(message.body);
            msg.setBackgroundResource(R.drawable.user_color1);
        }
    }
});

ChatData est une classe personnalisée que j'ai créée et qui ressemble à ceci:

public class ChatAdapter extends BaseAdapter {

    private static LayoutInflater inflater = null;
    private ArrayList<ChatData> chatMessageList;
    private Context mContext;

    ChatAdapter(Activity activity, ArrayList<ChatData> list) {
        mContext = activity;
        chatMessageList = list;
        inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    ...
}

Couleur dessinable:

    <corners
        android:bottomRightRadius="5dp"
        android:radius="40dp"/>

    <gradient
        android:angle="45"
        android:endColor="#01f1fa"
        android:startColor="#0189ff"
        android:type="linear" />

</shape>

getView() méthode de l'adaptateur:

public View getView(int position, View convertView, ViewGroup parent) {
    ChatData message = chatMessageList.get(position);
    View vi = convertView;

    if (convertView == null)
        vi = inflater.inflate(R.layout.msglist, parent, false);

    TextView msg = vi.findViewById(R.id.text);
    msg.setText(message.body);

    LinearLayout layout = vi.findViewById(R.id.message_layout);
    LinearLayout parent_layout = vi.findViewById(R.id.message_layout_parent);

    inflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // if message is mine then align to right
    if (message.isMine) {
        layout.setGravity(Gravity.RIGHT);

        int couleurBubble = getCouleurSelectionnee();

        switch(couleurBubble){
            case R.color.c1: msg.setBackgroundResource(R.drawable.user_color1); break;
            case R.color.c2: msg.setBackgroundResource(R.drawable.user_color2); break;
            case R.color.c3: msg.setBackgroundResource(R.drawable.user_color3); break;
            case R.color.c4: msg.setBackgroundResource(R.drawable.user_color4); break;
            case R.color.c5: msg.setBackgroundResource(R.drawable.user_color5); break;
            case R.color.c6: msg.setBackgroundResource(R.drawable.user_color6); break;
            case R.color.c7: msg.setBackgroundResource(R.drawable.user_color7); break;
            case R.color.c8: msg.setBackgroundResource(R.drawable.user_color8); break;
            default: break;
        }

        parent_layout.setGravity(Gravity.RIGHT);
    }
    // If not mine then align to left
    else {
        layout.setGravity(Gravity.LEFT);
        msg.setBackgroundResource(R.drawable.bot_chat);
        parent_layout.setGravity(Gravity.LEFT);
    }
    return vi;
}

Je ne sais pas vraiment où aller à partir d'ici, donc toute sorte d'aide serait appréciée. Si vous voulez que je vous fournisse plus de code, faites-le moi savoir et je le ferai.

Je vous remercie.

W0rmH0le:

Je partage comment je le ferais. Peut-être que cela peut vous aider. Il y a un problème étrange parce que vous appelez notifyDataSetChanged(). Ce serait suffisant pour redessiner toutes les bulles de message.

Mon idée est:

Ajoutez une intvariable à la classe d'adaptateur ( mColorResource). Cette variable pointera vers le dessinable approprié qui devrait être utilisé (comme R.drawable.user_color1).

public class ChatAdapter extends BaseAdapter {

    int mColorResource;

    ChatAdapter(Activity activity, ArrayList<ChatData> list, int initialColorResource) {
        mContext = activity;
        chatMessageList = list;
        inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // You must receive the color on the construtor
        mColorResource = initialColor;
    }

    // Use this method to update the color (when user select a new color)
    public void setColor(int newColorResource) {
        mColorResource = newColorResource;
    }


    public View getView(int position, View convertView, ViewGroup parent) {
        ...
        // Note how this if-else is cleaner now
        if (message.isMine) {
            layout.setGravity(Gravity.RIGHT);
            msg.setBackgroundResource(mColorResource);
            parent_layout.setGravity(Gravity.RIGHT);
        } else {
            layout.setGravity(Gravity.LEFT);
            msg.setBackgroundResource(R.drawable.bot_chat);
            parent_layout.setGravity(Gravity.LEFT);
        }
        ...
    }
}

Ensuite, lorsqu'une couleur est sélectionnée, trouvez le dessin approprié en fonction de la vue cliquée et transmettez-le à l'adaptateur:

ItemColor1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v){
        Toast.makeText(activity, "Couleur mise à jour", Toast.LENGTH_SHORT).show();
        currentTheme = position;

        SharedPreferences.Editor editor = pref.edit();
        editor.putInt("indexColorSelected", currentTheme);
        editor.apply();

        // Here, you send the proper drawable...
        // I'm not sure how you convert color selected to the drawable
        // So, add your logic to convert the button clicked to a drawable here
        // like R.drawable.user_color1
        chatAdapter.setColor(R.drawable.NAME_OF_THE_COLOR);

        // Request to re-draw all items from the list (all bubbles)
        chatAdapter.notifyDataSetChanged();
    }
});

Aussi, sur votre activité, vous créez l'adaptateur avec la dernière couleur utilisée. Quelque chose comme:

@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ....
    // Set a default color (if user is open you app for the first time)
    int chatColor = R.drawable.user_color1;

    // Add your logic to read the shared preference and convert that last color used to a valid drawable.
    // Like chatColor = pref.getInt(indexColorSelected, R.drawable.user_color1) etc....

    // Set the color in the adapter.
    chatAdapter = newAdapter(this, mChatDataList, chatColor);
}

Articles connexes