Improved user profile image picking

main
Hemanth S 2020-05-21 04:23:09 +05:30
parent 607d1722da
commit 2c4b00edb9
7 changed files with 412 additions and 360 deletions

View File

@ -183,4 +183,5 @@ dependencies {
implementation 'com.google.android.play:core:1.7.2'
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
}

View File

@ -1,38 +1,38 @@
package code.name.monkey.retromusic.activities
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore.Images.Media
import android.provider.MediaStore.Images.Media.getBitmap
import android.text.TextUtils
import android.view.MenuItem
import android.widget.Toast
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.Constants.USER_PROFILE
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.applyToolbar
import code.name.monkey.retromusic.util.Compressor
import code.name.monkey.retromusic.util.ImageUtil.getResizedBitmap
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
import code.name.monkey.retromusic.glide.UserProfileGlideRequest
import code.name.monkey.retromusic.util.ImageUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItems
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.github.dhaval2404.imagepicker.ImagePicker
import kotlinx.android.synthetic.main.activity_user_info.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
@ -46,53 +46,19 @@ class UserInfoActivity : AbsBaseActivity() {
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
applyToolbar(toolbar)
MaterialUtil.setTint(nameContainer, false)
name.setText(PreferenceUtil.getInstance(this).userName)
if (PreferenceUtil.getInstance(this).profileImage.isNotEmpty()) {
loadImageFromStorage(PreferenceUtil.getInstance(this).profileImage)
}
if (PreferenceUtil.getInstance(this).bannerImage.isNotEmpty()) {
loadBannerFromStorage(PreferenceUtil.getInstance(this).bannerImage)
}
userImage.setOnClickListener {
MaterialDialog(this).show {
cornerRadius(PreferenceUtil.getInstance(this@UserInfoActivity).dialogCorner)
title(text = getString(R.string.set_photo))
listItems(
items = listOf(
getString(R.string.new_profile_photo),
getString(R.string.remove_profile_photo)
)
) { _, position, _ ->
when (position) {
0 -> pickNewPhoto()
1 -> PreferenceUtil.getInstance(this@UserInfoActivity).saveProfileImage("")
}
}
}
pickNewPhoto()
}
bannerSelect.setOnClickListener {
MaterialDialog(this).show {
cornerRadius(PreferenceUtil.getInstance(this@UserInfoActivity).dialogCorner)
title(R.string.select_banner_photo)
listItems(
items = listOf(
getString(R.string.new_banner_photo),
getString(R.string.remove_banner_photo)
)
)
{ _, position, _ ->
when (position) {
0 -> selectBannerImage()
1 -> PreferenceUtil.getInstance(this@UserInfoActivity)
.setBannerImagePath("")
}
}
}
selectBannerImage()
}
next.setOnClickListener {
val nameString = name.text.toString().trim { it <= ' ' }
if (TextUtils.isEmpty(nameString)) {
@ -103,17 +69,26 @@ class UserInfoActivity : AbsBaseActivity() {
setResult(Activity.RESULT_OK)
finish()
}
next.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
ColorStateList.valueOf(
MaterialValueHelper.getPrimaryTextColor(
this,
ColorUtil.isColorLight(ThemeStore.accentColor(this))
)
)
.apply {
next.setTextColor(this)
next.iconTint = this
}
val textColor =
MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(accentColor()))
next.backgroundTintList = ColorStateList.valueOf(accentColor())
next.iconTint = ColorStateList.valueOf(textColor)
next.setTextColor(textColor)
loadProfile()
}
private fun loadProfile() {
bannerImage?.let {
ProfileBannerGlideRequest.Builder.from(
Glide.with(this),
ProfileBannerGlideRequest.getBannerModel()
).build().into(it)
}
UserProfileGlideRequest.Builder.from(
Glide.with(this),
UserProfileGlideRequest.getUserModel()
).build().into(userImage)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -124,141 +99,138 @@ class UserInfoActivity : AbsBaseActivity() {
}
private fun selectBannerImage() {
val pickImageIntent = Intent(Intent.ACTION_PICK, Media.EXTERNAL_CONTENT_URI)
pickImageIntent.type = "image/*"
//pickImageIntent.putExtra("crop", "true")
pickImageIntent.putExtra("outputX", 1290)
pickImageIntent.putExtra("outputY", 720)
pickImageIntent.putExtra("aspectX", 16)
pickImageIntent.putExtra("aspectY", 9)
pickImageIntent.putExtra("scale", true)
//intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(
Intent.createChooser(pickImageIntent, "Select Picture"),
PICK_BANNER_REQUEST
)
ImagePicker.with(this)
.compress(1024)
.crop(16f, 9f)
.start(PICK_BANNER_REQUEST)
}
private fun pickNewPhoto() {
val pickImageIntent = Intent(Intent.ACTION_PICK, Media.EXTERNAL_CONTENT_URI)
pickImageIntent.type = "image/*"
pickImageIntent.putExtra("crop", "true")
pickImageIntent.putExtra("outputX", 512)
pickImageIntent.putExtra("outputY", 512)
pickImageIntent.putExtra("aspectX", 1)
pickImageIntent.putExtra("aspectY", 1)
pickImageIntent.putExtra("scale", true)
startActivityForResult(
Intent.createChooser(pickImageIntent, "Select Picture"),
PICK_IMAGE_REQUEST
)
ImagePicker.with(this)
.galleryOnly()
.cropSquare()
.compress(1024)
.start(PICK_IMAGE_REQUEST)
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && data != null) {
when (requestCode) {
PICK_IMAGE_REQUEST -> {
try {
data.data?.let {
val bitmap = getResizedBitmap(
getBitmap(contentResolver, it),
PROFILE_ICON_SIZE
)
val profileImagePath = saveToInternalStorage(bitmap, USER_PROFILE)
PreferenceUtil.getInstance(this).saveProfileImage(profileImagePath)
loadImageFromStorage(profileImagePath)
}
} catch (e: IOException) {
e.printStackTrace()
}
if (resultCode == Activity.RESULT_OK && requestCode == PICK_IMAGE_REQUEST) {
val fileUri = data?.data
fileUri?.let { setAndSaveUserImage(it) }
} else if (resultCode == Activity.RESULT_OK && requestCode == PICK_BANNER_REQUEST) {
val fileUri = data?.data
fileUri?.let { setAndSaveBannerImage(it) }
} else if (resultCode == ImagePicker.RESULT_ERROR) {
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()
}
}
private fun setAndSaveBannerImage(fileUri: Uri) {
Glide.with(this)
.load(fileUri)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.listener(object : RequestListener<Any, Bitmap> {
override fun onException(
e: java.lang.Exception?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
return false
}
PICK_BANNER_REQUEST -> {
try {
data.data?.let {
val bitmap = getBitmap(contentResolver, it)
val profileImagePath = saveToInternalStorage(bitmap, USER_BANNER)
PreferenceUtil.getInstance(this).setBannerImagePath(profileImagePath)
loadBannerFromStorage(profileImagePath)
}
} catch (e: IOException) {
e.printStackTrace()
}
override fun onResourceReady(
resource: Bitmap?,
model: Any?,
target: Target<Bitmap>?,
isFromMemoryCache: Boolean,
isFirstResource: Boolean
): Boolean {
resource?.let { saveBannerImage(it) }
return false
}
}
}
})
.into(bannerImage)
}
private fun getImagePath(aUri: Uri, aSelection: String?): String? {
var path: String? = null
val cursor = App.getContext().contentResolver.query(aUri, null, aSelection, null, null)
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(Media.DATA))
}
cursor.close()
}
return path
}
private fun loadBannerFromStorage(profileImagePath: String) {
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val bitmap = Compressor(this@UserInfoActivity).setQuality(100)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmap(File(profileImagePath, USER_BANNER))
withContext(Dispatchers.Main) { bannerImage.setImageBitmap(bitmap) }
}
}
}
private fun loadImageFromStorage(path: String) {
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val bitmap = Compressor(this@UserInfoActivity)
.setMaxHeight(300)
.setMaxWidth(300)
.setQuality(75)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmap(File(path, USER_PROFILE))
withContext(Dispatchers.Main) { userImage.setImageBitmap(bitmap) }
}
}
}
private fun saveToInternalStorage(bitmapImage: Bitmap, userBanner: String): String {
val cw = ContextWrapper(this)
val directory = cw.getDir("imageDir", Context.MODE_PRIVATE)
val myPath = File(directory, userBanner)
var fos: FileOutputStream? = null
try {
fos = FileOutputStream(myPath)
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.WEBP, 100, fos)
} catch (e: Exception) {
e.printStackTrace()
} finally {
private fun saveBannerImage(bitmap: Bitmap) {
CoroutineScope(Dispatchers.IO).launch() {
val appDir = applicationContext.filesDir
val file = File(appDir, USER_BANNER)
var successful = false
try {
fos?.close()
val os = BufferedOutputStream(FileOutputStream(file))
successful = ImageUtil.resizeBitmap(bitmap, 2048)
.compress(Bitmap.CompressFormat.WEBP, 100, os)
os.close()
} catch (e: IOException) {
e.printStackTrace()
}
if (successful) {
withContext(Dispatchers.Main) {
Toast.makeText(this@UserInfoActivity, "Done", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun setAndSaveUserImage(fileUri: Uri) {
Glide.with(this)
.load(fileUri)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.listener(object : RequestListener<Any, Bitmap> {
override fun onException(
e: java.lang.Exception?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Bitmap?,
model: Any?,
target: Target<Bitmap>?,
isFromMemoryCache: Boolean,
isFirstResource: Boolean
): Boolean {
resource?.let { saveImage(it) }
return false
}
})
.into(userImage)
}
private fun saveImage(bitmap: Bitmap) {
CoroutineScope(Dispatchers.IO).launch() {
val appDir = applicationContext.filesDir
val file = File(appDir, USER_PROFILE)
var successful = false
try {
val os = BufferedOutputStream(FileOutputStream(file))
successful = ImageUtil.resizeBitmap(bitmap, 2048)
.compress(Bitmap.CompressFormat.WEBP, 100, os)
os.close()
} catch (e: IOException) {
e.printStackTrace()
}
if (successful) {
withContext(Dispatchers.Main) {
Toast.makeText(this@UserInfoActivity, "Done", Toast.LENGTH_SHORT).show()
}
}
}
return directory.absolutePath
}
companion object {
private const val PICK_IMAGE_REQUEST = 9002
private const val PICK_BANNER_REQUEST = 9004
private const val PROFILE_ICON_SIZE = 400
}
}
fun Activity.pickImage(requestCode: Int) {
Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "image/*"
startActivityForResult(this, requestCode)
}
}
}

View File

@ -22,13 +22,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
import code.name.monkey.retromusic.glide.UserProfileGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.SongLoader
@ -38,12 +36,9 @@ import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import kotlinx.android.synthetic.main.abs_playlists.*
import kotlinx.android.synthetic.main.fragment_banner_home.*
import kotlinx.android.synthetic.main.home_content.*
import java.io.File
import java.util.*
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks {
@ -63,31 +58,10 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
}
private fun loadImageFromStorage() {
Glide.with(requireContext())
.load(
File(
PreferenceUtil.getInstance(requireContext()).profileImage,
Constants.USER_PROFILE
)
)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(
TintHelper.createTintedDrawable(
requireContext(),
R.drawable.ic_account_white_24dp,
ThemeStore.accentColor(requireContext())
)
)
.error(
TintHelper.createTintedDrawable(
requireContext(),
R.drawable.ic_account_white_24dp,
ThemeStore.accentColor(requireContext())
)
)
.into(userImage)
UserProfileGlideRequest.Builder.from(
Glide.with(requireActivity()),
UserProfileGlideRequest.getUserModel()
).build().into(userImage)
}
private val displayMetrics: DisplayMetrics
@ -151,58 +125,24 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
homeModel.sections.observe(viewLifecycleOwner, androidx.lifecycle.Observer { sections ->
homeAdapter.swapData(sections)
})
loadProfile()
}
override fun handleBackPress(): Boolean {
return false
}
override fun onResume() {
super.onResume()
getTimeOfTheDay()
}
private fun getTimeOfTheDay() {
val calendar = Calendar.getInstance()
val timeOfDay = calendar.get(Calendar.HOUR_OF_DAY)
var images = arrayOf<String>()
when (timeOfDay) {
in 0..5 -> images = resources.getStringArray(R.array.night)
in 6..11 -> images = resources.getStringArray(R.array.morning)
in 12..15 -> images = resources.getStringArray(R.array.after_noon)
in 16..19 -> images = resources.getStringArray(R.array.evening)
in 20..23 -> images = resources.getStringArray(R.array.night)
}
val day = images[Random().nextInt(images.size)]
loadTimeImage(day)
}
private fun loadTimeImage(day: String) {
private fun loadProfile() {
bannerImage?.let {
val request = Glide.with(requireContext())
if (PreferenceUtil.getInstance(requireContext()).bannerImage.isEmpty()) {
request.load(day)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.drawable.material_design_default)
.error(R.drawable.material_design_default)
.into(it)
} else {
request.load(
File(
PreferenceUtil.getInstance(requireContext()).bannerImage,
USER_BANNER
)
)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.placeholder(R.drawable.material_design_default)
.error(R.drawable.material_design_default)
.into(it)
}
ProfileBannerGlideRequest.Builder.from(
Glide.with(requireContext()),
ProfileBannerGlideRequest.getBannerModel()
).build().into(it)
}
loadImageFromStorage()
UserProfileGlideRequest.Builder.from(
Glide.with(requireActivity()),
UserProfileGlideRequest.getUserModel()
).build().into(userImage)
}
companion object {

View File

@ -0,0 +1,79 @@
package code.name.monkey.retromusic.glide;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.BitmapTypeRequest;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature;
import java.io.File;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.R;
import static code.name.monkey.retromusic.Constants.USER_BANNER;
public class ProfileBannerGlideRequest {
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE;
private static final int DEFAULT_ERROR_IMAGE = R.drawable.material_design_default;
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
public static File getBannerModel() {
File dir = App.Companion.getContext().getFilesDir();
return new File(dir, USER_BANNER);
}
private static BitmapTypeRequest<File> createBaseRequest(RequestManager requestManager, File profile) {
return requestManager.load(profile).asBitmap();
}
private static Key createSignature(File file) {
return new MediaStoreSignature("", file.lastModified(), 0);
}
public static class Builder {
private RequestManager requestManager;
private File profile;
private Builder(RequestManager requestManager, File profile) {
this.requestManager = requestManager;
this.profile = profile;
}
public static Builder from(@NonNull RequestManager requestManager, File profile) {
return new Builder(requestManager, profile);
}
@NonNull
public BitmapRequestBuilder<File, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(requestManager, profile)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.placeholder(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(profile));
}
}
public static class BitmapBuilder {
private final Builder builder;
BitmapBuilder(Builder builder) {
this.builder = builder;
}
public BitmapRequestBuilder<?, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.profile)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.profile));
}
}
}

View File

@ -0,0 +1,79 @@
package code.name.monkey.retromusic.glide;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.BitmapTypeRequest;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature;
import java.io.File;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.R;
import static code.name.monkey.retromusic.Constants.USER_PROFILE;
public class UserProfileGlideRequest {
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE;
private static final int DEFAULT_ERROR_IMAGE = R.drawable.ic_account_white_24dp;
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
public static File getUserModel() {
File dir = App.Companion.getContext().getFilesDir();
return new File(dir, USER_PROFILE);
}
private static BitmapTypeRequest<File> createBaseRequest(RequestManager requestManager, File profile) {
return requestManager.load(profile).asBitmap();
}
private static Key createSignature(File file) {
return new MediaStoreSignature("", file.lastModified(), 0);
}
public static class Builder {
private RequestManager requestManager;
private File profile;
private Builder(RequestManager requestManager, File profile) {
this.requestManager = requestManager;
this.profile = profile;
}
public static Builder from(@NonNull RequestManager requestManager, File profile) {
return new Builder(requestManager, profile);
}
@NonNull
public BitmapRequestBuilder<File, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(requestManager, profile)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.placeholder(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(profile));
}
}
public static class BitmapBuilder {
private final Builder builder;
BitmapBuilder(Builder builder) {
this.builder = builder;
}
public BitmapRequestBuilder<?, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.profile)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.profile));
}
}
}

View File

@ -67,11 +67,8 @@ import static code.name.monkey.retromusic.helper.SortOrder.SongSortOrder;
public final class PreferenceUtil {
public static final String LIBRARY_CATEGORIES = "library_categories";
public static final String EXTRA_SONG_INFO = "extra_song_info";
public static final String DESATURATED_COLOR = "desaturated_color";
public static final String BLACK_THEME = "black_theme";
public static final String KEEP_SCREEN_ON = "keep_screen_on";
public static final String TOGGLE_HOME_BANNER = "toggle_home_banner";
@ -549,9 +546,6 @@ public final class PreferenceUtil {
editor.apply();
}
public String getProfileImage() {
return mPreferences.getString(PROFILE_IMAGE_PATH, "");
}
public final String getSAFSDCardUri() {
return mPreferences.getString(SAF_SDCARD_URI, "");
@ -700,11 +694,6 @@ public final class PreferenceUtil {
}
public void saveProfileImage(String profileImagePath) {
mPreferences.edit().putString(PROFILE_IMAGE_PATH, profileImagePath).apply();
}
public void setAlbumGridSize(final int gridSize) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putInt(ALBUM_GRID_SIZE, gridSize);

View File

@ -23,122 +23,114 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
<com.google.android.material.card.MaterialCardView
android:id="@+id/imageContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/imageContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:cardCornerRadius="12dp"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/bannerImage"
android:layout_width="match_parent"
android:layout_height="156dp"
android:scaleType="centerCrop"
app:srcCompat="@drawable/material_design_default" />
<View
android:id="@+id/bannerSelect"
android:layout_width="match_parent"
android:layout_height="156dp"
android:background="@color/twenty_percent_black_overlay" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="?roundSelector"
android:padding="16dp"
app:srcCompat="@drawable/ic_add_photo_white_24dp" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
android:layout_margin="16dp"
app:cardCornerRadius="12dp"
app:cardElevation="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/userImageContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginStart="16dp"
android:elevation="8dp"
android:transitionName="@string/transition_user_image"
app:layout_constraintBottom_toBottomOf="@id/imageContainer"
app:layout_constraintStart_toStartOf="@+id/imageContainer"
app:layout_constraintTop_toBottomOf="@id/imageContainer">
android:layout_width="match_parent"
android:layout_height="match_parent">
<code.name.monkey.retromusic.views.RetroShapeableImageView
android:id="@+id/userImage"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_gravity="center"
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/bannerImage"
android:layout_width="match_parent"
android:layout_height="156dp"
android:scaleType="centerCrop"
app:retroCornerSize="36dp"
app:srcCompat="@drawable/ic_person_flat"
app:strokeColor="?attr/colorSurface"
app:strokeWidth="2dp" />
app:srcCompat="@drawable/material_design_default" />
<View
android:id="@+id/bannerSelect"
android:layout_width="match_parent"
android:layout_height="156dp"
android:background="@color/twenty_percent_black_overlay" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:gravity="center"
android:padding="12dp"
android:src="@drawable/ic_add_photo_white_24dp"
app:tint="?attr/colorControlNormal" />
</FrameLayout>
android:layout_gravity="end"
android:background="?roundSelector"
android:padding="16dp"
app:srcCompat="@drawable/ic_add_photo_white_24dp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/nameContainer"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
<FrameLayout
android:id="@+id/userImageContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginStart="16dp"
android:elevation="8dp"
android:transitionName="@string/transition_user_image"
app:layout_constraintBottom_toBottomOf="@id/imageContainer"
app:layout_constraintEnd_toEndOf="@id/imageContainer"
app:layout_constraintStart_toStartOf="@+id/imageContainer"
app:layout_constraintTop_toBottomOf="@id/imageContainer">
<code.name.monkey.retromusic.views.RetroShapeableImageView
android:id="@+id/userImage"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_gravity="center"
android:scaleType="centerCrop"
app:retroCornerSize="36dp"
app:srcCompat="@drawable/ic_person_flat"
app:strokeColor="?attr/colorSurface"
app:strokeWidth="2dp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:gravity="center"
android:padding="12dp"
android:src="@drawable/ic_add_photo_white_24dp"
app:tint="?attr/colorControlNormal" />
</FrameLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/nameContainer"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:hintAnimationEnabled="true"
app:hintEnabled="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImageContainer">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:hintAnimationEnabled="true"
app:hintEnabled="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/userImageContainer">
android:autofillHints="name"
android:hint="@string/my_name"
android:importantForAutofill="yes"
android:inputType="textPersonName|textCapWords|text"
android:textAppearance="@style/TextViewSubtitle1"
tools:text="@tools:sample/full_names" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="name"
android:hint="@string/my_name"
android:importantForAutofill="yes"
android:inputType="textPersonName|textCapWords|text"
android:textAppearance="@style/TextViewSubtitle1"
tools:text="@tools:sample/full_names" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/next"