I was wondering how WhatsApp handles the time shown in every message.
For those who don't know:
With a RelativeLayout
and toLeftOf
I would get 1) but not 2) as previous lines would be "cut off" at the position of the time view. Same behaviour If i use a LinearLayout
.
So I tried to use a FrameLayout
or a RelativeLayout
without any connection between text and time.
However, if the text is as long as the message-view is big, both views would overlap. If I put blank characters to my message I wouldn't have the time on the right.
Do they really have some kind of text-wrapping-lib for this or is it possible to do only with layouts?
Here is the requested screenshot:
They use LinearLayout as FrameLayout.
How can I show dates in an app when I scroll the ListView like in WhatsApp? When I scroll the ListView, the date gets displayed over the list. If you still did not understand my question please open your WhatsApp, go to any group & start scrolling: you will see the date getting displayed for older texts.
Simply tap the Mark as read option and your friend will see their sent messages as read. Once you mark a message as read it will disappear from the notification center. However, you can still reply to messages from the notification.
@Hisham Muneer 's answer very good.
But there are some problems. For example:
I'm going to share my solution, if you will need like this problem.
This is example screenshot
ImFlexboxLayout.java
public class ImFlexboxLayout extends RelativeLayout { private TextView viewPartMain; private View viewPartSlave; private TypedArray a; private RelativeLayout.LayoutParams viewPartMainLayoutParams; private int viewPartMainWidth; private int viewPartMainHeight; private RelativeLayout.LayoutParams viewPartSlaveLayoutParams; private int viewPartSlaveWidth; private int viewPartSlaveHeight; public ImFlexboxLayout(Context context) { super(context); } public ImFlexboxLayout(Context context, AttributeSet attrs) { super(context, attrs); a = context.obtainStyledAttributes(attrs, R.styleable.ImFlexboxLayout, 0, 0); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); try { viewPartMain = (TextView) this.findViewById(a.getResourceId(R.styleable.ImFlexboxLayout_viewPartMain, -1)); viewPartSlave = this.findViewById(a.getResourceId(R.styleable.ImFlexboxLayout_viewPartSlave, -1)); } catch (Exception e) { e.printStackTrace(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (viewPartMain == null || viewPartSlave == null || widthSize <= 0) { return; } int availableWidth = widthSize - getPaddingLeft() - getPaddingRight(); int availableHeight = heightSize - getPaddingTop() - getPaddingBottom(); viewPartMainLayoutParams = (LayoutParams) viewPartMain.getLayoutParams(); viewPartMainWidth = viewPartMain.getMeasuredWidth() + viewPartMainLayoutParams.leftMargin + viewPartMainLayoutParams.rightMargin; viewPartMainHeight = viewPartMain.getMeasuredHeight() + viewPartMainLayoutParams.topMargin + viewPartMainLayoutParams.bottomMargin; viewPartSlaveLayoutParams = (LayoutParams) viewPartSlave.getLayoutParams(); viewPartSlaveWidth = viewPartSlave.getMeasuredWidth() + viewPartSlaveLayoutParams.leftMargin + viewPartSlaveLayoutParams.rightMargin; viewPartSlaveHeight = viewPartSlave.getMeasuredHeight() + viewPartSlaveLayoutParams.topMargin + viewPartSlaveLayoutParams.bottomMargin; int viewPartMainLineCount = viewPartMain.getLineCount(); float viewPartMainLastLineWitdh = viewPartMainLineCount > 0 ? viewPartMain.getLayout().getLineWidth(viewPartMainLineCount - 1) : 0; widthSize = getPaddingLeft() + getPaddingRight(); heightSize = getPaddingTop() + getPaddingBottom(); if (viewPartMainLineCount > 1 && !(viewPartMainLastLineWitdh + viewPartSlaveWidth >= viewPartMain.getMeasuredWidth())) { widthSize += viewPartMainWidth; heightSize += viewPartMainHeight; } else if (viewPartMainLineCount > 1 && (viewPartMainLastLineWitdh + viewPartSlaveWidth >= availableWidth)) { widthSize += viewPartMainWidth; heightSize += viewPartMainHeight + viewPartSlaveHeight; } else if (viewPartMainLineCount == 1 && (viewPartMainWidth + viewPartSlaveWidth >= availableWidth)) { widthSize += viewPartMain.getMeasuredWidth(); heightSize += viewPartMainHeight + viewPartSlaveHeight; } else { widthSize += viewPartMainWidth + viewPartSlaveWidth; heightSize += viewPartMainHeight; } this.setMeasuredDimension(widthSize, heightSize); super.onMeasure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (viewPartMain == null || viewPartSlave == null) { return; } viewPartMain.layout( getPaddingLeft(), getPaddingTop(), viewPartMain.getWidth() + getPaddingLeft(), viewPartMain.getHeight() + getPaddingTop()); viewPartSlave.layout( right - left - viewPartSlaveWidth - getPaddingRight(), bottom - top - getPaddingBottom() - viewPartSlaveHeight, right - left - getPaddingRight(), bottom - top - getPaddingBottom()); } }
attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ImFlexboxLayout"> <attr name="viewPartMain" format="reference"></attr> <attr name="viewPartSlave" format="reference"></attr> </declare-styleable> </resources>
Example right ballon layout (balloon.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="wrap_content" android:baselineAligned="false" android:gravity="center_vertical" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="right|center_vertical" android:layout_weight="1" android:gravity="right"> <tr.com.client.ImFlexboxLayout android:id="@+id/msg_layout" style="@style/BalloonMessageLayoutRight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|bottom" android:gravity="left|center_vertical" app:viewPartMain="@+id/chat_msg" app:viewPartSlave="@+id/lytStatusContainer"> <TextView android:id="@+id/chat_msg" style="@style/BalloonMessageRightTextItem" android:layout_width="wrap_content" android:layout_gravity="right|bottom" android:focusableInTouchMode="false" android:gravity="left|top" android:text="hjjfg" /> <LinearLayout android:id="@+id/lytStatusContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:gravity="right" android:minWidth="60dp"> <TextView android:id="@+id/date_view" style="@style/BallonMessageTimeText" android:layout_alignParentRight="true" android:layout_gravity="right|bottom" android:layout_marginRight="5dp" android:gravity="right" android:maxLines="1" /> <include android:id="@+id/lytStatus" layout="@layout/layout_im_message_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginRight="5dp" android:minWidth="40dp" /> </LinearLayout> </tr.com.client.ImFlexboxLayout> </LinearLayout> </LinearLayout>
You can modify layout xml and some sections related your scenario.
There are 2 important point: you must define in layout xml "viewPartMain", "viewPartSlave" attributes. Because the code will decide measure via your main(chat textview) and slave(datetime text view) elements.
I wish have good days. Greets.
Adding HTML non-breaking spaces did the trick. Tested the code on most devices and working absolutely fine. Maybe whatsapp is also doing the same thing. Below is the chat code:
XML Design:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rel_layout_left" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/txtDate" android:visibility="visible" android:orientation="vertical" > <TextView android:id="@+id/lblMsgFrom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="kfhdjbh" android:textColor="@color/lblFromName" android:textSize="12dp" android:textStyle="italic" android:visibility="gone" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/lblMsgFrom" android:layout_marginRight="-5dp" android:src="@drawable/bubble_corner" /> <FrameLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:background="@drawable/bg_msg_from" android:layout_toRightOf="@+id/imageView"> <TextView android:id="@+id/txtTimeFrom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="@dimen/d5" android:text="Time" android:textColor="@android:color/darker_gray" android:layout_gravity="bottom|right" android:padding="4dp" android:textSize="10dp" android:textStyle="italic" android:layout_below="@+id/txtMsgFrom" android:layout_alignRight="@+id/txtMsgFrom" android:layout_alignEnd="@+id/txtMsgFrom" /> <TextView android:id="@+id/txtMsgFrom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/imageView" android:layout_toEndOf="@+id/lblMsgFrom" android:layout_toRightOf="@+id/imageView" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="5dp" android:paddingBottom="5dp" android:text="kdfjhgjfhf" android:textColor="@color/black" android:textSize="16dp" android:layout_alignParentLeft="true" android:layout_marginLeft="0dp" android:layout_alignParentTop="true" android:layout_marginTop="0dp" android:layout_gravity="left|center_vertical" /> </FrameLayout> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <!-- view background color --> <!--<solid android:color="@color/bg_msg_from" >--> <solid android:color="@android:color/white" > </solid> <corners android:radius="@dimen/d5" > </corners> </shape>
txtMsgFrom.setText(Html.fromHtml(convertToHtml(txtMsgFrom.getText().toString()) + "         ")); // 10 spaces
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With