From c2266804f01156ee268660c51a027c2e8aa45812 Mon Sep 17 00:00:00 2001 From: Ivan Kupalov Date: Mon, 30 Jul 2018 15:36:22 +0200 Subject: [PATCH] Add RoundedImageView for avatars (#739) * Add RoundedImageView for avatars * RoundedImageView: Remove unused things, fix touchable area --- app/build.gradle | 1 - .../keylesspalace/tusky/AccountActivity.kt | 2 - .../keylesspalace/tusky/ComposeActivity.java | 4 +- .../tusky/adapter/AccountViewHolder.java | 4 +- .../tusky/adapter/BlocksAdapter.java | 4 +- .../tusky/adapter/FollowRequestsAdapter.java | 6 +- .../adapter/MentionAutoCompleteAdapter.java | 2 - .../tusky/adapter/MutesAdapter.java | 4 +- .../tusky/adapter/NotificationsAdapter.java | 6 +- .../tusky/adapter/StatusBaseViewHolder.java | 8 +- .../tusky/adapter/StatusViewHolder.java | 3 +- .../tusky/view/RoundedImageView.java | 332 ++++++++++++++++++ app/src/main/res/drawable/round_button.xml | 3 +- app/src/main/res/layout/activity_account.xml | 3 +- app/src/main/res/layout/activity_compose.xml | 2 +- .../main/res/layout/activity_edit_profile.xml | 2 +- app/src/main/res/layout/item_account.xml | 2 +- app/src/main/res/layout/item_autocomplete.xml | 2 +- app/src/main/res/layout/item_blocked_user.xml | 2 +- app/src/main/res/layout/item_follow.xml | 4 +- .../main/res/layout/item_follow_request.xml | 2 +- app/src/main/res/layout/item_muted_user.xml | 2 +- app/src/main/res/layout/item_status.xml | 6 +- .../main/res/layout/item_status_detailed.xml | 4 +- .../res/layout/item_status_notification.xml | 4 +- .../main/res/layout/view_account_moved.xml | 2 +- 26 files changed, 367 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/com/keylesspalace/tusky/view/RoundedImageView.java diff --git a/app/build.gradle b/app/build.gradle index 63353d80..91fb8a8b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,7 +81,6 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp:3.11.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' - implementation 'com.pkmmte.view:circularimageview:1.1' implementation 'com.github.connyduck:sparkbutton:1.0.1' implementation 'com.github.chrisbanes:PhotoView:2.1.3' implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar' diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt index 9bb731ec..4968499c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt @@ -314,7 +314,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF Picasso.with(this) .load(account.avatar) - .transform(RoundedTransformation(25f)) .placeholder(R.drawable.avatar_default) .into(accountAvatarImageView) Picasso.with(this) @@ -340,7 +339,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasSupportF Picasso.with(this) .load(movedAccount.avatar) - .transform(RoundedTransformation(25f)) .placeholder(R.drawable.avatar_default) .into(accountMovedAvatar) diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 70c24130..81b68897 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -111,12 +111,10 @@ import com.keylesspalace.tusky.view.ComposeOptionsListener; import com.keylesspalace.tusky.view.ComposeOptionsView; import com.keylesspalace.tusky.view.EditTextTyped; import com.keylesspalace.tusky.view.ProgressImageView; -import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.view.TootButton; import com.mikepenz.google_material_typeface_library.GoogleMaterial; import com.mikepenz.iconics.IconicsDrawable; import com.squareup.picasso.Picasso; -import at.connyduck.sparkbutton.helpers.Utils; import org.jetbrains.annotations.NotNull; @@ -135,6 +133,7 @@ import java.util.Locale; import javax.inject.Inject; +import at.connyduck.sparkbutton.helpers.Utils; import okhttp3.MediaType; import okhttp3.MultipartBody; import retrofit2.Call; @@ -264,7 +263,6 @@ public final class ComposeActivity composeAvatar.setImageResource(R.drawable.avatar_default); } else { Picasso.with(this).load(activeAccount.getProfilePictureUrl()) - .transform(new RoundedTransformation(25)) .error(R.drawable.avatar_default) .placeholder(R.drawable.avatar_default) .into(composeAvatar); diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java index de2e593e..c156d6ae 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java @@ -3,6 +3,7 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.View; +import android.widget.ImageView; import android.widget.TextView; import com.keylesspalace.tusky.R; @@ -10,14 +11,13 @@ import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.interfaces.LinkListener; import com.keylesspalace.tusky.util.CustomEmojiHelper; -import com.pkmmte.view.CircularImageView; import com.squareup.picasso.Picasso; class AccountViewHolder extends RecyclerView.ViewHolder { private View container; private TextView username; private TextView displayName; - private CircularImageView avatar; + private ImageView avatar; private String accountId; AccountViewHolder(View itemView) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java index bbe171f0..21689e91 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java @@ -21,13 +21,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.TextView; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.util.CustomEmojiHelper; -import com.pkmmte.view.CircularImageView; import com.squareup.picasso.Picasso; public class BlocksAdapter extends AccountAdapter { @@ -78,7 +78,7 @@ public class BlocksAdapter extends AccountAdapter { } static class BlockedUserViewHolder extends RecyclerView.ViewHolder { - private CircularImageView avatar; + private ImageView avatar; private TextView username; private TextView displayName; private ImageButton unblock; diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java index c7b77b28..31c19102 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java @@ -21,13 +21,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.TextView; -import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.entity.Account; +import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.util.CustomEmojiHelper; -import com.pkmmte.view.CircularImageView; import com.squareup.picasso.Picasso; public class FollowRequestsAdapter extends AccountAdapter { @@ -78,7 +78,7 @@ public class FollowRequestsAdapter extends AccountAdapter { } static class FollowRequestViewHolder extends RecyclerView.ViewHolder { - private CircularImageView avatar; + private ImageView avatar; private TextView username; private TextView displayName; private ImageButton accept; diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MentionAutoCompleteAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/MentionAutoCompleteAdapter.java index b0a9def9..e802c3ee 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/MentionAutoCompleteAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/MentionAutoCompleteAdapter.java @@ -31,7 +31,6 @@ import android.widget.TextView; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.util.CustomEmojiHelper; -import com.keylesspalace.tusky.view.RoundedTransformation; import com.squareup.picasso.Picasso; import java.util.ArrayList; @@ -131,7 +130,6 @@ public class MentionAutoCompleteAdapter extends ArrayAdapter Picasso.with(context) .load(account.getAvatar()) .placeholder(R.drawable.avatar_default) - .transform(new RoundedTransformation(25)) .into(avatar); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java index d9c0d6cf..b3c780d3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java @@ -6,13 +6,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.TextView; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.interfaces.AccountActionListener; import com.keylesspalace.tusky.util.CustomEmojiHelper; -import com.pkmmte.view.CircularImageView; import com.squareup.picasso.Picasso; public class MutesAdapter extends AccountAdapter { @@ -63,7 +63,7 @@ public class MutesAdapter extends AccountAdapter { } static class MutedUserViewHolder extends RecyclerView.ViewHolder { - private CircularImageView avatar; + private ImageView avatar; private TextView username; private TextView displayName; private ImageButton unmute; diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 2ad42ec6..136805fa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -23,8 +23,8 @@ import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; -import android.support.v7.widget.RecyclerView; import android.support.v4.text.BidiFormatter; +import android.support.v7.widget.RecyclerView; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -46,7 +46,6 @@ import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.util.CustomEmojiHelper; import com.keylesspalace.tusky.util.DateUtils; import com.keylesspalace.tusky.util.LinkHelper; -import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.viewdata.NotificationViewData; import com.keylesspalace.tusky.viewdata.StatusViewData; import com.squareup.picasso.Picasso; @@ -291,7 +290,6 @@ public class NotificationsAdapter extends RecyclerView.Adapter { Picasso.with(context) .load(account.getAvatar()) .fit() - .transform(new RoundedTransformation(25)) .placeholder(R.drawable.avatar_default) .into(avatar); } @@ -454,7 +452,6 @@ public class NotificationsAdapter extends RecyclerView.Adapter { Picasso.with(context) .load(statusAvatarUrl) .placeholder(R.drawable.avatar_default) - .transform(new RoundedTransformation(25)) .into(statusAvatar); } @@ -465,7 +462,6 @@ public class NotificationsAdapter extends RecyclerView.Adapter { .load(notificationAvatarUrl) .placeholder(R.drawable.avatar_default) .fit() - .transform(new RoundedTransformation(25)) .into(notificationAvatar); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index db96a17e..4bfd545b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -26,17 +26,16 @@ import com.keylesspalace.tusky.util.DateUtils; import com.keylesspalace.tusky.util.HtmlUtils; import com.keylesspalace.tusky.util.LinkHelper; import com.keylesspalace.tusky.util.ThemeUtils; -import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.viewdata.StatusViewData; import com.mikepenz.iconics.utils.Utils; import com.squareup.picasso.Picasso; -import at.connyduck.sparkbutton.SparkButton; -import at.connyduck.sparkbutton.SparkEventListener; - import java.util.Date; import java.util.List; +import at.connyduck.sparkbutton.SparkButton; +import at.connyduck.sparkbutton.SparkEventListener; + abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { private View container; private TextView displayName; @@ -122,7 +121,6 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { Picasso.with(avatar.getContext()) .load(url) .placeholder(R.drawable.avatar_default) - .transform(new RoundedTransformation(25)) .into(avatar); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java index 0dc0d74c..fcd96e52 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java @@ -25,9 +25,9 @@ import android.widget.TextView; import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.util.ThemeUtils; -import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.viewdata.StatusViewData; import com.squareup.picasso.Picasso; + import at.connyduck.sparkbutton.helpers.Utils; public class StatusViewHolder extends StatusBaseViewHolder { @@ -59,7 +59,6 @@ public class StatusViewHolder extends StatusBaseViewHolder { Picasso.with(context) .load(rebloggedUrl) .placeholder(R.drawable.avatar_default) - .transform(new RoundedTransformation(25)) .into(avatarReblog); } else { avatarReblog.setVisibility(View.GONE); diff --git a/app/src/main/java/com/keylesspalace/tusky/view/RoundedImageView.java b/app/src/main/java/com/keylesspalace/tusky/view/RoundedImageView.java new file mode 100644 index 00000000..dc07d27d --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/view/RoundedImageView.java @@ -0,0 +1,332 @@ +package com.keylesspalace.tusky.view; + +/* + * Original CircleImageView Copyright 2014 - 2018 Henning Dodenhof + * Adapted to RoundedImageView by charlag in 2018 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.support.annotation.DrawableRes; +import android.support.annotation.RequiresApi; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; + +public class RoundedImageView extends AppCompatImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT; + private static float ROUNDED_PERCENT = 25; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + private final Paint mCircleBackgroundPaint = new Paint(); + + private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + + public RoundedImageView(Context context) { + super(context); + + init(); + } + + public RoundedImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RoundedImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setOutlineProvider(new OutlineProvider()); + } + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + + if (mBitmap == null) { + return; + } + + if (mCircleBackgroundColor != Color.TRANSPARENT) { + canvas.drawRoundRect(mDrawableRect, mDrawableRadius, mDrawableRadius, + mCircleBackgroundPaint); + } + canvas.drawRoundRect(mDrawableRect, mDrawableRadius, mDrawableRadius, mBitmapPaint); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + @Override + public void setPadding(int left, int top, int right, int bottom) { + super.setPadding(left, top, right, bottom); + setup(); + } + + @Override + public void setPaddingRelative(int start, int top, int end, int bottom) { + super.setPaddingRelative(start, top, end, bottom); + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + initializeBitmap(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + initializeBitmap(); + } + + @Override + public void setImageResource(@DrawableRes int resId) { + super.setImageResource(resId); + initializeBitmap(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + initializeBitmap(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + applyColorFilter(); + invalidate(); + } + + @Override + public ColorFilter getColorFilter() { + return mColorFilter; + } + + private void applyColorFilter() { + if (mBitmapPaint != null) { + mBitmapPaint.setColorFilter(mColorFilter); + } + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void initializeBitmap() { + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (getWidth() == 0 && getHeight() == 0) { + return; + } + + if (mBitmap == null) { + invalidate(); + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(DEFAULT_BORDER_COLOR); + mBorderPaint.setStrokeWidth(DEFAULT_BORDER_WIDTH); + + mCircleBackgroundPaint.setStyle(Paint.Style.FILL); + mCircleBackgroundPaint.setAntiAlias(true); + mCircleBackgroundPaint.setColor(mCircleBackgroundColor); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(calculateBounds()); + + float shorterSideBorder = Math.min(mBorderRect.width(), mBorderRect.height()); + mBorderRadius = shorterSideBorder / 2 * ROUNDED_PERCENT / 100; + + mDrawableRect.set(mBorderRect); + + float shorterSide = Math.min(mDrawableRect.width(), mDrawableRect.height()); + mDrawableRadius = shorterSide / 2 * ROUNDED_PERCENT / 100; + + + applyColorFilter(); + updateShaderMatrix(); + invalidate(); + } + + private RectF calculateBounds() { + int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); + + int sideLength = Math.min(availableWidth, availableHeight); + + float left = getPaddingLeft() + (availableWidth - sideLength) / 2f; + float top = getPaddingTop() + (availableHeight - sideLength) / 2f; + + return new RectF(left, top, left + sideLength, top + sideLength); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private class OutlineProvider extends ViewOutlineProvider { + + @Override + public void getOutline(View view, Outline outline) { + Rect bounds = new Rect(); + mBorderRect.roundOut(bounds); + outline.setRoundRect(bounds, mBorderRadius); + } + + } + +} diff --git a/app/src/main/res/drawable/round_button.xml b/app/src/main/res/drawable/round_button.xml index cdcac515..a6c0da18 100644 --- a/app/src/main/res/drawable/round_button.xml +++ b/app/src/main/res/drawable/round_button.xml @@ -1,6 +1,7 @@ + android:shape="rectangle"> + - - diff --git a/app/src/main/res/layout/activity_compose.xml b/app/src/main/res/layout/activity_compose.xml index 4a4090c9..6670c4c3 100644 --- a/app/src/main/res/layout/activity_compose.xml +++ b/app/src/main/res/layout/activity_compose.xml @@ -13,7 +13,7 @@ android:layout_marginBottom="8dp" android:background="@android:color/transparent"> - - - - - - - - - - - - diff --git a/app/src/main/res/layout/view_account_moved.xml b/app/src/main/res/layout/view_account_moved.xml index 92f3764c..b35b7d3e 100644 --- a/app/src/main/res/layout/view_account_moved.xml +++ b/app/src/main/res/layout/view_account_moved.xml @@ -15,7 +15,7 @@ android:textSize="?attr/status_text_medium" tools:text="Account has moved" /> -