Soru Whatsapp Message Layout - Aynı satırda zaman görünümü nasıl alınır?


WhatsApp'ın her mesajda gösterilen zamanı nasıl ele aldığını merak ediyordum.

Bilmeyenler için:

  1. Mesaj çok kısasa, metin ve saat aynı satırdadır.
  2. Mesaj uzunsa, zaman sağ alt köşede - metin etrafına sarılmış.

Birlikte RelativeLayout ve toLeftOf 1) ancak 2) önceki satırların zaman görünümünde "kesilmesi" olacağından. Aynı davranış kullanırsam LinearLayout.

Bu yüzden bir FrameLayout ya da RelativeLayout metin ve zaman arasında herhangi bir bağlantı olmadan.

Bununla birlikte, metin ileti görünümü büyük olduğu sürece, her iki görünüm de çakışır. Mesajıma boş karakterler koyarsam sağdaki zamana sahip olmazdım.

Gerçekten bunun için bir çeşit metin-sarma-libresine sahipler mi, yoksa sadece mizanpajlarla yapmak mümkün mü?

İstenen ekran görüntüsü:

enter image description here


32
2018-05-11 13:05


Menşei


ekran görüntüsü lütfen. - r2DoesInc
ve zaman çizelgesini örtmeyen aynı satırda nasıl bir metin olurdu? - Frame91
İki metin görünümü kullanacaksınız - uçtan uca [Messagetext] [TimeText] ile hizalanmış, göreli bir düzen veya daha iyi bir yatay yönelimli LinearLayout ve görünümler için ağırlık kullanabilirsiniz. - Skynet
ancak bu, birden fazla satır varsa, metnin zaman görünümü üzerinde olabileceği ikinci senaryoyu yerine getirmez - Frame91
İpuçları: Bir özel yapmak gerekir ViewGroupmesajın ardından TextView ölçülebilir olsun son çizgisinin genişliği bunu zamanın genişliği ile karşılaştır TextView ve nereye koyacağınıza karar verin. Herhangi bir standart kullanmıyorsunuz *Layout. - Eugen Pechanec


Cevaplar:


HTML kesilmeyen boşluklar eklemek hile yaptı. Çoğu cihazda kodu test ettim ve kesinlikle iyi çalışıyor. Belki de whatsapp aynı şeyi yapıyor. Sohbet kodu aşağıdadır:

Çalıştığını görmek için aşağıdaki resimlere bakın.

XML Tasarımı:

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

Kod: 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>

** Dosya: bubble_corner.png **

Right Arrow Image enter image description here

enter image description here enter image description here enter image description here

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

25
2018-05-25 13:21



Harika!! ama bubble_corner & bg_msg_from için XML kodunu da gönderebilirsiniz - Diyaa
@DiyaaHamza İstenen dosyaları yapıştırdı. - Hisham Muneer
ConvertToHtml () fonksiyonunun nasıl çalıştığını gösterebilir misiniz ... Bu benim düzenimde çalışmak için buna ihtiyacım var ... Teşekkürler - Wan
Güzel çözüm. Ama bunun içinde bir kusur buldum. Eğer android set edersek: autoLink = "web" özelliği textview mesajına her mesaj link olarak görüntülenir. Bunun için herhangi bir çözüm var mı? - Pruthviraj
Bir şekilde bu düzen benim için çalışmıyor. Tek gördüğüm sol üst köşede beyaz küçük yuvarlak köşe dikdörtgeni ve daha büyük gri bir ok üst üste geliyor. Neyi özlediğim hakkında bir fikrim var mı? - Atul


@Hisham Muneer'in cevabı çok iyi.

Ama bazı problemler var. Örneğin:

  • TextView 2 tam satıra sahipse (uçtan uca), metin datetime metin düzeniyle kesişir. Son olarak, görüşler Soğan etkisine benziyor.
  • Metin satırı kaydırmaları verimli şekilde çalışamaz. Bunu kontrol etmelisin hatları ve datetime görünümünü yeniden konumlandırın.

Bu problem gibi ihtiyacınız olacaksa, çözümümü paylaşacağım.

Bu örnek ekran görüntüsü 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>

Örnek sağ balon düzeni (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>

Senaryo xml ve senaryonuzla ilgili bazı bölümleri değiştirebilirsiniz.

Var 2 önemli nokta: xml düzeninde tanımlamalısınız "ViewPartMain", "ViewPartSlave" Öznitellikler. Çünkü kod, ana (sohbet metni görünümü) ve köle (datetime metin görünümü) öğeleri aracılığıyla ölçüm yapmaya karar verecektir.

İyi günler dilerim. Karşılıyor.


18
2017-10-03 11:42



whatsapp ne yapıyorsa tam olarak budur. - Pierre
bunun kabul edilen cevap olması gerektiğini düşünüyorum - Dragos Rachieru
teşekkürler, en iyisi. +1 - erfan
efendim, bu başka bir dil için işe yaramaz, örneğin Arapça dil kullanmak istiyorum, bu yüzden, TextView yerçekimi doğru olmalı, ancak doğru yere ayarlandığında, kod çalışmıyor! ama telgraf veya whatsapp görürseniz, arapça dilini yazdığınızda, doğru yere gelip düzen tamamdır - erfan
@erfan Hmm haklısın .. LTR alfabesi için bu tasarım .. Görüşümde, Layout metodunu değiştirmelisin .. Sol ve sağ değer bölümlerini yansıtıyor musun? .. Bu RTL problemini çözebilir .. işinizin sonucunu burada paylaşır mısınız lütfen? - Sinan Ergin


Unicode ile daha kolay İşte.

Böylece, Unicode formatını arşivleyebilirsiniz

 new TextView("Hello\u00A0world");

HTML dizgisinden daha iyi.

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


4
2017-07-26 06:29



Bu + autolink + yalnızca mesaj metnindeki bir url = tıklamakta başarısız - Borja


Başka bir çözüm öneririm

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;

    }

İki Kamu Yöntemi

Bu düzende metin satırlarının sayısını döndür.

Öncelikli kenar boşluğu girintisi ve boşluk boşlukları dahil olmak üzere, belirtilen satırın işaretsiz yatay boyutunu alır.


2
2018-03-10 15:40





İstenen etkiyi elde etmek için aşağıdaki düzeni ve kodu kullanabilirsiniz. Kaynak kodu

Kullandığım şey, metnin genişliğini + zaman düzenini almak ve bunun kapsayıcı düzen genişliğini aşıp aşmadığını kontrol etmek ve kabın yüksekliğini buna göre ayarlamaktır. FrameLayout'tan genişletmek zorundayız çünkü bu iki çocuk görüşünün örtüşmesine izin veriyor.

Bu, İngilizce yerel ayarında test edilmiştir. Öneriler ve geliştirmeler her zaman açıktır :)

Umarım aynı çözümü arayan birine yardım ettim.


2
2017-07-01 12:38



Denedim, tek satır ile çalışır, ancak birden fazla satır ile değil - Hardik9850
Lütfen aynı kodla güncellenen kodu deneyin. Yeni kodu yorumlarda bulabilirsiniz. - Rahul Shukla
Mesaj metni ve zaman metni arasında boşluk sağlamak için basit bir yol eklemek android:paddingLeft zamana Ayrıca, zaman damgasının dibine oturması, int bottomMargin Gerek yok. - John Pang


Sanırım bu türden bir takvime ulaşmanın en kolay yolu, zamanınızı korumaya yetecek kadar alanın bulunduğundan emin olmak için mesajınızda yeterince boş alan eklemek olacaktır (bir marjı elde etmenin başka kolay bir yolunu görmüyorum / sadece metninizin son satırı için dolgu / konumlandırma) Ardından, zamanı göreli olarak sağ alt köşeye yerleştirirsiniz.


1
2018-05-11 13:57



Önerin için teşekkürler. Ancak, bu her durum için işe yaramaz. Boş alan satır kaydırma konusunda işe yaramıyor, bu yüzden uzun bir metnim varsa boş alanım bir sonraki satıra aktarılıyor - Frame91


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

0
2017-07-28 13:14