Add option to not crop image previews (#2832)

* Don't crop image previews with aspects between 2:1 & 1:2

Fixes #1995

* Custom media preview layout for handling various aspect ratios
This commit is contained in:
Eva Tatarka 2022-12-01 12:20:46 -08:00 committed by GitHub
parent 6b95790457
commit cc790ccf69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 402 additions and 298 deletions

View File

@ -1,5 +1,7 @@
package com.keylesspalace.tusky.adapter;
import static com.keylesspalace.tusky.viewdata.PollViewDataKt.buildDescription;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
@ -23,6 +25,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.core.text.HtmlCompat;
import androidx.core.view.ViewKt;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -53,6 +56,7 @@ import com.keylesspalace.tusky.util.StatusDisplayOptions;
import com.keylesspalace.tusky.util.ThemeUtils;
import com.keylesspalace.tusky.util.TimestampUtils;
import com.keylesspalace.tusky.view.MediaPreviewImageView;
import com.keylesspalace.tusky.view.MediaPreviewLayout;
import com.keylesspalace.tusky.viewdata.PollOptionViewData;
import com.keylesspalace.tusky.viewdata.PollViewData;
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
@ -66,12 +70,11 @@ import at.connyduck.sparkbutton.SparkButton;
import at.connyduck.sparkbutton.helpers.Utils;
import kotlin.collections.CollectionsKt;
import static com.keylesspalace.tusky.viewdata.PollViewDataKt.buildDescription;
public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
public static class Key {
public static final String KEY_CREATED = "created";
}
private TextView displayName;
private TextView username;
private ImageButton replyButton;
@ -81,8 +84,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private SparkButton bookmarkButton;
private ImageButton moreButton;
private ConstraintLayout mediaContainer;
protected MediaPreviewImageView[] mediaPreviews;
private ImageView[] mediaOverlays;
protected MediaPreviewLayout mediaPreview;
private TextView sensitiveMediaWarning;
private View sensitiveMediaShow;
protected TextView[] mediaLabels;
@ -132,19 +134,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
mediaContainer = itemView.findViewById(R.id.status_media_preview_container);
mediaContainer.setClipToOutline(true);
mediaPreview = itemView.findViewById(R.id.status_media_preview);
mediaPreviews = new MediaPreviewImageView[]{
itemView.findViewById(R.id.status_media_preview_0),
itemView.findViewById(R.id.status_media_preview_1),
itemView.findViewById(R.id.status_media_preview_2),
itemView.findViewById(R.id.status_media_preview_3)
};
mediaOverlays = new ImageView[]{
itemView.findViewById(R.id.status_media_overlay_0),
itemView.findViewById(R.id.status_media_overlay_1),
itemView.findViewById(R.id.status_media_overlay_2),
itemView.findViewById(R.id.status_media_overlay_3)
};
sensitiveMediaWarning = itemView.findViewById(R.id.status_sensitive_media_warning);
sensitiveMediaShow = itemView.findViewById(R.id.status_sensitive_media_button);
mediaLabels = new TextView[]{
@ -181,8 +172,6 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
mediaPreviewUnloaded = new ColorDrawable(ThemeUtils.getColor(itemView.getContext(), R.attr.colorBackgroundAccent));
}
protected abstract int getMediaPreviewHeight(Context context);
protected void setDisplayName(String name, List<Emoji> customEmojis, StatusDisplayOptions statusDisplayOptions) {
CharSequence emojifiedName = CustomEmojiHelper.emojify(
name, customEmojis, displayName, statusDisplayOptions.animateEmojis()
@ -420,64 +409,51 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
Drawable placeholder = blurhash != null ? decodeBlurHash(blurhash) : mediaPreviewUnloaded;
if (TextUtils.isEmpty(previewUrl)) {
imageView.removeFocalPoint();
Glide.with(imageView)
.load(placeholder)
.centerInside()
.into(imageView);
} else {
Focus focus = meta != null ? meta.getFocus() : null;
if (focus != null) { // If there is a focal point for this attachment:
imageView.setFocalPoint(focus);
Glide.with(imageView)
.load(previewUrl)
.placeholder(placeholder)
.centerInside()
.addListener(imageView)
.into(imageView);
} else {
ViewKt.doOnLayout(imageView, view -> {
if (TextUtils.isEmpty(previewUrl)) {
imageView.removeFocalPoint();
Glide.with(imageView)
.load(previewUrl)
.placeholder(placeholder)
.load(placeholder)
.centerInside()
.into(imageView);
} else {
Focus focus = meta != null ? meta.getFocus() : null;
if (focus != null) { // If there is a focal point for this attachment:
imageView.setFocalPoint(focus);
Glide.with(imageView)
.load(previewUrl)
.placeholder(placeholder)
.centerInside()
.addListener(imageView)
.into(imageView);
} else {
imageView.removeFocalPoint();
Glide.with(imageView)
.load(previewUrl)
.placeholder(placeholder)
.centerInside()
.into(imageView);
}
}
}
return null;
});
}
protected void setMediaPreviews(final List<Attachment> attachments, boolean sensitive,
final StatusActionListener listener, boolean showingContent,
boolean useBlurhash) {
Context context = itemView.getContext();
final int n = Math.min(attachments.size(), Status.MAX_MEDIA_ATTACHMENTS);
mediaPreview.setAspectRatios(AttachmentHelper.aspectRatios(attachments));
final int mediaPreviewHeight = getMediaPreviewHeight(context);
if (n <= 2) {
mediaPreviews[0].getLayoutParams().height = mediaPreviewHeight * 2;
mediaPreviews[1].getLayoutParams().height = mediaPreviewHeight * 2;
} else {
mediaPreviews[0].getLayoutParams().height = mediaPreviewHeight;
mediaPreviews[1].getLayoutParams().height = mediaPreviewHeight;
mediaPreviews[2].getLayoutParams().height = mediaPreviewHeight;
mediaPreviews[3].getLayoutParams().height = mediaPreviewHeight;
}
for (int i = 0; i < n; i++) {
mediaPreview.forEachIndexed((i, imageView) -> {
Attachment attachment = attachments.get(i);
String previewUrl = attachment.getPreviewUrl();
String description = attachment.getDescription();
MediaPreviewImageView imageView = mediaPreviews[i];
imageView.setVisibility(View.VISIBLE);
if (TextUtils.isEmpty(description)) {
imageView.setContentDescription(imageView.getContext()
@ -495,42 +471,38 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
final Attachment.Type type = attachment.getType();
if (showingContent && (type == Attachment.Type.VIDEO || type == Attachment.Type.GIFV)) {
mediaOverlays[i].setVisibility(View.VISIBLE);
imageView.setForeground(ContextCompat.getDrawable(itemView.getContext(), R.drawable.play_indicator_overlay));
} else {
mediaOverlays[i].setVisibility(View.GONE);
imageView.setForeground(null);
}
setAttachmentClickListener(imageView, listener, i, attachment, true);
}
if (sensitive) {
sensitiveMediaWarning.setText(R.string.post_sensitive_media_title);
} else {
sensitiveMediaWarning.setText(R.string.post_media_hidden_title);
}
sensitiveMediaWarning.setVisibility(showingContent ? View.GONE : View.VISIBLE);
sensitiveMediaShow.setVisibility(showingContent ? View.VISIBLE : View.GONE);
sensitiveMediaShow.setOnClickListener(v -> {
if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) {
listener.onContentHiddenChange(false, getBindingAdapterPosition());
if (sensitive) {
sensitiveMediaWarning.setText(R.string.post_sensitive_media_title);
} else {
sensitiveMediaWarning.setText(R.string.post_media_hidden_title);
}
v.setVisibility(View.GONE);
sensitiveMediaWarning.setVisibility(View.VISIBLE);
});
sensitiveMediaWarning.setOnClickListener(v -> {
if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) {
listener.onContentHiddenChange(true, getBindingAdapterPosition());
}
v.setVisibility(View.GONE);
sensitiveMediaShow.setVisibility(View.VISIBLE);
});
sensitiveMediaWarning.setVisibility(showingContent ? View.GONE : View.VISIBLE);
sensitiveMediaShow.setVisibility(showingContent ? View.VISIBLE : View.GONE);
sensitiveMediaShow.setOnClickListener(v -> {
if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) {
listener.onContentHiddenChange(false, getBindingAdapterPosition());
}
v.setVisibility(View.GONE);
sensitiveMediaWarning.setVisibility(View.VISIBLE);
});
sensitiveMediaWarning.setOnClickListener(v -> {
if (getBindingAdapterPosition() != RecyclerView.NO_POSITION) {
listener.onContentHiddenChange(true, getBindingAdapterPosition());
}
v.setVisibility(View.GONE);
sensitiveMediaShow.setVisibility(View.VISIBLE);
});
// Hide any of the placeholder previews beyond the ones set.
for (int i = n; i < Status.MAX_MEDIA_ATTACHMENTS; i++) {
mediaPreviews[i].setVisibility(View.GONE);
}
return null;
});
}
@DrawableRes
@ -751,10 +723,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} else {
setMediaLabel(attachments, sensitive, listener, status.isShowingContent());
// Hide all unused views.
mediaPreviews[0].setVisibility(View.GONE);
mediaPreviews[1].setVisibility(View.GONE);
mediaPreviews[2].setVisibility(View.GONE);
mediaPreviews[3].setVisibility(View.GONE);
mediaPreview.setVisibility(View.GONE);
hideSensitiveMediaWarning();
}

View File

@ -1,6 +1,5 @@
package com.keylesspalace.tusky.adapter;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.method.LinkMovementMethod;
import android.view.View;
@ -33,11 +32,6 @@ public class StatusDetailedViewHolder extends StatusBaseViewHolder {
infoDivider = view.findViewById(R.id.status_info_divider);
}
@Override
protected int getMediaPreviewHeight(Context context) {
return context.getResources().getDimensionPixelSize(R.dimen.status_detail_media_preview_height);
}
@Override
protected void setCreatedAt(Date createdAt, StatusDisplayOptions statusDisplayOptions) {
if (createdAt == null) {

View File

@ -53,11 +53,6 @@ public class StatusViewHolder extends StatusBaseViewHolder {
contentCollapseButton = itemView.findViewById(R.id.button_toggle_content);
}
@Override
protected int getMediaPreviewHeight(Context context) {
return context.getResources().getDimensionPixelSize(R.dimen.status_media_preview_height);
}
@Override
public void setupWithStatus(@NonNull StatusViewData.Concrete status,
@NonNull final StatusActionListener listener,

View File

@ -68,11 +68,6 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
this.listener = listener;
}
@Override
protected int getMediaPreviewHeight(Context context) {
return context.getResources().getDimensionPixelSize(R.dimen.status_media_preview_height);
}
void setupWithConversation(
@NonNull ConversationViewData conversation,
@Nullable Object payloads
@ -108,10 +103,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
} else {
setMediaLabel(attachments, sensitive, listener, statusViewData.isShowingContent());
// Hide all unused views.
mediaPreviews[0].setVisibility(View.GONE);
mediaPreviews[1].setVisibility(View.GONE);
mediaPreviews[2].setVisibility(View.GONE);
mediaPreviews[3].setVisibility(View.GONE);
mediaPreview.setVisibility(View.GONE);
hideSensitiveMediaWarning();
}

View File

@ -68,7 +68,9 @@ data class Attachment(
@Parcelize
data class MetaData(
val focus: Focus?,
val duration: Float?
val duration: Float?,
val original: Size?,
val small: Size?,
) : Parcelable
/**
@ -82,4 +84,14 @@ data class Attachment(
val x: Float,
val y: Float
) : Parcelable
/**
* The size of an image, used to specify the width/height.
*/
@Parcelize
data class Size(
val width: Int,
val height: Int,
val aspect: Double
) : Parcelable
}

View File

@ -1,4 +1,5 @@
@file:JvmName("AttachmentHelper")
package com.keylesspalace.tusky.util
import android.content.Context
@ -24,3 +25,12 @@ private fun formatDuration(durationInSeconds: Double): String {
val hours = durationInSeconds.toInt() / 3600
return "%d:%02d:%02d".format(hours, minutes, seconds)
}
fun List<Attachment>.aspectRatios(): List<Double> {
return map { attachment ->
// clamp ratio between 2:1 & 1:2, defaulting to 16:9
val size = (attachment.meta?.small ?: attachment.meta?.original) ?: return@map 1.7778
val aspect = if (size.aspect > 0) size.aspect else size.width.toDouble() / size.height
aspect.coerceIn(0.5, 2.0)
}
}

View File

@ -0,0 +1,210 @@
package com.keylesspalace.tusky.view
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.keylesspalace.tusky.R
import kotlin.math.roundToInt
/**
* Lays out a set of [MediaPreviewImageView]s keeping their aspect ratios into account.
*/
class MediaPreviewLayout(context: Context, attrs: AttributeSet? = null) :
ViewGroup(context, attrs) {
private val spacing = context.resources.getDimensionPixelOffset(R.dimen.preview_image_spacing)
/**
* An ordered list of aspect ratios used for layout. An image view for each aspect ratio passed
* will be attached. Supports up to 4, additional ones will be ignored.
*/
var aspectRatios: List<Double> = emptyList()
set(value) {
field = value
attachImageViews()
}
private val imageViewCache = Array(4) { MediaPreviewImageView(context) }
private var measuredOrientation = LinearLayout.VERTICAL
private fun attachImageViews() {
removeAllViews()
for (i in 0 until aspectRatios.size.coerceAtMost(imageViewCache.size)) {
addView(imageViewCache[i])
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width = MeasureSpec.getSize(widthMeasureSpec)
val halfWidth = width / 2 - spacing / 2
var totalHeight = 0
when (childCount) {
1 -> {
val aspect = aspectRatios[0]
totalHeight += getChildAt(0).measureToAspect(width, aspect)
}
2 -> {
val aspect1 = aspectRatios[0]
val aspect2 = aspectRatios[1]
if ((aspect1 + aspect2) / 2 > 1.2) {
// stack vertically
measuredOrientation = LinearLayout.VERTICAL
totalHeight += getChildAt(0).measureToAspect(width, aspect1.coerceAtLeast(1.8))
totalHeight += spacing
totalHeight += getChildAt(1).measureToAspect(width, aspect2.coerceAtLeast(1.8))
} else {
// stack horizontally
measuredOrientation = LinearLayout.HORIZONTAL
val height = rowHeight(halfWidth, aspect1, aspect2)
totalHeight += height
getChildAt(0).measureExactly(halfWidth, height)
getChildAt(1).measureExactly(halfWidth, height)
}
}
3 -> {
val aspect1 = aspectRatios[0]
val aspect2 = aspectRatios[1]
val aspect3 = aspectRatios[2]
if (aspect1 >= 1) {
// | 1 |
// -------------
// | 2 | 3 |
measuredOrientation = LinearLayout.VERTICAL
totalHeight += getChildAt(0).measureToAspect(width, aspect1.coerceAtLeast(1.8))
totalHeight += spacing
val bottomHeight = rowHeight(halfWidth, aspect2, aspect3)
totalHeight += bottomHeight
getChildAt(1).measureExactly(halfWidth, bottomHeight)
getChildAt(2).measureExactly(halfWidth, bottomHeight)
} else {
// | | 2 |
// | 1 |-----|
// | | 3 |
measuredOrientation = LinearLayout.HORIZONTAL
val colHeight = getChildAt(0).measureToAspect(halfWidth, aspect1)
totalHeight += colHeight
val halfHeight = colHeight / 2 - spacing / 2
getChildAt(1).measureExactly(halfWidth, halfHeight)
getChildAt(2).measureExactly(halfWidth, halfHeight)
}
}
4 -> {
val aspect1 = aspectRatios[0]
val aspect2 = aspectRatios[1]
val aspect3 = aspectRatios[2]
val aspect4 = aspectRatios[3]
val topHeight = rowHeight(halfWidth, aspect1, aspect2)
totalHeight += topHeight
getChildAt(0).measureExactly(halfWidth, topHeight)
getChildAt(1).measureExactly(halfWidth, topHeight)
totalHeight += spacing
val bottomHeight = rowHeight(halfWidth, aspect3, aspect4)
totalHeight += bottomHeight
getChildAt(2).measureExactly(halfWidth, bottomHeight)
getChildAt(3).measureExactly(halfWidth, bottomHeight)
}
}
super.onMeasure(
widthMeasureSpec,
MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY)
)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
val width = r - l
val height = b - t
val halfWidth = width / 2 - spacing / 2
when (childCount) {
1 -> {
getChildAt(0).layout(0, 0, width, height)
}
2 -> {
if (measuredOrientation == LinearLayout.VERTICAL) {
val y = imageViewCache[0].measuredHeight
getChildAt(0).layout(0, 0, width, y)
getChildAt(1).layout(
0,
y + spacing,
width,
y + spacing + getChildAt(1).measuredHeight
)
} else {
getChildAt(0).layout(0, 0, halfWidth, height)
getChildAt(1).layout(halfWidth + spacing, 0, width, height)
}
}
3 -> {
if (measuredOrientation == LinearLayout.VERTICAL) {
val y = getChildAt(0).measuredHeight
getChildAt(0).layout(0, 0, width, y)
getChildAt(1).layout(0, y + spacing, halfWidth, height)
getChildAt(2).layout(halfWidth + spacing, y + spacing, width, height)
} else {
val colHeight = getChildAt(0).measuredHeight
getChildAt(0).layout(0, 0, halfWidth, colHeight)
val halfHeight = colHeight / 2 - spacing / 2
getChildAt(1).layout(halfWidth + spacing, 0, width, halfHeight)
getChildAt(2).layout(
halfWidth + spacing,
halfHeight + spacing,
width,
colHeight
)
}
}
4 -> {
val topHeight = (getChildAt(0).measuredHeight + getChildAt(1).measuredHeight) / 2
getChildAt(0).layout(0, 0, halfWidth, topHeight)
getChildAt(1).layout(halfWidth + spacing, 0, width, topHeight)
val bottomHeight =
(imageViewCache[2].measuredHeight + imageViewCache[3].measuredHeight) / 2
getChildAt(2).layout(
0,
topHeight + spacing,
halfWidth,
topHeight + spacing + bottomHeight
)
getChildAt(3).layout(
halfWidth + spacing,
topHeight + spacing,
width,
topHeight + spacing + bottomHeight
)
}
}
}
inline fun forEachIndexed(action: (Int, MediaPreviewImageView) -> Unit) {
for (index in 0 until childCount) {
action(index, getChildAt(index) as MediaPreviewImageView)
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
}
}
private fun rowHeight(halfWidth: Int, aspect1: Double, aspect2: Double): Int {
return ((halfWidth / aspect1 + halfWidth / aspect2) / 2).roundToInt()
}
private fun View.measureToAspect(width: Int, aspect: Double): Int {
val height = (width / aspect).roundToInt()
measureExactly(width, height)
return height
}
private fun View.measureExactly(width: Int, height: Int) {
measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
)
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_play_indicator"
android:gravity="center" />
</layer-list>

View File

@ -1,198 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<com.keylesspalace.tusky.view.MediaPreviewImageView
android:id="@+id/status_media_preview_0"
android:layout_width="0dp"
android:layout_height="@dimen/status_media_preview_height"
android:scaleType="centerCrop"
app:layout_constraintEnd_toStartOf="@+id/status_media_preview_1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<com.keylesspalace.tusky.view.MediaPreviewLayout
android:id="@+id/status_media_preview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toStartOf="@+id/status_media_preview_1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.keylesspalace.tusky.view.MediaPreviewImageView
android:id="@+id/status_media_preview_1"
android:layout_width="0dp"
android:layout_height="@dimen/status_media_preview_height"
android:layout_marginStart="4dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/status_media_preview_0"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_sensitive_media_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.7"
android:contentDescription="@null"
android:padding="@dimen/status_sensitive_media_button_padding"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="@+id/status_media_preview_container"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_container"
app:srcCompat="@drawable/ic_eye_24dp"
app:tint="@color/white" />
<com.keylesspalace.tusky.view.MediaPreviewImageView
android:id="@+id/status_media_preview_2"
android:layout_width="0dp"
android:layout_height="@dimen/status_media_preview_height"
android:layout_marginTop="4dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toStartOf="@+id/status_media_preview_3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_media_preview_0"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/status_sensitive_media_warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/media_warning_bg"
android:gravity="center"
android:lineSpacingMultiplier="1.2"
android:orientation="vertical"
android:paddingLeft="12dp"
android:paddingTop="8dp"
android:paddingRight="12dp"
android:paddingBottom="8dp"
android:textAlignment="center"
android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.keylesspalace.tusky.view.MediaPreviewImageView
android:id="@+id/status_media_preview_3"
android:layout_width="0dp"
android:layout_height="@dimen/status_media_preview_height"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:background="@drawable/media_preview_outline"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/status_media_preview_2"
app:layout_constraintTop_toBottomOf="@+id/status_media_preview_1"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/status_media_label_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:maxLines="10"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/status_media_overlay_0"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="@+id/status_media_preview_0"
app:layout_constraintEnd_toEndOf="@+id/status_media_preview_0"
app:layout_constraintStart_toStartOf="@+id/status_media_preview_0"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_0"
app:srcCompat="@drawable/ic_play_indicator"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/status_media_label_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:maxLines="10"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
<ImageView
android:id="@+id/status_media_overlay_1"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="@+id/status_media_preview_1"
app:layout_constraintEnd_toEndOf="@+id/status_media_preview_1"
app:layout_constraintStart_toStartOf="@+id/status_media_preview_1"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_1"
app:srcCompat="@drawable/ic_play_indicator"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/status_media_label_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:maxLines="10"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
<ImageView
android:id="@+id/status_media_overlay_2"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="@+id/status_media_preview_2"
app:layout_constraintEnd_toEndOf="@+id/status_media_preview_2"
app:layout_constraintStart_toStartOf="@+id/status_media_preview_2"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_2"
app:srcCompat="@drawable/ic_play_indicator"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_media_overlay_3"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="@+id/status_media_preview_3"
app:layout_constraintEnd_toEndOf="@+id/status_media_preview_3"
app:layout_constraintStart_toStartOf="@+id/status_media_preview_3"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_3"
app:srcCompat="@drawable/ic_play_indicator"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_sensitive_media_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.7"
android:contentDescription="@null"
android:padding="@dimen/status_sensitive_media_button_padding"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="@+id/status_media_preview_container"
app:layout_constraintTop_toTopOf="@+id/status_media_preview_container"
app:srcCompat="@drawable/ic_eye_24dp"
app:tint="@color/white" />
<TextView
android:id="@+id/status_sensitive_media_warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/media_warning_bg"
android:gravity="center"
android:lineSpacingMultiplier="1.2"
android:orientation="vertical"
android:paddingLeft="12dp"
android:paddingTop="8dp"
android:paddingRight="12dp"
android:paddingBottom="8dp"
android:textAlignment="center"
android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/status_media_label_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
android:maxLines="10"
android:ellipsize="end"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/status_media_label_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
android:maxLines="10"
android:ellipsize="end"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_0" />
<TextView
android:id="@+id/status_media_label_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
android:maxLines="10"
android:ellipsize="end"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_1" />
<TextView
android:id="@+id/status_media_label_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
android:maxLines="10"
android:ellipsize="end"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />
<TextView
android:id="@+id/status_media_label_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:drawablePadding="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:importantForAccessibility="no"
android:maxLines="10"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:drawableTint="?android:attr/textColorTertiary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_media_label_2" />
</merge>

View File

@ -58,4 +58,5 @@
<dimen name="profile_media_audio_icon_padding">16dp</dimen>
<dimen name="preview_image_spacing">4dp</dimen>
</resources>