Change message view header layout

Co-authored-by: ByteHamster <info@bytehamster.com>
This commit is contained in:
cketti 2022-09-15 13:25:34 +02:00
parent a31db513b9
commit 7aa0c77b4a
5 changed files with 237 additions and 289 deletions

View file

@ -0,0 +1,21 @@
package com.fsck.k9.ui.helper
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
/**
* Return the baseline of the last line of text, instead of TextView's default of the first line.
*/
// Source: https://stackoverflow.com/a/62419876
class BottomBaselineTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : AppCompatTextView(context, attrs) {
override fun getBaseline(): Int {
val layout = layout ?: return super.getBaseline()
val baselineOffset = super.getBaseline() - layout.getLineBaseline(0)
return baselineOffset + layout.getLineBaseline(layout.lineCount - 1)
}
}

View file

@ -2,11 +2,11 @@ package com.fsck.k9.view;
import android.content.Context;
import android.content.res.ColorStateList;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -24,16 +24,18 @@ import com.fsck.k9.helper.MessageHelper;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.ui.ContactBadge;
import com.fsck.k9.ui.R;
import com.google.android.material.chip.Chip;
import com.google.android.material.snackbar.Snackbar;
public class MessageHeader extends LinearLayout implements OnClickListener, OnLongClickListener {
private static final int DEFAULT_SUBJECT_LINES = 3;
private Chip accountChip;
private TextView subjectView;
private CheckBox starView;
private ContactBadge contactBadge;
private ImageView starView;
private ImageView contactPictureView;
private TextView fromView;
private ImageView cryptoStatusIcon;
@ -44,22 +46,35 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
public MessageHeader(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
messageHelper = MessageHelper.getInstance(getContext());
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
accountChip = findViewById(R.id.chip);
subjectView = findViewById(R.id.subject);
starView = findViewById(R.id.flagged);
contactBadge = findViewById(R.id.contact_badge);
contactPictureView = findViewById(R.id.contact_picture);
fromView = findViewById(R.id.from);
cryptoStatusIcon = findViewById(R.id.crypto_status_icon);
subjectView.setOnClickListener(this);
subjectView.setOnLongClickListener(this);
messageHelper = MessageHelper.getInstance(getContext());
View menuPrimaryActionView = findViewById(R.id.menu_primary_action);
menuPrimaryActionView.setOnClickListener(this);
menuPrimaryActionView.setOnLongClickListener(this);
View menuOverflowView = findViewById(R.id.menu_overflow);
menuOverflowView.setOnClickListener(this);
menuOverflowView.setOnLongClickListener(this);
findViewById(R.id.participants_container).setOnClickListener(this);
}
@Override
@ -67,11 +82,15 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
int id = view.getId();
if (id == R.id.subject) {
toggleSubjectViewMaxLines();
} else if (id == R.id.icon_single_message_options) {
} else if (id == R.id.menu_primary_action) {
Snackbar.make(getRootView(), "TODO: Perform primary action", Snackbar.LENGTH_LONG).show();
} else if (id == R.id.menu_overflow) {
PopupMenu popupMenu = new PopupMenu(getContext(), view);
popupMenu.setOnMenuItemClickListener(onMenuItemClickListener);
popupMenu.inflate(R.menu.single_message_options);
popupMenu.show();
} else if (id == R.id.participants_container) {
Snackbar.make(getRootView(), "TODO: Display details popup", Snackbar.LENGTH_LONG).show();
}
}
@ -110,6 +129,9 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
}
public void populate(final Message message, final Account account, boolean showStar) {
accountChip.setText(account.getDisplayName());
accountChip.setChipBackgroundColor(ColorStateList.valueOf(account.getChipColor()));
Address fromAddress = null;
Address[] fromAddresses = message.getFrom();
if (fromAddresses.length > 0) {
@ -117,12 +139,10 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
}
if (fromAddress != null) {
contactBadge.setContact(fromAddress);
ContactPictureLoader contactsPictureLoader = ContactPicture.getContactPictureLoader();
contactsPictureLoader.setContactPicture(contactBadge, fromAddress);
contactsPictureLoader.setContactPicture(contactPictureView, fromAddress);
} else {
contactBadge.setImageResource(R.drawable.ic_contact_picture);
contactPictureView.setImageResource(R.drawable.ic_contact_picture);
}
CharSequence from = messageHelper.getSenderDisplayName(fromAddress);
@ -130,7 +150,7 @@ public class MessageHeader extends LinearLayout implements OnClickListener, OnLo
if (showStar) {
starView.setVisibility(View.VISIBLE);
starView.setChecked(message.isSet(Flag.FLAGGED));
starView.setSelected(message.isSet(Flag.FLAGGED));
} else {
starView.setVisibility(View.GONE);
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_star" />
<item android:state_selected="false" android:drawable="@drawable/ic_star_border" />
</selector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
</vector>

View file

@ -1,297 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fsck.k9.view.MessageHeader
xmlns:android="http://schemas.android.com/apk/res/android"
<com.fsck.k9.view.MessageHeader xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/header_container"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.chip.Chip
android:id="@+id/chip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:clickable="false"
android:textColor="@android:color/white"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/subject"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:chipBackgroundColor="#1976D2"
tools:text="Account name" />
<com.fsck.k9.ui.helper.BottomBaselineTextView
android:id="@+id/subject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="@id/chip"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:ellipsize="end"
android:maxLines="3"
android:textColor="?android:attr/textColorPrimary"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/flagged"
app:layout_constraintStart_toStartOf="parent"
tools:text="Message subject" />
<ImageView
android:id="@+id/flagged"
android:layout_width="44dp"
android:layout_height="48dp"
android:background="?attr/controlBackground"
android:baseline="33dp"
android:paddingHorizontal="10dp"
android:src="@drawable/btn_select_star"
app:layout_constraintBaseline_toBaselineOf="@+id/subject"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/participants_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:background="?attr/colorPrimary"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- Color chip -->
<View
android:id="@+id/chip"
android:layout_width="8dip"
android:layout_height="match_parent"
tools:background="#FF1976D2" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/contact_picture"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_contact_picture" />
<LinearLayout
android:layout_width="match_parent"
<TextView
android:id="@+id/from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="?android:attr/textColorPrimary"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/date"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/contact_picture"
app:layout_constraintTop_toTopOf="@+id/contact_picture"
tools:text="Sender name" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:ellipsize="none"
android:singleLine="true"
android:text="Sep 19"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBaseline_toBaselineOf="@+id/from"
app:layout_constraintEnd_toStartOf="@+id/menu_primary_action"
app:layout_constraintStart_toEndOf="@id/from" />
<TextView
android:id="@+id/subject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:ellipsize="end"
android:maxLines="3"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall"
tools:text="(no subject)"
/>
<ImageView
android:id="@+id/crypto_status_icon"
android:layout_width="18sp"
android:layout_height="18sp"
android:layout_marginStart="16dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/to"
app:layout_constraintStart_toEndOf="@id/contact_picture"
app:srcCompat="@drawable/status_lock_disabled"
app:tint="?attr/openpgp_grey"
tools:visibility="visible" />
<ImageView
android:id="@+id/crypto_status_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="6dp"
app:srcCompat="@drawable/status_lock_disabled"
app:tint="?attr/openpgp_grey"
android:background="?selectableItemBackground"
android:visibility="gone"
/>
<TextView
android:id="@+id/to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:ellipsize="end"
android:maxLines="1"
android:text="to me"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorSecondary"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/to_count"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/crypto_status_icon"
app:layout_constraintTop_toBottomOf="@+id/from"
app:layout_goneMarginStart="16dp" />
<CheckBox
android:id="@+id/flagged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:focusable="false"
android:checked="false"
style="@style/MessageStarStyle"
/>
<TextView
android:id="@+id/to_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:singleLine="true"
android:text="+2"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?attr/colorAccent"
app:layout_constraintBottom_toBottomOf="@+id/to"
app:layout_constraintEnd_toStartOf="@+id/menu_primary_action"
app:layout_constraintStart_toEndOf="@id/to" />
</LinearLayout>
<ImageView
android:id="@+id/menu_primary_action"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/controlBackground"
android:paddingHorizontal="12dp"
app:layout_constraintEnd_toStartOf="@id/menu_overflow"
app:layout_constraintTop_toTopOf="@+id/menu_overflow"
app:srcCompat="?iconActionSingleMessageOptions" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/menu_overflow"
android:layout_width="40dp"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="?attr/controlBackground"
android:clickable="true"
android:focusable="true"
android:paddingStart="6dp"
android:paddingEnd="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/dots_vertical" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.fsck.k9.ui.ContactBadge
android:id="@+id/contact_badge"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
tools:src="@drawable/ic_contact_picture"/>
<!-- State icons -->
<LinearLayout
android:id="@+id/icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:layout_marginBottom="2dip"
android:layout_below="@+id/contact_badge"
android:layout_centerHorizontal="true"
android:orientation="vertical" >
<View
android:id="@+id/answered"
android:layout_width="32sp"
android:layout_height="32sp"
android:paddingStart="0dp"
android:paddingEnd="2dp"
android:background="?attr/messageListAnswered" />
<View
android:id="@+id/forwarded"
android:layout_width="22sp"
android:layout_height="22sp"
android:paddingStart="0dp"
android:paddingEnd="4dp"
android:background="?attr/messageListForwarded" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dip"
android:layout_marginStart="2dp" >
<!-- From -->
<TextView
android:id="@+id/from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/status_icon_strip"
android:layout_alignBottom="@+id/status_icon_strip"
android:paddingTop="0dp"
android:paddingStart="0dp"
android:paddingEnd="6dp"
android:singleLine="true"
android:ellipsize="end"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall"
android:textStyle="bold"
android:text="@string/general_no_sender"
android:gravity="center_vertical"
/>
<!-- Sender -->
<TextView
android:id="@+id/sender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/status_icon_strip"
android:paddingTop="0dp"
android:layout_below="@+id/from"
android:ellipsize="end"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="@style/TextAppearance.K9.Small"
android:textStyle="bold"
android:visibility="gone"
android:gravity="center_vertical"
/>
<!-- To -->
<TextView
android:id="@+id/to_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/from"
android:layout_alignBaseline="@+id/to"
android:paddingTop="2dp"
android:paddingStart="0dp"
android:paddingEnd="4dp"
android:text="@string/message_to_label"
android:textColor="?android:attr/textColorPrimary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall"
android:textStyle="bold" />
<TextView
android:id="@+id/to"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/to_label"
android:layout_below="@+id/sender"
android:maxLines="2"
android:ellipsize="end"
android:paddingTop="2dp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall" />
<!-- CC -->
<TextView
android:id="@+id/cc_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/to_label"
android:layout_alignStart="@+id/to_label"
android:layout_alignBaseline="@+id/cc"
android:paddingTop="2dp"
android:paddingStart="0dp"
android:paddingEnd="4dp"
android:text="@string/message_view_cc_label"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.K9.MediumSmall" />
<TextView
android:id="@+id/cc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/cc_label"
android:layout_below="@+id/to"
android:maxLines="2"
android:ellipsize="end"
android:paddingTop="2dp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall" />
<!-- BCC -->
<TextView
android:id="@+id/bcc_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/cc_label"
android:layout_alignStart="@+id/cc_label"
android:layout_alignBaseline="@+id/bcc"
android:paddingTop="2dp"
android:paddingStart="0dp"
android:paddingEnd="4dp"
android:text="@string/message_view_bcc_label"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.K9.MediumSmall" />
<TextView
android:id="@+id/bcc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/bcc_label"
android:layout_below="@+id/cc"
android:maxLines="2"
android:ellipsize="end"
android:paddingTop="2dp"
android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@style/TextAppearance.K9.MediumSmall" />
<!-- Date -->
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/bcc"
android:layout_alignParentEnd="true"
android:paddingTop="8dp"
android:singleLine="true"
android:ellipsize="none"
android:textAppearance="@style/TextAppearance.K9.Small"
android:textColor="?android:attr/textColorSecondary" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:id="@+id/status_icon_strip"
>
<ImageView
android:id="@+id/icon_single_message_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="?iconActionSingleMessageOptions"
android:padding="8dp"
android:background="?selectableItemBackground"
/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View
android:layout_height="1dip"
android:layout_width="match_parent"
android:layout_marginBottom="4dip"
android:background="@drawable/divider_horizontal_email" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.fsck.k9.view.MessageHeader>