BottomNavigationView Custom Item Image - android

I wanna to set a custom image to "Profile" item in the BottomNavigationView as the user is logged in. I have user's image URL.
This is the suggested design

I used this code for make it works. (Kotlin)
navigation is the BottomNavigationView
val menu = navigation.menu
val menuItem = menu.findItem(R.id.my_account)
Glide.with(this)
.asBitmap()
.load("https://my_account_image_url")
.apply(RequestOptions
.circleCropTransform()
.placeholder(R.drawable.ic_avatar))
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
menuItem?.icon = BitmapDrawable(resources, resource)
}
})

You can do something like this:
BottomNavigationView navigation;
And then in your onCreate:
navigation = findViewById(R.id.navigation);
Menu a = navigation.getMenu();
MenuItem b = a.findItem(R.id.profile_menu);
if(userloggedIn){
b.setIcon(R.drawable.icons_logged_in);
}
else{
b.setIcon(R.drawable.icon_logged_out);
}
If you want to load from URL you can use either Glide or Picasso.

From AppCompat 1.1.0 you will also need to remove tint for this.
val menu = navigation.menu
val menuItem = menu.findItem(R.id.profile_menu_item)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menuItem?.iconTintList = null
menuItem?.iconTintMode = null
}
Glide.with(this)
.asBitmap()
.load("url")
.apply(RequestOptions
.circleCropTransform()
.placeholder(R.drawable.placeholder))
.into(object : CustomTarget<Bitmap>(24.toPixel(), 24.toPixel()) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
menuItem?.icon = BitmapDrawable(resources, resource)
}
override fun onLoadCleared(placeholder: Drawable?) {}
})

Right now, There is no proper solution can be found for this but you can do something like this. works for me.
..........
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:elevation="0dp"
app:itemBackground="#color/bottomMenuColor"
app:itemHorizontalTranslationEnabled="false"
app:itemTextAppearanceActive="#style/BottomNavigationView"
app:itemTextAppearanceInactive="#style/BottomNavigationView"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/main_menu" />
<ImageView
android:id="#+id/imgView"
android:layout_width="#dimen/scale_30dp"
android:layout_height="#dimen/scale_30dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="#dimen/scale_40dp"
android:src="#drawable/temp_person" />
</RelativeLayout>
.......

You can use Glide to set the profile image in your bottom navigation view. Before setting the profile image, you need to load the image as bitmap. Then, convert the Bitmap to a Drawable type in order to set up the item icon.
Here is how it's done.
Firstly call in the app level build.gradle
implementation 'com.github.bumptech.glide:glide:4.9.0'
then click Sync now.
After that, in the activity where your BottomNavigationView is located, you can do something like this.
Glide.with(getApplicationContext()).asBitmap().load(*yourImageUrl*)
.into(new CustomTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
Drawable profileImage = new BitmapDrawable(getResources(), resource);
bottomNavigationView.getMenu().getItem(*yourItemIndex*).setIcon(profileImage);
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
}
}
if you want to make the profile image in circular shape, you can either call .circleCrop() or .optionalCircleCrop(). However, I think using .optionalCircleCrop is better.

you can get ImageView from NavigationItemView , and load image by glide or another image loader libraries in imageview!
please see my answer :
https://stackoverflow.com/a/69175500/8780115

Related

How to ensure that glide uses the palette to obtain color and fill it for a period of time before loading a successful picture

I want to use palette to get a color and fill it before glide successfully loads the picture.
Just like bing.com or twitter.com, a color will cover the image before it is successfully loaded.
I use the following methods to achieve it:
Glide
.with(imageView.context)
.asBitmap()
.load(imageUrl)
.listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(e: GlideException?, model: Any, target: Target<Bitmap>, isFirstResource: Boolean) = false
override fun onResourceReady(resource: Bitmap, model: Any, target: Target<Bitmap>, dataSource: DataSource, isFirstResource: Boolean): Boolean {
Palette
.from(resource)
.generate(PaletteAsyncListener { palette ->
val darkVibrantSwatch = palette!!.darkVibrantSwatch
val dominantSwatch = palette.dominantSwatch
val lightVibrantSwatch = palette.lightVibrantSwatch
if (darkVibrantSwatch != null) {
imageView.setBackgroundColor(darkVibrantSwatch.rgb)
} else if (dominantSwatch != null) {
imageView.setBackgroundColor(dominantSwatch.rgb)
} else {
imageView.setBackgroundColor(lightVibrantSwatch!!.rgb)
}
})
return false
}
})
.into(imageView)
However, through the above code, I will load the image directly (imagview will display white before the image is loaded successfully), without filling it with solid color first.
I think maybe glide is loading too fast?
Is there any way to ensure that my picture is filled with solid color for a period of time, such as 500ms?
use Palette.from(resource!!.toBitmap) this will force and rap the resources to bitmap. but firstly you will need to use let on the resources variable so that resources doe's not give you issues

AppWidgetTarget doesn't work inside RemoteViewsFactory. How to get around this?

There is not enough documentation or blogs around this topic.
Can someone point me in the right direction? Tried this in getView. Works on an imageview that is not part of item of listview.
val articleImage: AppWidgetTarget = object : AppWidgetTarget(appContext, R.id.article_image, views, appWidgetId) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
super.onResourceReady(resource, transition)
}
}
val options = RequestOptions()
.override(62, 62)
.placeholder(R.drawable.news_thumbnail)
.error(R.drawable.news_thumbnail)
Glide
.with(appContext)
.asBitmap()
.load("/*URL*/")
.apply(options)
.into(articleImage)
AppWidgetTarget appears to be for an ImageView directly in the app widget's layout, as it uses updateAppWidget() to push over the change. It does not appear to tie into a RemoteViewsFactory, which is how you populate an AdapterView inside of an app widget.

How to properly fit image with background drawable in glide

I have to successfully load an image to this imageview and I am using glide. My biggest challenged however is I want this rectangle drawable to be in the image and the image to fit in the white rectangle drawable.
Here is my glide function
private fun loadUrl(url: String) {
Glide.with(this)
.asBitmap()
.load(url)
.fitCenter()
.centerInside()
.into(object : CustomTarget<Bitmap?>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap?>?
) {
binding.imageview.setImageBitmap(resource)
binding.imageview.setBackgroundResource(R.drawable.white_rectangle)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
My image view
<ImageView
android:id="#+id/imageview"
android:layout_width="48dp"
android:layout_height="48dp"
I want to achieve something like this.
I saw this one how can I advance this?
How to make border for circle cropped image in glide

SharedElementTransition not animating image scale properly with Glide

I am doing a shared element transition from a fragment with a RecyclerView to a detail view, where an image is shared between the two. The transition is mostly fine, but because the two images are different sizes, when I click on one, it scales the image to the final size, and then animates the ImageView bounds as it should. This results in the image not matching the size of the bounds during the animation.
Here is a video of what I'm describing
DetailFragment:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
ViewCompat.setTransitionName(binding.podcastImage, "podcastImage_${args.podcastId}")
postponeEnterTransition()
}
// called from onStart
private fun observeViewModel() {
viewModel.podcastObservable.observe(this, Observer { podcast ->
Glide.with(requireContext())
.load(podcast.image)
.into(binding.podcastImage)
// other stuff
startPostponedEnterTransition()
})
}
GridFragment:
fun navigateToPodcastDetailFragment(podcastId: String) {
val args = Bundle()
args.putString("podcast_id", podcastId)
val directions = TopPodcastsFragmentDirections.viewPodcastDetails(podcastId)
val extras = FragmentNavigatorExtras(
podcast_image to "podcastImage_$podcastId"
)
Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
.navigate(directions, extras)
}
GridAdapter:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
getItem(position).let { podcast ->
with(holder) {
Glide.with(holder.itemView.context)
.load(podcastList[position].image)
.dontAnimate()
.dontTransform()
.into(binding.thumbnail)
bind(createOnClickListener(binding, podcast.id), podcast)
}
}
}
ViewHolder.bind() {
// other stuff
ViewCompat.setTransitionName(binding.thumbnail, "podcast${value.id}")
}
Grid item ImageView:
<ImageView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:transitionName="#string/podcastImageTransition"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="#drawable/ic_launcher_background" />
DetailFragment ImageView:
<ImageView
android:id="#+id/podcast_image"
android:layout_width="164dp"
android:layout_height="164dp"
android:scaleType="centerCrop"
android:layout_marginTop="24dp"
android:transitionName="#string/podcastImageTransition"
app:layout_constraintTop_toBottomOf="#id/toolbar"
app:layout_constraintStart_toStartOf="parent"
tools:src="#drawable/ic_launcher_background"/>
I think I have the transition part mostly correct, but something about the way the image is being cropped or scaled isn't right during the transition.
Thanks in advance.
Make sure in DetailFragment to include .dontTransform() within Glide
// called from onStart
private fun observeViewModel() {
viewModel.podcastObservable.observe(this, Observer { podcast ->
Glide.with(requireContext())
.load(podcast.image)
.dontTransform()
.into(binding.podcastImage)
// other stuff
startPostponedEnterTransition()
})
}
Also, I've been working on this all day (for an app I'm making coincidentally), and I just found something else you can try. Try removing the image scale type in the xml files.

Glide - Load a GIF as a placeholder

I'm using Glide in my Android project, and I have a RecyclerView with a list of CardViews in it. What I wanna do is to load an image for each CardView while showing a GIF loading image until the real image gets loaded. Now if it try to load the GIF as the main image, no problem:
Glide.with(context)
.load(R.raw.gif_loading_bar)
.into(imageView);
The code above works fine and the GIF gets loaded. But when I try to load another image and make the GIF a placeholder Android Studio shows an error "Expected resource of type drawable":
Glide.with(mContext)
.setDefaultRequestOptions(new RequestOptions()
.placeholder(R.raw.gif_loading_bar))
.load(imageUrl)
.into(imageView);
What should I do to fix this?
Glide does support GIF as placeholder. I recently faced this situation and solved it like below. Hope it helps someone like me who is facing this situtaion.
var builder = Glide.with(mContext).load(path).apply(options).thumbnail(Glide.with(mContext).load(R.raw.loader2))
if (listener == null) {
builder = builder.addListener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
//TODO; your code here
return false
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
//TODO; your code here
return false
}
})
} else {
builder = builder.addListener(listener)
}
builder.into(myImageView)
What it does
It load your gif as thumbnail until the image is downloaded from the source.
Inside the onResourceReady method it will give you the callback when the resource is ready. Make sure to put gif file under R.raw package and not in drawable package. Let me know if you face any issue.
Unfortunately, Glide does not support GIF placeholders, as mentioned in this Github issue, and this one.
This should do the job:
ImageView imageView = (ImageView) findViewById(R.id.imageView);
GlideDrawableImageViewTarget imageViewTarget = new
GlideDrawableImageViewTarget(imageView);
Glide.with(context)
.asGif()
.setDefaultRequestOptions(new RequestOptions()
.placeholder(R.raw.gif_loading_bar))
.load(imageUrl)
.into(imageView);
More info here and here
Just make sure to change the getContext() as per your codes. For example in my case I am passing it as holder.img.getContext()
Glide.with(getContext()).load(item[position])
.thumbnail(Glide.with(getContext()).load(R.drawable.gif_image))
.fitCenter()
.crossFade()
.into(imageView);

Categories

Resources