ImageView does not replace previously used Drawable in RecyclerView Adapter - android

I am using ImageView inside my custom Adapter class. The problem is my Adapter has 2 image views inside and I am using a "placeholder image" as a default image on them but when I try to populate my RecyclerView and setImageResource() using Adapter's ViewHolder it simply goes behind the default "placeholder image" instead of overwriting it. I am quite new to both Java and Android App Development so I don't know if the setImageResource() works different with Adapters.
Here's my code:
public void onBindViewHolder(#NonNull ProductAdapter.ViewHolder holder, int position) {
holder.itemView.setTag(product.get(position));
holder.tvTitle.setText(product.get(position).getTitle());
holder.tvDescription.setText(product.get(position).getDescription());
//PROBLEM STARTS HERE
//Set Status (getSale() returns bool)
switch (product.get(position).getSale()?"sold":"available"){
case "sold":
holder.ivStatus.setImageResource(R.drawable.sold);
break;
case "available":
holder.ivStatus.setImageResource(R.drawable.available);
break;
}
//Set Product Image
switch (product.get(position).getType()){
case "Laptop":
holder.ivProduct.setImageResource(R.drawable.laptop);
break;
case "LCD":
holder.ivProduct.setImageResource(R.drawable.screen);
break;
case "USB":
holder.ivProduct.setImageResource(R.drawable.memory);
break;
case "Hard Disk":
holder.ivProduct.setImageResource(R.drawable.hdd);
break;
}
}
In Both cases the switch-case works correctly and picks the right image resource but it simply places the image Resource behind placeholder image. how do I just overwrite the default image?

The reason you see both images because you set both background and foreground images on the ImageView
To solve this remove android:foreground from both ImageViews and leave the placeholder in app:srcCompat
So your ImageView should look like:
<ImageView
android:id="#+id/ivStatus"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
app:srcCompat="#drawable/placeholder" />

Related

How to re-size an image not proportionaly?

I'm trying to make a game like a "click & kill" and I'm trying to make a health bar for the character to kill.
I'm using a simple image (a red rectangle) and I would like to reduce the health bar after one click. What I tryed works but the problem is not just the with decrease, the height too. So the result is really horrible. To begin, this is my XML (I only show one for example):
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="33">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFF00"
android:id="#+id/hole4"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/healthBar4"
android:src="#drawable/health_bar"/>
</RelativeLayout>
So here nothing bad (I think) I leave android:adjustViewBounds="true" because I thought the problem came from here.
Next is my Activity :
final int healthBarHeightInitial = healthBar4.getLayoutParams().height;
final int healthBarWidthInitial = healthBar4.getLayoutParams().width;
healthBar4.requestLayout();
//ivHole4 is my ImageView I get the click to leave some life to the character
ivHole4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//If character die (works great).
if(choixAction.ChoixAction(CharaHole4,outil)){
Log.d("Perso","Character is die");
mAvancement +=1;
ivHole4.setImageResource(0);
CharaHole4 = null;
placeChara.setHole4(true);
healthBar4.setVisibility(View.GONE);
healthBar4.getLayoutParams().height = healthBarHeightInitial;
healthBar4.getLayoutParams().width = healthWidthInitial;
}
//if character don't die (here is the problem !)
else {
healthBar4.getLayoutParams().width = healthBar4.getWidth()/2; //This is works great
healthBar4.getLayoutParams().height = healthBarHeightInitial; //This is do nothing, the height is /2 too.
healthBar4.requestLayout();
}
}
});
I hope someone know how to change the image size not proportionally.
Thank's advance.
Your ImageView in the XML Layout needs to set the scale type to fitXY to allow it to expand without keeping proportions.
android:scaleType="fitXY"
Use Picasso Library and set Crop Center.

Fresco : Display Wrong Image in listitems

I am using fersco library for loading local image. Initially i am displaying placeholder image in each item.Once the image is downloaded then i am storing that image in to local path and then load image via setImageUri function. If i am scrolling fast at the time of downloading image it display different image and re-appearing some time keep on changing if i am stop scrolling.
My SimpleDraweeView :
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/fake_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center|center_horizontal|center_vertical"
android:adjustViewBounds="true"
android:contentDescription="#string/app_name"
android:scaleType="centerInside" />
My Adapter Code is :
GenericDraweeHierarchy hierarchy = setHierarchyForDraweeView(mImageView, 300);
hierarchy.setFailureImage(mContext.getResources().getDrawable(R.drawable.broken_image_black));
mSimpleDraweeView.setImageURI(Uri.fromFile(new File(mPath/local path/)));
SetHierarchyForDraweeView Function :
private GenericDraweeHierarchy setHierarchyForDraweeView(SimpleDraweeView draweeView, int duration) {
if (draweeView != null) {
if (draweeView.getHierarchy() == null) {
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(mContext.getResources());
GenericDraweeHierarchy hierarchy = builder
.setFadeDuration(duration)
.setPlaceholderImage(new AsyncColorDrawable(mContext.getResources()))
.setFailureImage(mContext.getResources().getDrawable(R.drawable.broken_image_black))
.build();
draweeView.setHierarchy(hierarchy);
} else {
GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
hierarchy.setFadeDuration(duration);
return hierarchy;
}
}
return null;
}
AsyncColorDrawable Class :
private class AsyncColorDrawable extends ColorDrawable {
public AsyncColorDrawable(Resources res) {
super(res.getColor(R.color.RED));
}
}
I am doing anything wrong ?
I see several things that should be fixed, but none of which would explain incorrect loading. I will be able to help, but I'll need the logcat logs as explained here. Also, there is one thing I don't fully understand. From your description it seems that you are downloading your images manually, saving them to disk and when they are downloaded you set the Uri. Why not using Fresco to automatically download and disk-cache images for you? Can you provide this piece of code as well, because the issue might very well be there.
Things that should be fixed:
adjustViewBounds and scaleType attributtes are not supported by SimpleDraweeView. Drawee operates on several images at once (placeholder, failure image, actual image, etc.) Each can have its own scale type so you need to use Drawee atrributes as explained here.
If you are inflating your view from XML, draweeView.getHierarchy should never be null. You would have a NullPointerException anyway because you are not returning hierarchy from that if-branch. So, you can specify your failure image via XML too, no need to do that programmatically. Same for the fade duration if you always use the same value.

RecyclerView laggy scrolling

I am loading 400x200 images in RecyclerView, but scrolling is laggy on 2k devices. I am using Picasso for loading images from resource.
As you can see in the demo images are blurry on 2k screen, but if I load higher resolution images the situation gets worse.
How to fix this, I am not even loading large image, its 400x200 ?
Demo
Here is my code
card_view.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
card_view:cardPreventCornerOverlap="false"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
card_view:cardCornerRadius="2dp">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/rel">
<ImageView
android:id="#+id/cardimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#drawable/p7"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="title"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="24dp"
android:textStyle="bold"
android:textSize="24sp"
android:id="#+id/cardtitle"
android:layout_gravity="center_vertical"/>
</LinearLayout>
</android.support.v7.widget.CardView>
Myadapter Code
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
private Context mContext;
List<Flower> list = new ArrayList<>();
public CardAdapter(Context mContext, List<Flower> list) {
this.mContext = mContext;
this.list = list;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.Flower=getItem(position);
holder.cardtitle.setText(list.get(position).name);
Picasso.with(mContext)
.load(list.get(position).id)
.placeholder(R.drawable.ic_launcher)
.into(holder.cardimage);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemCount() {
return list.size();
}
public Flower getItem(int i) {
return list.get(i);
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView cardimage;
TextView cardtitle;
Flower Flower;
public ViewHolder(View itemView) {
super(itemView);
cardimage = (ImageView) itemView.findViewById(R.id.cardimage);
cardtitle = (TextView) itemView.findViewById(R.id.cardtitle);
}
}
}
UPDATE: I am loading images from resource, I am not downloading nothing
Here is my array
private void initializeData() {
flowers = new ArrayList<>();
flowers.add(new Flower("Flower 1", R.drawable.p8));
flowers.add(new Flower("Flower 2", R.drawable.p10));
flowers.add(new Flower("Flower 3", R.drawable.p11));
flowers.add(new Flower("Flower 4", R.drawable.p8));
flowers.add(new Flower("Flower 5", R.drawable.photo2));
flowers.add(new Flower("Flower 6", R.drawable.photo6));
flowers.add(new Flower("Flower 7", R.drawable.p12));
flowers.add(new Flower("Flower 8", R.drawable.p9));
flowers.add(new Flower("Flower 9", R.drawable.p8));
flowers.add(new Flower("Flower 10", R.drawable.p8));
flowers.add(new Flower("Flower 11", R.drawable.p8));
flowers.add(new Flower("Flower 12", R.drawable.p10));
}
UPDATE 2 : Guys I fixed most of the lag by setting adapter.setHasStableIds(true) , but app is still laggy on the first scroll while images are not loaded yet, how to fix that ?
UPDATE 3: I just tried loading images from web and everything seems smooth, probably there is some problem with loading images from resource .
Ok, thank you guys, I am gonna load my images from web.
if you are using two or more recycler views like (RecyclerView and NestedView)
try this
recyclerView.setNestedScrollingEnabled(false);
Source : Recyclerview inside Nested Scrollview scroll but does not fast scroll like normal Recyclerview or Nested Scrollview
Is RecyclerView.setHasFixedSize() set to true? I'm not able to reproduce this lag...can you please post the whole project on git? Check this out, maybe it can help you: http://antonioleiva.com/recyclerview/
I Believe that sometimes you may piss off when only trying some static images in drawable to display your recycler view. And it happens extremely lagging.
Why? You may not get this issue when using some library to load an image from url (Picasso, Glide, ...), but what happens with the same image, the same size, and it's right in your drawable (not need to download at all). And after a while, I figure out, android did some trick to resize an image in drawable for us to get a proper image in different resolution devices. So my suggestion is to use drawable-nodpi to store your image in order for android not to interfere with our images.
This is because the image is taking time to load.
Firstly, change your code for loading image as the below one...
Picasso.get().load(list.get(position).id).fit().centerCrop()
.placeholder(R.drawable.ic_launcher)
.into(holder.cardimage);
Then, before setting the adapter on recyclerview to the instance of CardAdapter inside MainActivity add this line..
yourAdapter_name.setHasStableIds(true);
One more tip...If anyone is using large drawables (xxxhdpi, xxhdpi ), first convert them into mdpi or ldpi . This will also improve the performance a lot and also reduces the apk size.You can use this website NativeScript Image Builder
This could be because of Picasso taking time to load the image. Use the below snapshot and adjust accordingly.
Picasso.with (context)
.load (url).fit().centerCrop()
.error (R.drawable.UserImage)
.into (imageView);
Use fit() and centerCrop() to avoid legginess.
You need to be getting the images asynchronously. As it is now, it stalls to actually download the image.
Leave the imageview blank when it's created, but have some sort of listener to set the image when it's been downloaded.
if you use Recyclerview in vertical mode and your activity contains other item that you have ScrollView then you must use NestedScrollView instead of ScrollView.
as described in google documentation NestedScrollView is just like ScrollView, but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.
I had laggy recyclerView issue when one of the textView within the recyclerView was receiving null values. I fix this and my recyclerView stopped lagging.
It might be late, but maybe somebody will find it useful. Had the same problem, problem was at line:
Picasso.get().load(image).into(holder.imageView);
so I added fit().centerCrop() like this:
Picasso.get().load(image).fit().centerCrop().into(holder.imageView);
That solved my problem
I am bit late but this can be fixed bu using thumbnail with Glide.
Glide.with(context)
.load(URL)
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.thumbnail(0.5f)
.centerCrop()
.into(imageView);
In my case, bitmap creation was making delay for scroll. So I put bitmap creation in background thread and set to image in UI thread. This way, UI is not blocked for bitmap creation
new Thread(new Runnable() {
#Override
public void run() {
Bitmap myBitmap = BitmapFactory.decodeFile(filepath);
activity.runOnUiThread(new Runnable() {
public void run() {
vItem.imgProfile.setImageBitmap(myBitmap);
}
});
}
}).start();
from my experience with recyclerview what i found the possible cause could be is the image size.
beside that adding property ( setNestedScrollingEnabled(false); ) to the recyclerview and ( setHasStableIds) to the adapter does help to make recyclerview work smoothly.
So, bottom line is, if your recyclerview has image to load from network make sure to override their size or use thumbnail property(in glide).
this tricked saved my life and i hope it might save others life as well.
Happy coding :)
A bit late but I found leveraging Kotlin Coroutines as an effective way to make your onBindViewHolder() calls cheap, by offloading your image loading on to a background thread. I use Glide to load 384x384 images and the scrolling is smooth for upto a couple of thousand images.
// Here, defaultScope = CoroutineScope(Dispatchers.Default + SupervisiorJob())
// Key idea is to launch the Glide call on a background thread.
defaultScope.launch(exceptionHandler) {
Glide.with(view)
.load(uri)
.also {
// When Glide is done preparing the resource,
// use Main thread to load into ImageView.
withContext(Dispatchers.Main) {
it.into(view)
}
}
}
For Picasso, it will be a similar thing (though I haven't tried it personally), where into() must be invoked from the Main thread and the preparation on the background thread.
I think the reason is that Picasso caches your images but since you have a list of drawables that you bundle together with your app, you do not in theory need to cache your images. Caching is only useful when you are downloading the image from the internet and you don't want the app to redownload the images each time you swipe up or down on the recyclerview.
I would adjust the way picasso works by changing the memorypolicy so try this instead :
Picasso.with(getContext()).load(data.get(pos).getFeed_thumb_image()).memoryPolicy(MemoryPolicy.NO_CACHE).into(image);

ImageButton stretch src to fill

This question comes up quite often, however in all examples i have found, the image src is defined in the XML. e.g android:src="..."
My code doesn't specificy the src untill the activity, using ImageButton.setImageResource() as it is a single button, performing play/stop
How do i fill the ImageButton with the src, when src is defined later?
I tryed ImageButton.setScaleType="fitXY", however sdk doesn't like it using string...
UPDATE: After trying to use the suggested below, the problem still occurs. here is more explanation to help
<ImageButton
android:id="#+id/imgStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
public class MainActivity extends Activity{
private ImageButton player;
protected void onCreate(){
player = (ImageButton) findViewById(R.id.imgStart);
...
if(isPlaying){
player.setImageResource(bitmap image);
}
else{
player.setImageResource(different bitmap image);
}
...
}
Use ScaleType.CENTER_CROP instead
player .setScaleType(ImageView.ScaleType.CENTER_CROP);
It seems CENTER_CROP works as fit_xy.
but, it's not sure why it does..
Please try below code to set ScaleType programatically
ImageButton object".setScaleType(ScaleType.FIT_XY)
"ImageButton object" should be object of class ImageButton
(that you defined probably in xml).
Do it this way
ImageButton object.setScaleType(ScaleType.FIT_XY)
Use ScaleType.FIT_XY instead of fitXY in your code
ImageButton.setScaleType="fitXY"
yes this will not work, because you have to use it properly using below code also should setAdjustViewBounds to true.like this:
player.setAdjustViewBounds(true);
player.setScaleType(ScaleType.FIT_XY);
This will definitely work!

Find and return the ID of the current view

I'm trying to set up a "close to start" button in a game. The game takes the user from view to view like a maze. The user could be on any view, but I want a way to get them back to the start screen. Is there a way to find and return the ID of the current view for my findViewByID? I've found a I've tried the following code in various forms:
OnClickListener closetomain = new OnClickListener() {
#Override
public void onClick(View v) {
int currentid = v.findFocus().getId();
RelativeLayout hideme = (RelativeLayout)findViewById(currentid);
hideme.setVisibility(View.GONE);
setContentView(R.layout.main);
// RelativeLayout showme = (RelativeLayout)findViewById(R.id.startLayout);
// showme.setVisibility(View.VISIBLE);
}
};
Okay, it turns out I should have given each close button the same ID and used theisenp's suggestion for the simplest code (well, that I could understand). It also turns out that I should have started by putting each level/layout in its own activity. You live and you learn I guess. Below is my XML and java. It may not be the elegant solution but I'm not sure I care all that much as long as it works.
<ImageButton android:id="#+id/closeButton"
android:layout_height="wrap_content"
android:background="#drawable/close"
android:layout_width="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
android:onClick="closetomain">
</ImageButton>
And here's my Java:
public void closetomain(View view) {
switch(view.getId()) {
case R.id.closeButton:
setContentView(R.layout.main);
break;
}
}
Why do you need to retrieve the id of the current view? Is it just so that you can set it's visibility to GONE? If so, there are probably better ways of implementing that same functionality.
Instead of just changing the layout with setContentView(), it would probably be a better idea to have the Start Screen be its own separate activity. When you are in any of the "maze views" you could simply use an intent to start your home screen activity like this
Intent startScreenIntent = new Intent(this, StartScreen.Class);
startActivity(startScreenIntent);
Then you won't have to worry about finding id's or changing visibilities, plus the code is cleaner, because it separates the code for your Maze levels and your Start Menu.

Categories

Resources