Whatsapp Message Layout – Wie bekomme ich Zeit in der gleichen Zeile?

Ich habe mich gefragt, wie WhatsApp die in jeder Nachricht gezeigte Zeit verarbeitet.

Für diejenigen, die es nicht wissen:

  • Herauszufinden, welche Aktivität meine Tätigkeit begonnen hat?
  • UsageStatsManager, der Daten von nur letztem Tag / Woche / Monat / Jahr zurückgibt?
  • Android Firebase Analytics Benutzerdefinierte Ereignisse Berichte in der Konsole
  • Testing Release und proguarded Version von Android App - NoSuchMethodError
  • Warum beendet mein ProgressDialog, wenn ich auf Aktivität klicke?
  • Android: Eine Klasse packbar machen
    1. Wenn die Nachricht sehr kurz ist, befinden sich Text und Uhrzeit in derselben Zeile.
    2. Wenn die Nachricht lang ist, ist die Zeit in der rechten unteren Ecke – der Text ist um ihn gewickelt.

    Mit einem RelativeLayout und toLeftOf würde ich 1) aber nicht 2) als vorherige Zeilen "cut off" an der Position der toLeftOf . Gleiches Verhalten Wenn ich ein LinearLayout .

    Also habe ich versucht, ein FrameLayout oder ein RelativeLayout ohne jegliche Verbindung zwischen Text und Zeit zu verwenden.

    Wenn der Text aber so lange ist, wie die Nachrichtenansicht groß ist, würden sich beide Ansichten überschneiden. Wenn ich leere Zeichen zu meiner Nachricht stelle, hätte ich nicht die Zeit auf der rechten Seite.

    Haben sie wirklich eine Art Text-Wrapping-lib für diese oder ist es möglich, nur mit Layouts zu tun?

    Hier ist der gewünschte Screenshot:

    Bildbeschreibung hier eingeben

  • Android Textansicht Umriss Text
  • So finden Sie Android Google Play Services Version
  • Benutzerdefinierte Alert-Dialog bekommen unerwünschte Padding
  • Gradle Wie generiere ich Quellcode vor der Kompilierung in Android App
  • Android-Emulator-Hosts-Datei
  • Android: Standard AppTheme Hintergrundfarben
  • 7 Solutions collect form web for “Whatsapp Message Layout – Wie bekomme ich Zeit in der gleichen Zeile?”

    Hinzufügen von HTML non-breaking Räume hat der Trick. Getestet den Code auf die meisten Geräte und funktioniert absolut in Ordnung. Vielleicht macht whatsapp auch dasselbe. Unten ist der Chat-Code:

    Siehe Bilder unten, um es zu sehen.

    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> 

    Code: bg_msg_from.xml

     <?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> 

    ** Datei: bubble_corner.png **

    Pfeil rechts Bildbeschreibung hier eingeben

    Bildbeschreibung hier eingebenBildbeschreibung hier eingebenBildbeschreibung hier eingeben

     txtMsgFrom.setText(Html.fromHtml(convertToHtml(txtMsgFrom.getText().toString()) + " &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;")); // 10 spaces 

    @Hisham Muneers Antwort sehr gut

    Aber es gibt einige Probleme. Beispielsweise:

    • Wenn die TextView 2 volle Zeilen hat (Ende zu Ende), schneidet der Text mit dem Datumstext-Layout. Schließlich werden die Ansichten wie Zwiebel-Effekt aussehen.
    • Die Textzeilen-Wraps können nicht effizient arbeiten. Sie müssen diese Zeilen steuern und die datetime-Ansicht verlagern.

    Ich werde meine Lösung teilen, wenn Sie dieses Problem brauchen werden.

    Dies ist Beispiel Screenshot Beispiel 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> 

    Beispiel rechts 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> 

    Sie können Layout xml und einige Abschnitte in Bezug auf Ihr Szenario ändern.

    Es gibt zwei wichtige Punkte : Sie müssen im Layout xml "viewPartMain" , "viewPartSlave" Attribute definieren. Denn der Code entscheidet über Ihre Haupt- (Chat-Textansicht) und Slave (datetime Text View) Elemente.

    Ich wünsche gute Tage. Grüßt

    Es ist einfacher mit Unicode von hier .

    So können Sie das Unicode-Format archivieren

      new TextView("Hello\u00A0world"); 

    Besser als HTML-String.

    Quelle: https://stackoverflow.com/a/6565049

    Ich schlage eine weitere Lösung vor

     public static final String TAG = "MainActivity"; private TextView mText; private RelativeLayout relativeLayout; private Boolean mFirstTime = true; private static final int WIDH_HOUR = 382; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final int width = getScreensWidh(); mText = (TextView) findViewById(R.id.activity_main_text); relativeLayout = (RelativeLayout) findViewById(R.id.activity_main_relative); mText.setText("aaaaa dfsafsa afdsfa fdsafas adfas fdasf adfsa dsa aaaa dfsafsa afdsfa fdsafas adfas fdasf adfsa"); ViewTreeObserver vto = mText.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mFirstTime) { Layout layout = mText.getLayout(); int lines = layout.getLineCount(); int offset = layout.layout.getLineWidth(lines - 1); int freeSpace = width - offset; TextView hour = new TextView(MainActivity.this); hour.setText("12:20"); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); if (freeSpace > WIDH_HOUR) { params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.activity_main_text); } else { params.addRule(RelativeLayout.BELOW, R.id.activity_main_text); } hour.setLayoutParams(params); relativeLayout.addView(hour); Log.d(TAG, String.valueOf(freeSpace)); mFirstTime = false; } } }); } public int getScreensWidh() { Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); return size.x; } 

    Zwei öffentliche Methoden

    • Public abstract int getLineCount ()

    Geben Sie die Anzahl der Textzeilen in diesem Layout zurück.

    • Public int getLineWidth (int line)

    Ruft das unsigned horizontale Ausmaß der angegebenen Zeile ab, einschließlich des führenden Randeinzugs und des nachlaufenden Leerraums.

    Sie können das Layout und den Code unten verwenden, um den gewünschten Effekt zu erzielen. Quellcode gist

    Was ich benutzt habe, bekomme die Breite des Textes + das Zeitlayout und prüfe, ob dies die Behälterlayoutbreite übersteigt und die Höhe des Containers entsprechend anpasst. Wir müssen von FrameLayout verlängern, da dies diejenige ist, die eine Überlappung von zwei Kinderansichten ermöglicht.

    Dies wird getestet, um an englischem Gebietsschema zu arbeiten. Vorschläge und Verbesserungen sind immer willkommen 🙂

    Hoffe, ich habe jemanden geholfen, der nach der gleichen Lösung sucht.

    Ich denke, der einfachste Weg, um diese Art vonlayout zu erreichen wäre, um genug Leerzeichen in Ihrer Nachricht zu geben, um sicherzustellen, dass es genug Platz auf der rechten Seite, um nicht die Zeit zu decken (ich sehe keinen anderen einfachen Weg, um eine Marge / Padding / positioning für die letzte Zeile Ihres Textes nur) Dann legen Sie einfach die Zeit in die relative als eine Ausrichtung unten rechts

     <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rel_layout_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bubble1" android:orientation="vertical"> <TextView android:id="@+id/lblMsgFrom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Person Name or Id" android:visibility="gone" /> <TextView android:id="@+id/lblMessage_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="5dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="5dp" android:text="Sample \n Sample2 Sample2 Sample2 Sample2 Sample2 Sample2 Sample2 Sample2 Sample2 \n Sample2" android:textSize="16dp" /> <TextView android:id="@+id/lblMessage_Time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignEnd="@+id/lblMessage_text" android:layout_alignRight="@+id/lblMessage_text" android:layout_below="@+id/lblMessage_text" android:text="04:50 Am" android:textColor="@android:color/darker_gray" android:textSize="10dp" android:textStyle="italic" /> </RelativeLayout> 
    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.