pul*_*ion 4 android android-layout
当您与某人聊天时,我正在尝试开发类似 Activity 的 Whatsapp。我已经能够创建如下内容:
此处的聊天消息有 2 种类型 - 已发送和已接收。我希望收到的消息在左侧,发送的消息在右侧。为此,我创建了一个带有 LinearLayoutManager 的 RecyclerView 左侧和右侧对齐的以下布局:
接收消息的布局,即显示在左侧。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:background="@drawable/message_view_border">
<!--The message text-->
<TextView
android:id="@+id/message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"/>
<!--the timestamp-->
<TextView
android:id="@+id/time_stamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/message_content"
android:textStyle="bold"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
已发送消息的布局,即显示在右侧。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@drawable/message_view_border"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:layout_gravity="right"
android:gravity="right">
<!--The message text-->
<TextView
android:id="@+id/message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"/>
<!--the timestamp-->
<TextView
android:id="@+id/time_stamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/message_content"
android:textStyle="bold"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
问题:正如您在图像中看到的,右侧显示的消息(带有文本“rtdfg”)没有这样做。我不明白,为什么即使在相对布局上将 layout_gravity 设置为正确之后它也不会这样做。
任何人都可以阐明为什么会发生这种情况以及如何将其与右侧对齐?
编辑 1:我正在提供我正在做的工作供您参考的活动。
public class ChatActivity extends AppCompatActivity {
private ChatMessagesAdapter chatMessagesAdapter;
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//Get the root view that is the recycler view
ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this
.findViewById(android.R.id.content)).getChildAt(0);
recyclerView = (RecyclerView) viewGroup.findViewById(R.id.chart_activity_recycler_view);
//Set up the layout manager for the RecyclerView
linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
//Attach the adapter to the RecyclerView
chatMessagesAdapter = new ChatMessagesAdapter();
recyclerView.setAdapter(chatMessagesAdapter);
//Retrieve the added text
final EditText typedText = (EditText)viewGroup.findViewById(R.id.typed_message);
//Setup the listener on the send button.
Button sendButton = (Button)viewGroup.findViewById(R.id.send_button);
sendButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//On clicking the send button, update the adapter source and as the adapter source gets updated,
//trigger notification of the adapter with the updated data source.
//Secondly, ensure that the type of message that gets displayed varies for Sender versus Receiver
//as in Left vs Right
//If the "typed" message is empty then no point in sending it.
String typedMessageText = typedText.getText().toString();
if(typedMessageText.isEmpty()){
return;
}
//Construct the message typed by the Sender
Message messageFromSender = new Message();
//Set the message text from the typed message EditText
messageFromSender.setMessageText(typedText.getText().toString());
messageFromSender.setUserStatus(Message.SENDER);
//For the timestamp, retrieve the time-stamp from the system
messageFromSender.setTimeStamp(System.currentTimeMillis()/1000L);
chatMessagesAdapter.getChatMessagesSource().add(messageFromSender);
//Now, notify the adapter of the change in source
chatMessagesAdapter.notifyDataSetChanged();
}
});
}
private class ChatMessagesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
//Initialize the source from the JSON file having messages
private List<Message> messageList = getListOfSenderMessagesFromJSONSource();
@Override
public int getItemViewType(int position){
int viewType = messageList.get(position).getUserStatus();
if(viewType == Message.RECEIVER){
return Message.RECEIVER;
}
else if(viewType == Message.SENDER){
return Message.SENDER;
}
else if(viewType == Message.DATE_DIVIDER){
return Message.DATE_DIVIDER;
}
return -1;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){
//Add the code for constructing a ViewHolder
LayoutInflater inflater = LayoutInflater.from(ChatActivity.this);
RelativeLayout viewGroup1;
RecyclerView.ViewHolder viewHolder = null;
switch(viewType){
case Message.RECEIVER:
viewGroup1 = (RelativeLayout) inflater.inflate(R.layout.layout_chat_message_receiver, viewGroup, false);
viewHolder = new ChatMessageViewHolder(viewGroup1);
break;
case Message.SENDER:
viewGroup1 = (RelativeLayout) inflater.inflate(R.layout.layout_chat_message_sender, viewGroup, false);
viewHolder = new ChatMessageViewHolder(viewGroup1);
break;
default: //I know its not a good idea to return a receiver message template as default but for now it suffices
viewGroup1 = (RelativeLayout) inflater.inflate(R.layout.layout_chat_message_receiver, viewGroup, false);
viewHolder = new ChatMessageViewHolder(viewGroup1);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position){
switch(viewHolder.getItemViewType()){
case Message.RECEIVER:
((ChatMessageViewHolder)viewHolder).bindMessage(messageList.get(position));
break;
case Message.SENDER:
((ChatMessageViewHolder)viewHolder).bindMessage(messageList.get(position));
break;
}
}
@Override
public int getItemCount(){
return messageList.size();
}
private List<Message> getListOfSenderMessagesFromJSONSource(){
List<Message> messageList = new ArrayList<>();
//Parse the given JSONFile to get the individual messages
//Name of the file: sampleChats.json
Message chatMessage = null;
try {
JSONArray rootJSONArray = new JSONArray(Message.chatMessagesJSONString);
JSONArray level1JSONArray = (JSONArray)rootJSONArray.get(0);
JSONObject jsonObjectInsideLevel1Array = level1JSONArray.getJSONObject(0);
JSONObject messageObject = jsonObjectInsideLevel1Array.getJSONObject("message").getJSONObject("pn_gcm").getJSONObject("data");
/*Retrieved message object has the following structure
"data": {
"name": "Dr. Renu Gupta",
"userType": "doctor",
"timestamp": 1480535381,
"senderId": "1578",
"text": "Hi Fgdfgdgf!",
"type": "chat",
"cardType": "text",
"notificationType": "QChat"
}
* */
//Populate the fields with the fields from JSON data
String senderName = messageObject.getString("name");
String userType = messageObject.getString("userType");
long timeStamp = messageObject.getInt("timestamp");
long senderId = messageObject.getInt("senderId");
String messageText = messageObject.getString("text");
String messageType = messageObject.getString("type");
String cardType = messageObject.getString("cardType");
String notificationType = messageObject.getString("notificationType");
//Populate the message list with the retrieved JSON object
chatMessage = new Message();
chatMessage.setSenderName(senderName);
chatMessage.setUserType(userType);
chatMessage.setSenderID(senderId);
chatMessage.setTimeStamp(timeStamp);
chatMessage.setMessageText(messageText);
chatMessage.setMessageType(messageType);
chatMessage.setCardType(cardType);
chatMessage.setNotificationType(notificationType);
//Don't forget to set the sender status
chatMessage.setUserStatus(Message.RECEIVER);
} catch (JSONException e) {
e.printStackTrace();
}
messageList.add(chatMessage);
return messageList;
}
public List<Message> getChatMessagesSource(){
return messageList;
}
}
private class ChatMessageViewHolder extends RecyclerView.ViewHolder{
//Root view
private View messageView;
//Child views
private TextView chatMessageContent;
private TextView timeStamp;
private Message toBeBindedChatMessage;
Drawable placeHolder;
public ChatMessageViewHolder(View displayMessageView){
super(displayMessageView);
messageView = displayMessageView;
chatMessageContent = (TextView)messageView.findViewById(R.id.message_content);
timeStamp = (TextView)messageView.findViewById(R.id.time_stamp);
placeHolder = getResources().getDrawable(R.drawable.dante_dmc_623_350);
}
public void bindMessage(Message toBeBindedChatMessage){
this.toBeBindedChatMessage = toBeBindedChatMessage;
//Bind the view with messsage object
//Bind the message content
chatMessageContent.setText(toBeBindedChatMessage.getMessageText());
//Bind the Time Stamp
timeStamp.setText(Message.timeStampToHH_MMFormat(toBeBindedChatMessage.getTimeStamp()*1000));
}
}
}
Run Code Online (Sandbox Code Playgroud)
要快速修复,请执行此操作。
RelativeLayout的宽度应该match_parent使其占据其容器的整个宽度。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@drawable/message_view_border"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp">
<!--The message text-->
<TextView
android:id="@+id/message_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:textStyle="bold"/>
<!--the timestamp-->
<TextView
android:id="@+id/time_stamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/message_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:textStyle="bold"/>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7134 次 |
| 最近记录: |