Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ListView上的聊天气泡对齐_Android_Android Layout_Firebase_Firebase Realtime Database_Getview - Fatal编程技术网

Android ListView上的聊天气泡对齐

Android ListView上的聊天气泡对齐,android,android-layout,firebase,firebase-realtime-database,getview,Android,Android Layout,Firebase,Firebase Realtime Database,Getview,我已经将我的android应用程序连接到Firebase,我正在发送带有“name”和“status”属性的消息。正在发送或接收的状态。 根据状态将聊天气泡左/右对齐时,我遇到了问题 下面是代码片段 message_row.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layou

我已经将我的android应用程序连接到Firebase,我正在发送带有“name”和“status”属性的消息。正在发送或接收的状态。 根据状态将聊天气泡左/右对齐时,我遇到了问题

下面是代码片段

message_row.xml

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

<LinearLayout
    android:id="@+id/singleMessageContainer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/message_bubble_received">

<TextView
    android:id="@+id/username_text_view"
    android:layout_width="wrap_content"
    android:paddingLeft="10dip"
    android:layout_margin="5dip"
    android:text="Hello bubbles!"
    android:layout_height="wrap_content"/>

<TextView
    android:id="@+id/message_text_view"
    android:layout_width="wrap_content"
    android:paddingLeft="1dip"
    android:layout_margin="5dip"
    android:text="Hello bubbles!"
    android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ECECEC">

<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:divider="@null"
android:layout_marginTop="10dp"
android:listSelector="@android:color/transparent"
android:transcriptMode="alwaysScroll"
android:layout_marginBottom="80dp"/>

<RelativeLayout
android:id="@+id/form"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="vertical" >

<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">

<EditText
    android:id="@+id/message_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_gravity="left"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="5dp"
    android:layout_weight="3"
    android:autoText="true"
    android:background="@drawable/note_backgroud"
    android:hint="Write your question here"
    android:minLines="1"
    android:paddingLeft="20dp"
    android:paddingRight="8dp"
    android:paddingBottom="16dp"
    android:paddingTop="8dp"/>

<ImageButton
    android:id="@+id/cameraButton"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:background="@null"
    android:src="@drawable/camera"
    android:gravity="top|right"
    android:layout_marginRight="8dp"
    android:layout_marginLeft="-52dp"
    />

<ImageButton
    android:id="@+id/chatSendButton"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:src="@drawable/sent"
    android:background="@null"
    android:layout_gravity="center"
    android:layout_marginRight="8dp"
    android:layout_marginLeft="8dp"
    android:text="Send"
    android:onClick="onSendButtonClick"
    android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

活动\u main.xml

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

<LinearLayout
    android:id="@+id/singleMessageContainer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/message_bubble_received">

<TextView
    android:id="@+id/username_text_view"
    android:layout_width="wrap_content"
    android:paddingLeft="10dip"
    android:layout_margin="5dip"
    android:text="Hello bubbles!"
    android:layout_height="wrap_content"/>

<TextView
    android:id="@+id/message_text_view"
    android:layout_width="wrap_content"
    android:paddingLeft="1dip"
    android:layout_margin="5dip"
    android:text="Hello bubbles!"
    android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ECECEC">

<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:divider="@null"
android:layout_marginTop="10dp"
android:listSelector="@android:color/transparent"
android:transcriptMode="alwaysScroll"
android:layout_marginBottom="80dp"/>

<RelativeLayout
android:id="@+id/form"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="vertical" >

<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">

<EditText
    android:id="@+id/message_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_gravity="left"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="5dp"
    android:layout_weight="3"
    android:autoText="true"
    android:background="@drawable/note_backgroud"
    android:hint="Write your question here"
    android:minLines="1"
    android:paddingLeft="20dp"
    android:paddingRight="8dp"
    android:paddingBottom="16dp"
    android:paddingTop="8dp"/>

<ImageButton
    android:id="@+id/cameraButton"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:background="@null"
    android:src="@drawable/camera"
    android:gravity="top|right"
    android:layout_marginRight="8dp"
    android:layout_marginLeft="-52dp"
    />

<ImageButton
    android:id="@+id/chatSendButton"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:src="@drawable/sent"
    android:background="@null"
    android:layout_gravity="center"
    android:layout_marginRight="8dp"
    android:layout_marginLeft="8dp"
    android:text="Send"
    android:onClick="onSendButtonClick"
    android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

下面是MessageAdapter的代码snipet

MessageAdapter.java

public abstract class MessageAdapter<T> extends BaseAdapter {

private Query mRef;
private Class<T> mModelClass;
private int mLayout;
private LayoutInflater mInflater;
private List<T> mModels;
private List<String> mKeys;
private ChildEventListener mListener;
private Context context;
private LinearLayout message_row;
private ProgressDialog mProgressDialog;


public MessageAdapter(Query mRef, Class<T> mModelClass, int mLayout, Activity activity) {
    this.mRef = mRef;
    this.mModelClass = mModelClass;
    this.mLayout = mLayout;
    this.context = activity.getApplicationContext();
    mInflater = activity.getLayoutInflater();
    mModels = new ArrayList<T>();
    mKeys = new ArrayList<String>();
    mProgressDialog = new ProgressDialog(activity);
    mProgressDialog.show();
    // 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(MessageAdapter.this.mModelClass);
            String key = dataSnapshot.getKey();

            // Insert into the correct location, based on previousChildName
            if (previousChildName == null) {
                mModels.add(0, model);
                mKeys.add(0, key);
            } else {
                int previousIndex = mKeys.indexOf(previousChildName);
                int nextIndex = previousIndex + 1;
                if (nextIndex == mModels.size()) {
                    mModels.add(model);
                    mKeys.add(key);
                } else {
                    mModels.add(nextIndex, model);
                    mKeys.add(nextIndex, key);
                }
            }
            notifyDataSetChanged();
            mProgressDialog.dismiss();
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            // One of the mModels changed. Replace it in our list and name mapping
            String key = dataSnapshot.getKey();
            T newModel = dataSnapshot.getValue(MessageAdapter.this.mModelClass);
            int index = mKeys.indexOf(key);

            mModels.set(index, 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 key = dataSnapshot.getKey();
            int index = mKeys.indexOf(key);

            mKeys.remove(index);
            mModels.remove(index);

            notifyDataSetChanged();
        }

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

            // A model changed position in the list. Update our list accordingly
            String key = dataSnapshot.getKey();
            T newModel = dataSnapshot.getValue(MessageAdapter.this.mModelClass);
            int index = mKeys.indexOf(key);
            mModels.remove(index);
            mKeys.remove(index);
            if (previousChildName == null) {
                mModels.add(0, newModel);
                mKeys.add(0, key);
            } else {
                int previousIndex = mKeys.indexOf(previousChildName);
                int nextIndex = previousIndex + 1;
                if (nextIndex == mModels.size()) {
                    mModels.add(newModel);
                    mKeys.add(key);
                } else {
                    mModels.add(nextIndex, newModel);
                    mKeys.add(nextIndex, key);
                }
            }
            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();
    mKeys.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) {
    LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (view == null) {
        view = mInflater.inflate(mLayout, viewGroup, false);
        message_row = (LinearLayout) view.findViewById(R.id.singleMessageContainer);
    }

    T model = mModels.get(i);
    Message m = (Message) model;
    Log.i("status", m.getStatus());
    if (m.getStatus().equals("sent")){
       message_row.setGravity(Gravity.LEFT);
       message_row.setBackgroundResource(R.drawable.message_bubble_received);
    }
    else {
        message_row.setGravity(Gravity.RIGHT);
            message_row.setBackgroundResource(R.drawable.message_bubble_sent);
   }
    // Call out to subclass to marshall this model into the provided view
    populateView(view, model);
    return view;
}

protected abstract void populateView(View v, T model);
}
公共抽象类MessageAdapter扩展了BaseAdapter{
私有查询mRef;
私人类;
私人内部布局;
私人停车场;
私有列表MMODEL;
私人名单;
私家子弟;
私人语境;
专用线路布局信息_行;
private ProgressDialog mProgressDialog;
公共消息适配器(查询mRef、类mModelClass、int-mLayout、活动){
this.mRef=mRef;
this.mModelClass=mModelClass;
this.mLayout=mLayout;
this.context=activity.getApplicationContext();
mInflater=activity.getLayoutFlater();
mModels=新的ArrayList();
mKeys=newarraylist();
mProgressDialog=新建进度对话框(活动);
mProgressDialog.show();
//查找所有子事件,然后将它们映射到我们自己的内部ArrayList,它支持ListView
mListener=this.mRef.addChildEventListener(新的ChildEventListener()){
@凌驾
公共void onChildAdded(DataSnapshot DataSnapshot,字符串previousChildName){
T model=dataSnapshot.getValue(MessageAdapter.this.mModelClass);
String key=dataSnapshot.getKey();
//根据previousChildName插入到正确的位置
如果(previousChildName==null){
mModels.add(0,模型);
mKeys.add(0,键);
}否则{
int-previousIndex=mKeys.indexOf(previousChildName);
int nextIndex=以前的索引+1;
如果(nextIndex==mModels.size()){
mModels.add(模型);
添加(键);
}否则{
mModels.add(nextIndex,model);
mKeys.add(nextIndex,key);
}
}
notifyDataSetChanged();
mProgressDialog.disclose();
}
@凌驾
公共void onChildChanged(DataSnapshot DataSnapshot,字符串s){
//其中一个MMODEL已更改。请在列表和名称映射中替换它
String key=dataSnapshot.getKey();
T newModel=dataSnapshot.getValue(MessageAdapter.this.mModelClass);
int index=mKeys.indexOf(键);
mModels.set(索引,新模型);
notifyDataSetChanged();
}
@凌驾
ChildRemoved上的公共void(DataSnapshot DataSnapshot){
//已从列表中删除模型。请将其从列表和名称映射中删除
String key=dataSnapshot.getKey();
int index=mKeys.indexOf(键);
移除(索引);
mModels.remove(索引);
notifyDataSetChanged();
}
@凌驾
onChildMoved公共void(DataSnapshot DataSnapshot,字符串previousChildName){
//模型在列表中的位置已更改。请相应地更新我们的列表
String key=dataSnapshot.getKey();
T newModel=dataSnapshot.getValue(MessageAdapter.this.mModelClass);
int index=mKeys.indexOf(键);
mModels.remove(索引);
移除(索引);
如果(previousChildName==null){
mModels.add(0,新模型);
mKeys.add(0,键);
}否则{
int-previousIndex=mKeys.indexOf(previousChildName);
int nextIndex=以前的索引+1;
如果(nextIndex==mModels.size()){
mModels.add(newModel);
添加(键);
}否则{
mModels.add(nextIndex,newModel);
mKeys.add(nextIndex,key);
}
}
notifyDataSetChanged();
}
@凌驾
取消后的公共无效(FirebaseError FirebaseError){
Log.e(“FirebaseListAdapter”,“侦听已取消,将不再进行更新”);
}
});
}
公共空间清理(){
//我们被毁灭了,放开我们的mListener,忘掉所有的MModel
mRef.removeEventListener(mListener);
mModels.clear();
mKeys.clear();
}
@凌驾
public int getCount(){
返回mModels.size();
}
@凌驾
公共对象getItem(int i){
返回mModels.get(i);
}
@凌驾
公共长getItemId(int i){
返回i;
}
@凌驾
公共视图getView(int i、视图视图、视图组视图组){
LayoutInflater vi=(LayoutInflater)context.getSystemService(context.LAYOUT\u INFLATER\u SERVICE);
如果(视图==null){
视图=最小平坦度。充气(最小布局、视图组、假);
message_row=(LinearLayout)view.findViewById(R.id.singleMessageContainer);
}
T model=mModels.get(i);
消息m=(消息)模型;
Log.i(“status”,m.getStatus());
if(m.getStatus().equals(“sent”)){
信息_row.setGravity(Gravity.LEFT);
消息行。setBackgroundResource(R.drawable。消息气泡已接收);
}
否则{
信息_row.setGravity(Gravity.RIGHT);
消息行。setBackgroundResource(R.drawable.message\u bubble\u sent);
}
//调用子类将此模型打包到提供的视图中
populateView(视图、模型);
返回视图;
}
受保护的抽象void populateView(视图v,T模型);
}
我注意到调用getView()的次数超过了列表中的计数(例如:如果我有2条消息,则调用getView()的次数为4到5次)。 使用当前代码,聊天泡泡始终位于左侧