revise nft ui (#3072)

* Avoid exceed parent rounded corners and clip bottom rounded corners
* Ensure border visible
* Fix round corners for .webp
* Fix title not displaying
* Fix layouts
* Revise collectibles grid
* Revise layout when on image on the same row as a svg (loading with WebView)
* Fix activity details NFT display
pull/3172/head
Seaborn 2 years ago committed by GitHub
parent acefb4ba47
commit e13ddf4825
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/build.gradle
  2. 7
      app/src/main/java/com/alphawallet/app/ui/NFTAssetsFragment.java
  3. 79
      app/src/main/java/com/alphawallet/app/ui/widget/adapter/NFTAssetsAdapter.java
  4. 66
      app/src/main/java/com/alphawallet/app/util/RoundedTopCorners.java
  5. 8
      app/src/main/java/com/alphawallet/app/walletconnect/WalletConnectV2SessionRequestHandler.java
  6. 2
      app/src/main/java/com/alphawallet/app/widget/ActionSheetDialog.java
  7. 90
      app/src/main/java/com/alphawallet/app/widget/NFTImageView.java
  8. 3
      app/src/main/java/com/alphawallet/app/widget/TokenIcon.java
  9. 11
      app/src/main/res/drawable/background_round_bottom_corners.xml
  10. 11
      app/src/main/res/drawable/background_round_top_corners.xml
  11. 5
      app/src/main/res/layout/item_asset_detail.xml
  12. 18
      app/src/main/res/layout/item_asset_image.xml
  13. 125
      app/src/main/res/layout/item_erc1155_asset_select_grid.xml
  14. 3
      app/src/main/res/layout/item_token_grid.xml
  15. 8
      app/src/main/res/layout/item_token_icon_square.xml

@ -309,8 +309,8 @@ dependencies {
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
// Image Loader
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'com.github.bumptech.glide:glide:4.13.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
implementation group: 'com.google.guava', name: 'guava', version: '30.1.1-android'

@ -183,6 +183,13 @@ public class NFTAssetsFragment extends BaseFragment implements OnAssetClickListe
Bundle result = new Bundle();
result.putBoolean(SYNC_STATUS, token.getTokenCount() != token.getTokenAssets().size());
getParentFragmentManager().setFragmentResult(SIGNAL_NFT_SYNC, result);
forceRedraw();
}
// This is a trick to fix a bug
private void forceRedraw()
{
search.setText("");
}
private boolean hasTokenScriptOverride(Token t)

@ -7,8 +7,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -34,8 +32,10 @@ import java.util.Map;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
public class NFTAssetsAdapter extends RecyclerView.Adapter<NFTAssetsAdapter.ViewHolder> {
public class NFTAssetsAdapter extends RecyclerView.Adapter<NFTAssetsAdapter.ViewHolder>
{
private final Activity activity;
private final OnAssetClickListener listener;
private final Token token;
@ -103,56 +103,48 @@ public class NFTAssetsAdapter extends RecyclerView.Adapter<NFTAssetsAdapter.View
if (item != null && item.requiresReplacement())
{
fetchAsset(holder, pair);
if (!holder.icon.hasContent())
{
holder.loadingSpinner.setVisibility(View.VISIBLE);
}
}
}
private void displayAsset(@NotNull ViewHolder holder, NFTAsset asset, BigInteger tokenId)
{
displayTitle(holder, asset, token, tokenId);
displayImage(holder, asset);
holder.layout.setOnClickListener(v -> listener.onAssetClicked(new Pair<>(tokenId, asset)));
}
private void displayImage(@NonNull ViewHolder holder, NFTAsset asset)
{
if (asset.hasImageAsset())
{
holder.icon.setupTokenImageThumbnail(asset, isGrid);
}
else
{
holder.icon.showFallbackLayout(token);
}
}
private void displayTitle(@NotNull ViewHolder holder, NFTAsset asset, Token token, BigInteger tokenId)
{
int assetCount = asset.isCollection() ? asset.getCollectionCount() : asset.getBalance().intValue();
int textId = assetCount == 1 ? R.string.asset_description_text : R.string.asset_description_text_plural;
if (asset.isBlank())
String title = asset.getName() == null ? String.format("ID #%s", tokenId) : asset.getName();
holder.title.setText(title);
// set subtitle
if (token.isERC721())
{
holder.title.setText(String.format("ID #%s", tokenId));
// Hide subtitle containing redundant information
holder.subtitle.setVisibility(View.GONE);
}
else
{
if (asset.getName() != null)
{
holder.title.setText(asset.getName());
if (token.isERC721())
{
// Hide subtitle containing redundant information
holder.subtitle.setVisibility(View.GONE);
}
else
{
holder.subtitle.setVisibility(View.VISIBLE);
holder.subtitle.setText(activity.getString(textId, assetCount, asset.getAssetCategory(tokenId).getValue()));
}
}
else
{
holder.title.setText(String.format("ID #%s", tokenId));
holder.subtitle.setVisibility(View.GONE);
}
if (asset.hasImageAsset())
{
holder.icon.setupTokenImageThumbnail(asset);
}
else
{
holder.icon.showFallbackLayout(token);
}
holder.subtitle.setText(activity.getString(textId, assetCount, asset.getAssetCategory(tokenId).getValue()));
holder.subtitle.setVisibility(View.VISIBLE);
}
holder.layout.setOnClickListener(v -> listener.onAssetClicked(new Pair<>(tokenId, asset)));
holder.loadingSpinner.setVisibility(View.GONE);
}
private void fetchAsset(ViewHolder holder, Pair<BigInteger, NFTAsset> pair)
@ -273,12 +265,12 @@ public class NFTAssetsAdapter extends RecyclerView.Adapter<NFTAssetsAdapter.View
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
RelativeLayout layout;
static class ViewHolder extends RecyclerView.ViewHolder
{
ViewGroup layout;
NFTImageView icon;
TextView title;
TextView subtitle;
ProgressBar loadingSpinner;
ImageView arrowRight;
ViewHolder(View view)
@ -288,7 +280,6 @@ public class NFTAssetsAdapter extends RecyclerView.Adapter<NFTAssetsAdapter.View
icon = view.findViewById(R.id.icon);
title = view.findViewById(R.id.title);
subtitle = view.findViewById(R.id.subtitle);
loadingSpinner = view.findViewById(R.id.loading_spinner);
arrowRight = view.findViewById(R.id.arrow_right);
if (arrowRight != null) arrowRight.setVisibility(View.VISIBLE);

@ -0,0 +1,66 @@
package com.alphawallet.app.util;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Util;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
public final class RoundedTopCorners extends BitmapTransformation
{
private static final String ID = "com.bumptech.glide.load.resource.bitmap.RoundedCorners";
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);
private final int roundingRadius;
/**
* @param roundingRadius the corner radius (in device-specific pixels).
* @throws IllegalArgumentException if rounding radius is 0 or less.
*/
public RoundedTopCorners(int roundingRadius)
{
Preconditions.checkArgument(roundingRadius > 0, "roundingRadius must be greater than 0.");
this.roundingRadius = roundingRadius;
}
@Override
protected Bitmap transform(
@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight)
{
return TransformationUtils.roundedCorners(pool, toTransform, roundingRadius, roundingRadius, 0, 0);
}
@Override
public boolean equals(Object o)
{
if (o instanceof RoundedTopCorners)
{
RoundedTopCorners other = (RoundedTopCorners) o;
return roundingRadius == other.roundingRadius;
}
return false;
}
@Override
public int hashCode()
{
return Util.hashCode(ID.hashCode(), Util.hashCode(roundingRadius));
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest)
{
messageDigest.update(ID_BYTES);
byte[] radiusData = ByteBuffer.allocate(4).putInt(roundingRadius).array();
messageDigest.update(radiusData);
}
}

@ -86,13 +86,10 @@ public class WalletConnectV2SessionRequestHandler
}
}
@SuppressWarnings("checkstyle:MissingSwitchDefault")
private boolean validateChainId(Signable signable)
{
switch (signable.getMessageType())
{
case SIGN_ERROR:
return false;
case SIGN_MESSAGE:
case SIGN_PERSONAL_MESSAGE:
case SIGN_TYPED_DATA:
@ -104,9 +101,10 @@ public class WalletConnectV2SessionRequestHandler
case ATTESTATION:
//TODO: Check attestation signing chain
return true;
case SIGN_ERROR:
default:
return false;
}
return false;
}
private WalletConnectV2SessionItem getSessionItem()

@ -657,7 +657,6 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
/**
* Either Send or Sign (WalletConnect only) the transaction
*/
@SuppressWarnings("checkstyle:MissingSwitchDefault")
private void handleTransactionOperation()
{
if (walletType != WalletType.HARDWARE)
@ -699,6 +698,7 @@ public class ActionSheetDialog extends ActionSheet implements StandardFunctionIn
case SIGN_MESSAGE:
case WALLET_CONNECT_REQUEST:
case NODE_STATUS_INFO:
default:
break;
}

@ -8,6 +8,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
@ -21,6 +22,7 @@ import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
@ -32,9 +34,11 @@ import com.alphawallet.app.C;
import com.alphawallet.app.R;
import com.alphawallet.app.entity.nftassets.NFTAsset;
import com.alphawallet.app.entity.tokens.Token;
import com.alphawallet.app.util.RoundedTopCorners;
import com.alphawallet.app.util.Utils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
@ -47,6 +51,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import timber.log.Timber;
@ -69,7 +74,7 @@ public class NFTImageView extends RelativeLayout
/**
* Prevent glide dumping log errors - it is expected that load will fail
*/
private final RequestListener<Drawable> requestListener = new RequestListener<Drawable>()
private final RequestListener<Drawable> requestListener = new RequestListener<>()
{
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource)
@ -79,13 +84,14 @@ public class NFTImageView extends RelativeLayout
if (msg.contains(C.GLIDE_URL_INVALID)) //URL not valid: use the attribute name
{
handler.post(() -> {
progressBar.setVisibility(View.GONE);
fallbackLayout.setVisibility(View.VISIBLE);
progressBar.setVisibility(GONE);
fallbackLayout.setVisibility(VISIBLE);
});
}
else if (model != null) //or fallback to webview if there was some other problem
{
setWebView(model.toString(), ImageType.IMAGE);
fallbackLayout.setVisibility(GONE);
}
return false;
}
@ -93,14 +99,14 @@ public class NFTImageView extends RelativeLayout
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
{
progressBar.setVisibility(View.GONE);
progressBar.setVisibility(GONE);
fallbackLayout.setVisibility(GONE);
return false;
}
};
private Request loadRequest;
private String imageUrl;
private boolean hasContent;
private boolean showProgress;
private boolean isThumbnail;
public NFTImageView(Context context, @Nullable AttributeSet attrs)
{
@ -116,9 +122,8 @@ public class NFTImageView extends RelativeLayout
overlay = findViewById(R.id.overlay_rect);
mediaPlayer = null;
webLayout.setVisibility(View.GONE);
webView.setVisibility(View.GONE);
showProgress = false;
webLayout.setVisibility(GONE);
webView.setVisibility(GONE);
if (loadRequest != null && loadRequest.isRunning())
{
@ -130,13 +135,20 @@ public class NFTImageView extends RelativeLayout
}
public void setupTokenImageThumbnail(NFTAsset asset)
{
setupTokenImageThumbnail(asset, false);
}
public void setupTokenImageThumbnail(NFTAsset asset, boolean onlyRoundTopCorners)
{
fallbackIcon.setupFallbackTextIcon(asset.getName());
loadImage(asset.getThumbnail(), asset.getBackgroundColor(), 1);
isThumbnail = true;
loadImage(asset.getThumbnail(), asset.getBackgroundColor(), 30, onlyRoundTopCorners);
}
public void setupTokenImage(NFTAsset asset) throws IllegalArgumentException
{
isThumbnail = false;
String anim = asset.getAnimation();
fallbackIcon.setupFallbackTextIcon(asset.getName());
@ -148,23 +160,20 @@ public class NFTImageView extends RelativeLayout
}
else if (shouldLoad(asset.getImage()))
{
showLoadingProgress();
progressBar.setVisibility(showProgress ? View.VISIBLE : View.GONE);
loadImage(asset.getImage(), asset.getBackgroundColor(), 16);
loadImage(asset.getImage(), asset.getBackgroundColor(), 16, false);
playAudioIfAvailable(anim);
}
}
private void loadImage(String url, String backgroundColor, int corners) throws IllegalArgumentException
private void loadImage(String url, String backgroundColor, int corners, boolean onlyRoundTopCorners) throws IllegalArgumentException
{
if (!Utils.stillAvailable(getContext())) return;
setWebViewHeight((int)getLayoutParams().width);
setWebViewHeight(getLayoutParams().width);
this.imageUrl = url;
fallbackLayout.setVisibility(View.GONE);
image.setVisibility(View.VISIBLE);
webLayout.setVisibility(View.GONE);
webLayout.setVisibility(GONE);
try
{
@ -177,9 +186,24 @@ public class NFTImageView extends RelativeLayout
holdingView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.transparent));
}
if (url.toLowerCase(Locale.ROOT).contains(".webp"))
{
corners += 30;
}
Transformation<Bitmap> roundedCorners;
if (onlyRoundTopCorners)
{
roundedCorners = new RoundedTopCorners(corners);
}
else
{
roundedCorners = new RoundedCorners(corners);
}
loadRequest = Glide.with(getContext())
.load(url)
.transform(new CenterCrop(), new RoundedCorners(corners))
.transform(new CenterCrop(), roundedCorners)
.transition(withCrossFade())
.override(Target.SIZE_ORIGINAL)
.timeout(30 * 1000)
@ -193,17 +217,26 @@ public class NFTImageView extends RelativeLayout
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient()
{
@Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
progressBar.setVisibility(GONE);
}
});
//determine how to display this URL
final DisplayType useType = new DisplayType(imageUrl, hint);
handler.post(() -> {
this.imageUrl = imageUrl;
image.setVisibility(View.GONE);
image.setVisibility(GONE);
webLayout.setVisibility(View.VISIBLE);
webView.setVisibility(View.VISIBLE);
overlay.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
progressBar.setVisibility(GONE);
if (useType.getImageType() == ImageType.WEB)
{
@ -234,6 +267,10 @@ public class NFTImageView extends RelativeLayout
String loader = loadFile(getContext(), R.raw.token_graphic).replace("[URL]", imageUrl);
String base64 = android.util.Base64.encodeToString(loader.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
webView.loadData(base64, "text/html; charset=utf-8", "base64");
if (isThumbnail)
{
setWebViewHeight(500);
}
}
});
}
@ -271,17 +308,6 @@ public class NFTImageView extends RelativeLayout
fallbackLayout.setVisibility(View.VISIBLE);
fallbackIcon.bindData(token);
hasContent = true;
}
public boolean hasContent()
{
return hasContent;
}
public void showLoadingProgress()
{
this.showProgress = true;
}
public boolean shouldLoad(String url)
@ -318,7 +344,7 @@ public class NFTImageView extends RelativeLayout
return (url != null && MimeTypeMap.getFileExtensionFromUrl(url).equals("glb"));
}
private static final List<String> audioTypes = new ArrayList<>(Arrays.asList( "mp3", "ogg", "wav", "flac", "aac", "opus", "weba" ));
private static final List<String> audioTypes = new ArrayList<>(Arrays.asList("mp3", "ogg", "wav", "flac", "aac", "opus", "weba"));
private boolean isAudio(String url)
{

@ -33,10 +33,13 @@ import com.alphawallet.app.service.TokensService;
import com.alphawallet.app.ui.widget.TokensAdapterCallback;
import com.alphawallet.app.ui.widget.entity.IconItem;
import com.alphawallet.app.ui.widget.entity.StatusType;
import com.alphawallet.app.util.RoundedTopCorners;
import com.alphawallet.app.util.Utils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.FitCenter;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?colorSurface" />
<stroke
android:width="1dp"
android:color="?colorSurfaceQuaternary" />
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
</shape>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?colorSurface" />
<stroke
android:width="1dp"
android:color="?colorSurfaceQuaternary" />
<corners
android:topLeftRadius="10dp"
android:topRightRadius="10dp" />
</shape>

@ -72,8 +72,7 @@
<com.alphawallet.app.widget.NFTImageView
android:id="@+id/asset_image"
android:layout_width="match_parent"
android:layout_height="250dp"
android:gravity="center"
android:layout_height="wrap_content"
custom:webview_height="250" />
<TextView
@ -93,4 +92,4 @@
tools:text="A narcissist drew herself." />
</LinearLayout>
</LinearLayout>
</LinearLayout>

@ -4,31 +4,31 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_asset"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
tools:src="@drawable/ic_token_eth" />
<ProgressBar
android:id="@+id/avatar_progress_spinner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/progress_bar_spinner"
android:visibility="gone"
tools:visibility="visible" />
android:visibility="invisible"
tools:visibility="invisible" />
<RelativeLayout
android:id="@+id/web_view_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
android:padding="4dp"
android:visibility="gone" >
<WebView
android:id="@+id/image_web_view"
@ -61,7 +61,7 @@
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:visibility="gone">
android:visibility="invisible">
<com.alphawallet.app.widget.TokenIcon
android:id="@+id/icon_fallback"

@ -1,92 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/holding_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/holding_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:cardCornerRadius="8dp"
custom:cardElevation="0dp"
android:background="@drawable/background_grid_icon"
custom:strokeColor="?colorSurfaceQuaternary"
custom:strokeWidth="1dp">
<LinearLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_alignParentTop="true"
android:paddingBottom="35dp">
<RelativeLayout
android:id="@+id/icon_wrapper"
<com.alphawallet.app.widget.NFTImageView
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<com.alphawallet.app.widget.NFTImageView
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="156dp"
android:layout_centerInParent="true" />
android:layout_height="match_parent" />
<TextView
android:id="@+id/text_count"
style="@style/Aw.Typography.Title.SemiBold"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerInParent="true"
android:background="@drawable/value_amount_overlay"
android:backgroundTint="?colorPrimary"
android:gravity="center"
android:textColor="?colorOnPrimary"
android:visibility="gone"
tools:text="25"
tools:visibility="visible" />
<TextView
android:id="@+id/text_count"
style="@style/Aw.Typography.Title.SemiBold"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerInParent="true"
android:background="@drawable/value_amount_overlay"
android:backgroundTint="?colorPrimary"
android:gravity="center"
android:textColor="?colorOnPrimary"
android:visibility="gone"
tools:text="25"
tools:visibility="visible" />
<ProgressBar
android:id="@+id/loading_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="@dimen/standard_16"
android:visibility="gone"
tools:visibility="visible" />
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_round_bottom_corners"
android:layout_alignParentBottom="true"
android:padding="@dimen/dp9">
<RelativeLayout
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/standard_16">
android:layout_alignParentStart="true"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
tools:text="Title" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
tools:text="Title" />
<TextView
android:id="@+id/subtitle"
style="@style/Aw.Typography.Sub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:gravity="center"
android:singleLine="true"
android:visibility="gone"
tools:text="Subtitle"
tools:visibility="visible" />
</RelativeLayout>
</LinearLayout>
<TextView
android:id="@+id/subtitle"
style="@style/Aw.Typography.Sub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:gravity="center"
android:singleLine="true"
android:visibility="gone"
tools:text="Subtitle"
tools:visibility="visible" />
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>

@ -7,6 +7,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/small_12"
android:padding="1dp"
android:background="@drawable/background_grid_icon"
android:gravity="center_horizontal"
android:orientation="vertical">
@ -60,4 +61,4 @@
android:focusable="true"
android:orientation="vertical" />
</RelativeLayout>
</RelativeLayout>

@ -4,8 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_height="match_parent"
app:layout_constraintDimensionRatio="1:1">
<androidx.constraintlayout.widget.Guideline
@ -92,6 +91,7 @@
android:layout_gravity="center"
android:contentDescription="@string/empty"
android:gravity="center"
android:scaleType="fitStart"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="@id/guidelineInnerBottom"
app:layout_constraintDimensionRatio="H,1:1"
@ -106,7 +106,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:background="?colorPrimary"
android:background="@drawable/background_round_top_corners"
android:backgroundTint="?colorPrimary"
android:gravity="center"
android:lines="1"
@ -176,4 +176,4 @@
app:layout_constraintTop_toTopOf="@id/guidelineBottomMid" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Loading…
Cancel
Save