Custom Array adapter for chat app

江枫思渺然 提交于 2019-12-23 03:31:15

问题


I'm creating Bluetooth chat app and I'm kinda new to Android programming. Atm my app can manage bluetooth connection and send/receive data. My problem is populating list view with strings because I'm not so good with creating Custom ArrayAdapters. I have 2 shapes (Red and Blue bubble) for sent and received messages (R.drawable.rounded_corner and R.drawable.rounded_corner_get). I'm managing bluetooth connection(ConnectedThread) in activity(MessengerActivity) as you can see in code bellow. So if anyone knows how can I create Custom ArrayAdapter for given code or knows any other similar StackOverflow question, I could really use help.

public class MessengerActivity extends AppCompatActivity {
protected static final int MESSAGE_READ = 5;
ConnectedThread mConnectedThhread;
static BluetoothSocket blueSocket;
String nameOfDevice;
public String message;
Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Log.i("tag", "in handler");
        switch (msg.what) {
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                String string = new String(readBuf);
                try {
                    getMessage(string);
                } catch (Exception e) {}
                break;
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_messenger);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    blueSocket = BluetoothSocketGet.blueSocket;
    nameOfDevice = blueSocket.getRemoteDevice().getName();
    toolbar.setTitle(nameOfDevice);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    mConnectedThhread = new ConnectedThread(blueSocket);
    mConnectedThhread.start();

}

public void messageText(View v) {
    EditText edit = (EditText) findViewById(R.id.textMessage);
    String string;
    string = edit.getText().toString();
    edit.setText("");
    mConnectedThhread.write(string.getBytes());
}

public void getMessage(String s) {
    message=s;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_messenger, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    if (id == R.id.action_settings) {
        Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
        startActivity(intent);
    }
    return super.onOptionsItemSelected(item);
}

protected class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {

        mmSocket = socket;

        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the input and output streams, using temp objects because
        // member streams are final
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        byte[] buffer;  // buffer store for the stream
        int bytes; // bytes returned from read()

        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                // Read from the InputStream
                buffer = new byte[1024];
                bytes = mmInStream.read(buffer);
                // Send the obtained bytes to the UI activity
                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();

            } catch (IOException e) {
                break;
            }
        }
    }

    /* Call this from the main activity to send data to the remote device */
    public void write(byte[] bytes) {
        try {
            mmOutStream.write(bytes);
        } catch (IOException e) {
        }
    }

    /* Call this from the main activity to shutdown the connection */
    public void cancel() {
        if (mmInStream != null) {
            try {
                mmInStream.close();
            } catch (IOException e) {
            }
        }
        if (mmOutStream != null) {
            try {
                mmOutStream.close();
            } catch (IOException e) {
            }
        }
        if (mmSocket != null) {
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
        }
    }
}}

XML for MessengerActivity:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.milan.redtooth.MessengerActivityFragment"
tools:showIn="@layout/activity_messenger">

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:transcriptMode="alwaysScroll"
    android:stackFromBottom="true"
    android:layout_weight="1"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:id="@+id/listMessages">
</ListView>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_alignParentBottom="true">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textMessage"
        android:layout_weight="1"
        android:layout_gravity="bottom" />

    <ImageButton
        android:onClick="messageText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/sendMessage"
        android:layout_gravity="bottom"
        android:src="@drawable/ic_send_white_18dp" />

</LinearLayout>


回答1:


=> You have to define two list row layouts

1). item_send.xml for Sending message

    <?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="vertical" >

        <TextView
            android:id="@+id/msgr"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5sp"
            android:layout_gravity="right"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="20dp"
            android:background="@drawable/ic_send"
            android:shadowColor="@color/textShadow"
            android:shadowDx="1"
            android:shadowDy="1"
            android:text="Medium Texts"
            android:textColor="@color/textColor"
            android:textSize="18sp" />

    </LinearLayout>

2). item_receive.xml for Receiving message

    <?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="vertical" >

        <TextView
            android:id="@+id/msgr"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5sp"
            android:layout_marginBottom="5dp"
            android:layout_marginRight="20dp"
            android:background="@drawable/ic_receive"
            android:shadowColor="@color/textShadow"
            android:shadowDx="1"
            android:layout_gravity="left"
            android:shadowDy="1"
            android:text="Medium Text"
            android:textColor="@color/textColor"
            android:textSize="18sp" />

    </LinearLayout>

    [Replace the TextView Background with your own 9 patch bubble image for each row_layout (send and received)]

=> Now you have to create custom array adapter

    class ChatArrayAdapter extends ArrayAdapter<ChatMessage> {

        private TextView chatText;
        private List<ChatMessage> chatMessageList = new ArrayList<ChatMessage>();
        private Context context;

        @Override
        public void add(ChatMessage object) {
            chatMessageList.add(object);
            super.add(object);
        }

        public ChatArrayAdapter(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
            this.context = context;
        }

        public int getCount() {
            return this.chatMessageList.size();
        }

        public ChatMessage getItem(int index) {
            return this.chatMessageList.get(index);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ChatMessage chatMessageObj = getItem(position);
            View row = convertView;
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if (chatMessageObj.left) {
                row = inflater.inflate(R.layout.item_send, parent, false);
            } else {
                row = inflater.inflate(R.layout.item_receive, parent, false);
            }
            chatText = (TextView) row.findViewById(R.id.msgr);
            chatText.setText(chatMessageObj.message);
            return row;
        }
    }

=> In Your Main Activity onCreate() method, just place following code

ChatArrayAdapter chatArrayAdapter = new ChatArrayAdapter(getApplicationContext(), R.layout.item_send);
    ListView listView = (ListView) findViewById(R.id.listMessage);
    listView.setAdapter(chatArrayAdapter);    
    listView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setAdapter(chatArrayAdapter);
    //to scroll the list view to bottom on data change
    chatArrayAdapter.registerDataSetObserver(new DataSetObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            listView.setSelection(chatArrayAdapter.getCount() - 1);
        }
    });

=> In Your Main Activity, just place following methods and call it on button click

        private boolean receiveMessage(String msg) {
            chatArrayAdapter.add(new ChatMessage(false, msg));
            return true;
        }


        private boolean sendMessage(String msg) {
            chatArrayAdapter.add(new ChatMessage(true, msg));
            return true;
        }

        enter code here


来源:https://stackoverflow.com/questions/37081724/custom-array-adapter-for-chat-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!