I wrote an universal custom ImageView , there are parts of code:
public class AvatarImageView extends ImageView {
#Override
protected void onDraw(Canvas canvas) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
// I want to make this bitmap compress
}
and then I can use this custom ImageView like this:
<CustomerView.AvatarImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#drawable/avatar"
/>
It will lead to an oom error when I set more than 2 AvatarImageViews in my listview .
I see a lot of developers make it in that way: Google Training Loading Large Bitmaps Efficiently
BitmapFactory.decodeResource(res, resId, options);
It needs to offer a resId . But I want to reuse this custom ImageView ,so I couldn't offer a certain id .
Is there any good solutions ? Any help would be greatly appreciated.Thank you!
Related
I would appreciate if you could help me with this, I'm trying to show pictures from my drawable folder, and the names of those images are in a sqlite database.
The problem is that I can't apply the image on the imageview. Any idea about why this happened. Thanks
This is my code
setviewholder.java
public class SetViewHolder extends RecyclerView.ViewHolder {
public ImageView txt_imagen;
public TextView txt_path_imagen;
public SetViewHolder (View itemView){
super(itemView);
txt_imagen = (ImageView) itemView.findViewById(R.id.txt_imagen);
txt_path_imagen = (TextView) itemView.findById(R.id.txt_path_imagen);
}
custom_list_item2.xml
<ImageView
android:id="#+id/txt_imagen"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
MyAdapter.java
public void onBindViewHolder(SetViewHolder holder, final int position){
holder.txt_path_imagen.setText(items.get(position).getPath_imagen());
Bitmap bmp = BitmapFactory.decodeFile("ar.com.allnight.allnight:drawable/"+items.get(position).getPath_imagen());
holder.txt_imagen.setImageBitmap(bmp);
the log:
Unable to decode the stream: java.ioFileNotFoundException: /ar.comm.allnight:drawable/imgage1
I have tried many different ways, but I canĀ“t make it work and the others vars shows ok!, So now it is everything else work ok.
Any idea about what I'm doing wrong?
I am absolulty new in Android and I am doing some experiment with the Canvas object.
I am trying to add it to a Canvas and then show it into a retrieved ImageView (I know that this is not the standard and simplest way to show an image into an ImageView but this is only a simplified experiment for a further more complex thing that I have to do using Canvas).
So I have a star.png (a 32x32 px icon into my /res/drawable/ folder) and I am trying to
This is my activity_main.xml layout configuration file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ImageView
android:id="#+id/star_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
This layout contain the ImageView having id=star_container that is where I have to draw the image using the Canvas
And this is the MainActivity class that handle this view:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView imgView = (ImageView) findViewById(R.id.star_container);
Canvas canvas;
Bitmap star = BitmapFactory.decodeResource(getResources(), R.drawable.star);
Bitmap output = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);
canvas = new Canvas(output);
canvas.drawBitmap(star, star.getWidth() + 2, 0, null);
imgView.setImageDrawable(new BitmapDrawable(getResources(), output));
}
}
So into the onCreate() method I retrieve the ImageView where the image have to be placed. Then I create a Bitmap object retrieving the star.png image from the resoruces that will be added to the otuput Bitmap using the Canvas.
Finally I set this output Bitmap into the retrieve ImageView.
So I expected that, when the app is running, the previous ImageView contains the star.png image but it does not appear.
I have no error when I execute this app but the only output that I obtain is the textual message defined into the TextView.
Why? What is wrong? What am I missing? How can I modify this code and let it work?
According to the documents:
left: The position of the left side of the bitmap being drawn
The problem is here :
canvas.drawBitmap(star, star.getWidth() + 2, 0, null);
You're using a value for left that is out of bitmap bounds, So nothing is drawn, try this: canvas.drawBitmap(star, 0, 0, null);
Android API provides another method to set Bitmap as drawable directly :
ImageView#setImageBitmap(Bitmap bm)
I think it's a better practice to implement a custom View and explore Canvas capabilities there (in onDraw method)
another way - using rect area:
Canvas canvas;
Bitmap star = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Bitmap output = Bitmap.createBitmap(star.getWidth(), star.getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(output);
Rect source = new Rect(0, 0, star.getWidth(), star.getHeight());
canvas.drawBitmap(star, null, source, null);
imgView.setImageBitmap(output);
I'm writing an application that works alot with google map and markers on it. My task is to create and display some amount of markers on google map. Markers have custom image and text in it. Data is loading from server and i need to display new amount of data every time user moves google map camera. So i'm using android-maps-utils:0.4.3 library for creating custom Bitmap (using IconGenerator) and then create BitmapDescriptor from it. Here is part of the code:
googleMap.clear()
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
IconGenerator clusterIconGenerator = new IconGenerator(getActivity());
View clusterView = layoutInflater.inflate(R.layout.marker_cluster_view, null, false);
clusterIconGenerator.setContentView(clusterView);
clusterIconGenerator.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.mark_normal_grey));
List<Cluster> clusters = result.getResult(); // server data
for (Cluster cluster : clusters) {
Bitmap bitmap = clusterIconGenerator.makeIcon(String.valueOf(cluster.getOffersCount()));
Marker marker = googleMap.addMarker(new MarkerOptions()
.position(new LatLng(cluster.getLocation().getLatitude(), cluster.getLocation().getLongitude()))
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)) // crash here
.anchor(0.5f, 0.5f));
markerClusterMap.put(marker, cluster);
}
Everything is ok except application is crashes sometimes (not very often) with 2 different exceptions:
java.lang.RuntimeException: Could not copy bitmap to parcel blob.
at android.graphics.Bitmap.nativeWriteToParcel(Native Method)
at android.graphics.Bitmap.writeToParcel(Bitmap.java:1541)
at com.google.android.gms.maps.model.a.c.a(:com.google.android.gms:237)
at com.google.android.gms.maps.internal.h.a(:com.google.android.gms:227)
at com.google.android.gms.maps.internal.j.a(:com.google.android.gms:183)
at com.google.android.gms.maps.internal.CreatorImpl.a(:com.google.android.gms:32)
at com.google.android.gms.maps.internal.b.a(:com.google.android.gms:227)
at com.google.android.gms.maps.model.a.b.onTransact(:com.google.android.gms:106)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.model.internal.zza$zza$zza.zzc(Unknown Source)
at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source)
at com.cheapsta.cheapsta.fragments.GoogleMapFragment.clustersLoadingFinished(GoogleMapFragment.java:187)
and sometimes
java.lang.RuntimeException: Could not allocate dup blob fd.
at android.graphics.Bitmap.nativeCreateFromParcel(Native Method)
at android.graphics.Bitmap.-wrap0(Bitmap.java)
at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1516)
at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1515)
at maps.bx.a$a.onTransact(:com.google.android.gms.alldynamite:101)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.model.a.c.a(:com.google.android.gms:242)
at com.google.android.gms.maps.internal.h.a(:com.google.android.gms:227)
at com.google.android.gms.maps.internal.j.a(:com.google.android.gms:183)
at com.google.android.gms.maps.internal.CreatorImpl.a(:com.google.android.gms:32)
at com.google.android.gms.maps.internal.b.a(:com.google.android.gms:227)
at com.google.android.gms.maps.model.a.b.onTransact(:com.google.android.gms:106)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.model.internal.zza$zza$zza.zzc(Unknown Source)
at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source)
at com.cheapsta.cheapsta.fragments.GoogleMapFragment.clustersLoadingFinished(GoogleMapFragment.java:187)
What can i do with this? I guess i'm using my memory to much to create BitmapDescriptors. It's nearly 20 BitmapDescriptos every 3 seconds if user moving camera too much. Should i cache it somehow? Thx a lot for your answers and time!
Well here is what i got. Looks like BitmapFactory can't create Bitmap if it don't have enought memory. So if GC didn't do job and u don't have enough memory u'll get this exception. In my case that was pretty often because i need to generate about 10-20 markers every time user moves google map camera.
First of all don't be stupid like me and don't use android-maps-utils just for IconGenerator :) I wrote my own class that generate's BitmapDescriptor from Bitmap and caches it in LruCache. Here's good tutorial for caching Bitmaps. You can do almost the same for BitmapDescriptor. Pay attention to LruCache size. You can't get BitmapDescriptor size in bytes, so you need to think about amount of these objects in LruCache. Just look at your bitmap size and do some calculations.
If you need text in your image do something like this:
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.mark_active_grey).copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(offersCount,
canvas.getWidth()/2,
canvas.getHeight()/2 - ((clustersPaint.getFontMetrics().ascent + clustersPaint.getFontMetrics().descent) / 2) ,
clustersPaint);
Sorry for bad english and i hope this information will be useful to some one.
I had same problem. With Kuva's answer I make a new class like this:
public class MapBmpContainter
{
private int mBmpSize;
public BitmapDescriptor mBmpDescriptor;
public MapBmpContainter(Bitmap bmp)
{
mBmpSize=bmp.getByteCount()/1014;
mBmpDescriptor= BitmapDescriptorFactory.fromBitmap(bmp);
}
public int getSize()
{
return mBmpSize;
}
}
I cache new class object in LruCache instead of Bitmap.
Same with Kuva I think Bitmap and BitmapDescriptor almost same size.
And It worked
For me the problem was related to the size of the icon. I just change dynamically the size of the Bitmap and works fine.
Bitmap image2 = Bitmap.createScaledBitmap(iconBitmap, 120, 120, false);
Use Picasso , Glide or Fresco Literary to cache bitmaps efficiently.
Picasso.with(getContext())
.load(R.drawable.marker)
.resize(width, width)
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
markerOptionsHome = new MarkerOptions();
markerOptionsHome.title("Home location");
markerOptionsHome.snippet("");
markerOptionsHome.position(latlng);
markerOptionsHome.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
homeLocationMarker = map.addMarker(markerOptionsHome);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) { }
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) { }
});
I am new for Android. I want to create an jar file if i call a method of that jar file in another android application it will show an image in imageview of the application. For example
a method in jar file as DisplayImg(URL); i will use this jar as library in another application and here i will create an imageview
ImageView imageView;
imageView = (ImageView) findViewById(R.id.img);
Then if i call imageView.DisplayImg(URL); then it will display specified url image on the imageview. I spend lot more time to get the solution but not work.plz help with the code thank
You don't need to create a library, in fact, there is a same library available for doing exactly what you want to!
It's called Picasso. You can find it here.
Also note that if you want imageView.DisplayImage(URL); you should create a new instance of ImageView class, because it doesn't contain this method. I recommend using DisplayImage(URL, imageView);.
But in case you REALLY WANT to do this, here you go:
1- For creating a library, create a New Android Application Project, and in the second window, check Mark this project as a library option. Also notice that we don't need Activity.
2- Create a new class, such as ImageUtils.java in the newly-created project. Here you need to put the DisplayImage() method:
public static void DisplayImage(String URL, ImageView imageView) {
new DownloadImageTask(imageView).execute(URL);
}
And this for the DownloadImageTask class :
public static class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView imageView;
public DownloadImageTask(ImageView bmImage) {
this.imageView = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap imageBitmap = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
imageBitmap = BitmapFactory.decodeStream(in);
} catch (IOException e) {
// Probably there's no Internet connection. Warn the user about checking his/her connection.
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return imageBitmap;
}
protected void onPostExecute(Bitmap result) {
if (imageView != null) imageView.setImageBitmap(result);
}
}
3- Execute your project as an android application.
4- There should be a jar file under the bin folder. It's your library. Import it to your other applications and use it. In that applications you can use it with this code:
ImageView imageView = (ImageView) findViewById(R.id.img);
ImageUtils.DisplayImage(URL, imageView);
5- Don't forget to add this permission to the apps that use this library:
<uses-permission android:name="android.permission.INTERNET" />
Hope it helps :)
I use the following code to initialize my bitmap variable:
Bitmap bitmap = ((BitmapDrawable)this.model.gameView.context.getResources().getDrawable(R.drawable.pic1)).getBitmap();
When I try to log the width of that bitmap, the log does not even output anything for that call.
I know it's making it to that line, because I traced the code.
Also, when I try to do canvas.draw for the bitmap, nothing is drawn on the screen.
Everything I draw with rectangles works fine.
My picture resource is a PNG.
Any help is appreciated!
Try something like this for your bitmap class.
public class DrawBitmap extends View
{
Bitmap bitmap;
public DrawBitmap(Context content)
{
super(content);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic1);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);//whatever color you want, make sure it's not the same as your image
canvas.drawBitmap(bitmap, (canvas.getWidth()), 0, null);
}
}
Main Class
public class Main extends Activity
{
DrawBitmap myView;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myView = new DrawBitmap(this);
setContentView(myView);
}
}
Try using BitmapFactory.decodeResource
Have a look at the answer in this topic:
How to convert a Drawable to a Bitmap?
Just figured it out. It had nothing to do with the method of bitmap loading I used.
It was a logical error on my part. My code accidentally reached a case where my bitmap became null, and it tried to draw the null resource on the canvas.