Firebase Chat的左右对齐

时间:2015-08-06 05:46:14

标签: android firebase android-adapter firebase-realtime-database firebaseui

您好我正在创建一个基于Firebase和Parse的聊天应用程序。在此我提到官方Firebase聊天示例。聊天工作正常,但来电和发送聊天都是一个接一个地显示。像这样,例如

作者:发件人
消息:你好 作者:接收人
消息:你好吗?

我只需要聊天看起来像左右对齐的应用和其他聊天。

在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);
}

ChatListAdapter

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>

2 个答案:

答案 0 :(得分:1)

布局文件:

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>

在适配器文件中

<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"/>

答案 1 :(得分:1)

最后我找到了一个解决方案,我刚刚在编码中添加了一个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));
    }

}