Выравнивание по левому и правому краю для чата Firebase

Привет, я создаю приложение для чата на основе Firebase и Parse. В этом я упомянул официальный пример чата Firebase. Чат работает отлично, но входящий и исходящий чат отображаются один за другим. Вот так, например

автор: отправитель
сообщение: привет
автор: получатель
сообщение: привет как дела?

Мне просто нужно, чтобы чат выглядел как приложение Whats и другой чат с выравниванием по левому и правому краям.

В чате Firebase они используют два адаптера: один — FirebaseListAdapter (общий, который расширяет BaseAdapter), а другой — ChatListAdapter (который расширяет FirebaseCahtListAdapter). Я не знаю, где мне нужно изменить код. Пожалуйста, помогите мне исправить это.

FirebaseListAdapter

public abstract class FirebaseListAdapter<T> extends BaseAdapter {

private Query mRef;
private Class<T> mModelClass;
private int mLayout;
private LayoutInflater mInflater, recieveInflater;
private List<T> mModels;
private Map<String, T> mModelKeys;
private ChildEventListener mListener;


/**
 * @param mRef        The Firebase location to watch for data changes. Can also be a slice of a location, using some
 *                    combination of <code>limit()</code>, <code>startAt()</code>, and <code>endAt()</code>,
 * @param mModelClass Firebase will marshall the data at a location into an instance of a class that you provide
 * @param mLayout     This is the mLayout used to represent a single list item. You will be responsible for populating an
 *                    instance of the corresponding view with the data from an instance of mModelClass.
 * @param activity    The activity containing the ListView
 */
public FirebaseListAdapter(Query mRef, Class<T> mModelClass, int mLayout, Activity activity) {
    this.mRef = mRef;
    this.mModelClass = mModelClass;
    this.mLayout = mLayout;
    mInflater = activity.getLayoutInflater();
    mModels = new ArrayList<T>();
    mModelKeys = new HashMap<String, T>();
    // Look for all child events. We will then map them to our own internal ArrayList, which backs ListView
    mListener = this.mRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {

            T model = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
            mModelKeys.put(dataSnapshot.getKey(), model);

            // Insert into the correct location, based on previousChildName
            if (previousChildName == null) {
                mModels.add(0, model);
            } else {
                T previousModel = mModelKeys.get(previousChildName);
                int previousIndex = mModels.indexOf(previousModel);
                int nextIndex = previousIndex + 1;
                if (nextIndex == mModels.size()) {
                    mModels.add(model);
                } else {
                    mModels.add(nextIndex, model);
                }
            }

            notifyDataSetChanged();
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            // One of the mModels changed. Replace it in our list and name mapping
            String modelName = dataSnapshot.getKey();
            T oldModel = mModelKeys.get(modelName);
            T newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
            int index = mModels.indexOf(oldModel);

            mModels.set(index, newModel);
            mModelKeys.put(modelName, newModel);

            notifyDataSetChanged();
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

            // A model was removed from the list. Remove it from our list and the name mapping
            String modelName = dataSnapshot.getKey();
            T oldModel = mModelKeys.get(modelName);
            mModels.remove(oldModel);
            mModelKeys.remove(modelName);
            notifyDataSetChanged();
        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {

            // A model changed position in the list. Update our list accordingly
            String modelName = dataSnapshot.getKey();
            T oldModel = mModelKeys.get(modelName);
            T newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
            int index = mModels.indexOf(oldModel);
            mModels.remove(index);
            if (previousChildName == null) {
                mModels.add(0, newModel);
            } else {
                T previousModel = mModelKeys.get(previousChildName);
                int previousIndex = mModels.indexOf(previousModel);
                int nextIndex = previousIndex + 1;
                if (nextIndex == mModels.size()) {
                    mModels.add(newModel);
                } else {
                    mModels.add(nextIndex, newModel);
                }
            }
            notifyDataSetChanged();
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            Log.e("FirebaseListAdapter", "Listen was cancelled, no more updates will occur");
        }

    });
}

public void cleanup() {
    // We're being destroyed, let go of our mListener and forget about all of the mModels
    mRef.removeEventListener(mListener);
    mModels.clear();
    mModelKeys.clear();
}

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

@Override
public Object getItem(int i) {
    return mModels.get(i);
}

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

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    if (view == null) {

        view = mInflater.inflate(mLayout, viewGroup, false);

    }

    T model = mModels.get(i);

    // Call out to subclass to marshall this model into the provided view
    populateView(view, model);
    return view;
}

/**
 * Each time the data at the given Firebase location changes, this method will be called for each item that needs
 * to be displayed. The arguments correspond to the mLayout and mModelClass given to the constructor of this class.
 * <p/>
 * Your implementation should populate the view using the data contained in the model.
 *
 * @param v     The view to populate
 * @param model The object containing the data used to populate the view
 */
protected abstract void populateView(View v, T model);
}

Адаптер списка чатов

public class ChatListAdapter extends FirebaseListAdapter<Chat> {

// The mUsername for this client. We use this to indicate which messages originated from this user
private String mUsername;
Activity activity;
LayoutInflater inflater;

public ChatListAdapter(Query ref, Activity activity, int layout, String mUsername) {
    super(ref, Chat.class, layout, activity);
    this.mUsername = mUsername;
    this.activity = activity;
    this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

/**
 * Bind an instance of the <code>Chat</code> class to our view. This method is called by <code>FirebaseListAdapter</code>
 * when there is a data change, and we are given an instance of a View that corresponds to the layout that we passed
 * to the constructor, as well as a single <code>Chat</code> instance that represents the current data to bind.
 *
 * @param view A view instance corresponding to the layout we passed to the constructor.
 * @param chat An instance representing the current state of a chat message
 */
@Override
protected void populateView(View view, Chat chat) {

    String author = chat.getAuthor();
    TextView authorText = (TextView) view.findViewById(R.id.author);
    TextView messageText = (TextView) view.findViewById(R.id.message);

    authorText.setText(author + ": ");
    // If the message was sent by this user, design it differently
    if (author != null && author.equals(mUsername)) {
        authorText.setTextColor(view.getResources().getColor(R.color.lblFromName));
        authorText.setGravity(Gravity.RIGHT | Gravity.END);

        messageText.setText(chat.getMessage());
        messageText.setGravity(Gravity.RIGHT);
        messageText.setBackground(view.getResources().getDrawable(R.drawable.bg_msg_you));

    } else {
        authorText.setTextColor(view.getResources().getColor(R.color.lblFromName));
        authorText.setGravity(Gravity.LEFT | Gravity.START);

        messageText.setText(chat.getMessage());
        messageText.setGravity(Gravity.LEFT);
        messageText.setBackground(view.getResources().getDrawable(R.drawable.bg_msg_from));
    }

}

}

Файл макета, используемый в CahtListAdapter

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/author"
    android:layout_width="wrap_content"
    android:text="Name"
    android:padding="5dp"
    android:textStyle="italic"
    android:textSize="12dp"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Content"
    android:paddingBottom="5dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="5dp"
    android:textSize="16dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"/>
</LinearLayout>

person Encipherer    schedule 06.08.2015    source источник
comment
можете ли вы опубликовать файл макета, используемый в «ChatListAdapter»   -  person Satyen Udeshi    schedule 06.08.2015
comment
Привет, я добавил, пожалуйста, проверьте   -  person Encipherer    schedule 06.08.2015
comment
ссылайтесь на свой «LinearLayout» в адаптере и уделяйте серьезное внимание LinearLayout.   -  person Satyen Udeshi    schedule 06.08.2015
comment
Я уже пробовал это, но не работал. Можете ли вы привести мне пример?   -  person Encipherer    schedule 06.08.2015
comment
я сам пробовал с вашей раскладкой в ​​редакторе и она нормально работает,   -  person Satyen Udeshi    schedule 06.08.2015


Ответы (2)


Файл макета:

LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical">

<TextView
    android:id="@+id/author"
    android:layout_width="wrap_content"
    android:text="Name"
    android:padding="5dp"
    android:textStyle="italic"
    android:textSize="12dp"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Content"
    android:paddingBottom="5dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="5dp"
    android:textSize="16dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"/>

LinearLayout>

В вашем файле адаптера


if (author != null && author.equals(mUsername)) {
llMessage.setGravity(Gravity.RIGHT | Gravity.END);
}else{
llMessage.setGravity(Gravity.LEFT | Gravity.START);
}

person Satyen Udeshi    schedule 06.08.2015
comment
Нашел решение бро :) - person Encipherer; 06.08.2015
comment
хорошо :), затем опубликуйте это, чтобы оно было полезно другим пользователям SO. - person Satyen Udeshi; 06.08.2015

Наконец я нашел решение для этого, я просто добавил LayoutGravity в кодирование, а оттуда установил Gravity.

Внутри ChatListAdapter

@Override
protected void populateView(View view, Chat chat) {

    String author = chat.getAuthor();
    TextView authorText = (TextView) view.findViewById(R.id.author);
    TextView messageText = (TextView) view.findViewById(R.id.message);

    authorText.setText(author + ": ");
    // If the message was sent by this user, design it differently
    if (author != null && author.equals(mUsername)) {

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT);
        params.weight = 1.0f;
        params.gravity = Gravity.RIGHT;

        authorText.setTextColor(view.getResources().getColor(R.color.lblFromName));
        authorText.setLayoutParams(params);

        messageText.setText(chat.getMessage());
        messageText.setBackground(view.getResources().getDrawable(R.drawable.bg_msg_you));
        messageText.setLayoutParams(params);

    } else {
        authorText.setTextColor(view.getResources().getColor(R.color.lblFromName));
        authorText.setGravity(Gravity.LEFT | Gravity.START);

        messageText.setText(chat.getMessage());
        messageText.setGravity(Gravity.LEFT);
        messageText.setBackground(view.getResources().getDrawable(R.drawable.bg_msg_from));
    }

}
person Encipherer    schedule 06.08.2015