dynamic Bitmap drawable in android - android

I am wondering how i can set a Bitmap drawable resource from a dynamic variable that is the image name/ type string:
public CustomIcon getView(int position, View convertView, ViewGroup parent) {
String label;
String image;
DataBaseManager db = new DataBaseManager(context);
label = db.getIconLabel(mIcons.get(position));
image = db.getIconImage(mIcons.get(position));
Bitmap bitmap = BitmapFactory.decodeResource(parent.getResources(),
parent.getResources().getIdentifier(image, "drawable", getApplicationContext().getPackageName()));
Log.v(TAG, "current pos:"+ position);
CustomIcon icon = new CustomIcon(context, bitmap,label);
return icon;
}
the part in question is
Bitmap bitmap = BitmapFactory.decodeResource(parent.getResources(),
R.drawable.[image]);
CODE CHANGED ABOVE -

The way to deal with this is to get the resource ID first and then use the BitmapFactory method:
String imgName = "myicon";
int resID = parent.getResources().getIdentifier(imgName, "drawable", "my.app.package.name");
Bitmap bitmap = BitmapFactory.decodeResource(parent.getResources(), resID);

Related

Android Custom text View To hold images and text

I have to show text and images exactly as TextView holds. spannable object can be used but the problem is images are being downloaded from server at run time and have to display placeholder till images are downloaded..
So I am thinking of creating Custom TextView which extends a ViewGroup but then there would be a lot of handling. let me know if there is another best option available because I have shortage of time
This can be achieved by using SpannableString and ImageSpan classes. An instance of SpannableString can be created and can be set to TeaxtView.
Instance of SpannableString can contain combination of Text and Image. Here is a quick example I could find:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textView = (TextView) findViewById(R.id.textview);
SpannableString ss = new SpannableString("abc");
Drawable d = getResources().getDrawable(R.drawable.icon32);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
textView.setText(ss);
}
Have a look at this link as well
I think the easiest way to achieve this is to create a custom TextView that inside uses Html.fromHtml() to add the images and the text. You can then feed it the placeholder and when the images load you simply update with the new image. You wouldn't need to handle almost anything.
The stuff you pass to the TextView could be something of the sort:
CustomTextView(String text, List<...> plceholders)
With the text containing string placeholders for where the images should be fitted, something like "{img} test message {img}" and then a simple search and replace for {img} with the <img> tag should be enough.
You can find plenty of samples online about Html.fromHtml().
Also, N-JOY's Spannable String solution would work.
Here is the solution I implemented.
Spanned spanned = null;
String messageCustomized = "<img src ='"+ WebConstant.IMAGE_BASE_URL +
part +"'/>";//WebConstant.IMAGE_BASE_URL + part;
Spanned span = Html.fromHtml(messageCustomized, new
URLImageParser(sentMessagesViewHolder.tvMessage, context), null);
if (spanned!=null) {
spanned = (Spanned) TextUtils.concat(spanned, span);
}else spanned= span;
if (spanned!=null) {
txtView.setText(spanned);
}
Image Getter
public class URLImageParser implements ImageGetter {
Context context;
View container;
private int imageSize = 20;
private int imageSizeDisplaySize = 20;
URLDrawable urlDrawable = null;
public URLImageParser(View container, Context context) {
this.context = context;
this.container = container;
imageSize = Utility.convertDpTopPixels(context, 20);
imageSizeDisplaySize = Utility.convertDpTopPixels(context, 35);
}
#Override
public Drawable getDrawable(final String url) {
String[] arr = url.split("/");
final String fileName = arr[arr.length - 1];
urlDrawable = new URLDrawable();
Drawable drawable = null;
if (Build.VERSION.SDK_INT >= 21)
drawable =
context.getDrawable(R.drawable.profile_main_placeholder);
else
drawable = context.getResources().getDrawable(R.drawable.profile_main_placeholder);
drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize);
urlDrawable.drawable = drawable;
Bitmap bitmap = null;
bitmap = ImageUtility.getImageFromSDCard(fileName);
if (bitmap != null) { // the bitmap is available
bitmap = RoundedImageView.getCroppedBitmap(bitmap, imageSize, imageSize, imageSize);
drawable = new BitmapDrawable(context.getResources(), bitmap);//ImageUtility.bitmapToDrawable(context,resource);
drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize); //set the correct bound according to the result from HTTP call
URLImageParser.this.urlDrawable.drawable = drawable;
} else
Glide.with(context)
.load(url)
.asBitmap()
.transform(new CircleTransform(context))
.override(imageSizeDisplaySize, imageSizeDisplaySize)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
// you can do something with loaded bitmap here
// .....
Drawable drawable = new BitmapDrawable(context.getResources(), resource);//ImageUtility.bitmapToDrawable(context,resource);
drawable.setBounds(0, 0, 0 + imageSize, 0 + imageSize); //set the correct bound according to the result from HTTP call
URLImageParser.this.urlDrawable.drawable = drawable;
URLImageParser.this.container.invalidate();
ImageUtility.saveImageToSDCard(resource, fileName);
}
});
return urlDrawable.drawable; //return reference to URLDrawable where We will change with actual image from the src tag
//}
}
}
Custom Bitmap Drawable
public class URLDrawable extends BitmapDrawable {
// the drawable that you need to set, you could set the initial drawing
// with the loading image if you need to
protected Drawable drawable;
#Override
public void draw(Canvas canvas) {
// override the draw to facilitate refresh function later
if(drawable != null) {
drawable.draw(canvas);
}
}
}

how to set image stored in database to imageView in android?

I want to set image address that is stored in database to image view
I have this code but I don't know do it, I get name column to TextView but I can't set image address to imageview
Please help me!
Source code:
#Override
public View getView(int arg0, View view, ViewGroup arg2) {
// TODO Auto-generated method stub
View v1 = view;
if (v1 == null) {
v1 = inflate.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.txt_name = (TextView) v1.findViewById(R.id.item_name);
holder.src = (TextView) v1.findViewById(R.id.textView1);
holder.img = (ImageView) v1.findViewById(R.id.item_img);
v1.setTag(holder);
} else {
holder = (ViewHolder) v1.getTag();
}
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(arg0);
holder.txt_name.setText(song.get("name"));
return v1;
}
static class ViewHolder {
TextView txt_name,src;
ImageView img;
}
it depends on how you saved your image
assuming it's 64base array you can do like that
byte[] imageBytes = Base64.decode(song.getImageBytes(), Base64.DEFAULT);
Bitmap pic = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
imageView.setImageBitmap(pic);
What do you mean with "image adress" ?
Is it a local image saved in your device with local path stored in your database or an URL and you need to download the image ?
If local path : Show Image View from file path?
If you have an URL and you need to download image : How to load an ImageView by URL in Android?

skimagedecoder::factory returned null, Skipping frames in Android

I am using a GridView to display the images of albumart, for that i am creating a adapter, below is the code of my getView function of adapter
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
FrameLayout albumLayout = (FrameLayout)layoutInflater.inflate(R.layout.album, viewGroup, false);
ImageView imageview = (ImageView)albumLayout.findViewById(R.id.iconItem);
int albumId = keys[position];
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
Bitmap image = null;
try {
image = MediaStore.Images.Media.getBitmap(resolver, albumArtUri);
//image = Bitmap.createScaledBitmap(image, 80, 80, true);
} catch (IOException e) {
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.musicimage);
}
imageview.setImageBitmap(image);
String albumName = albumMap.get(albumId);
TextView albumNameView = (TextView)albumLayout.findViewById(R.id.textItem);
albumNameView.setText(albumName);
albumLayout.setTag(albumId);
return albumLayout;
}
I have 4 fragments inside a ViewPager and when i swipe to the album page then it gets stuck there and i am getting skimagedecoder::factory returned null, Skipping frames in logs.
Can anyone suggest me how to resolve this and how can i make it more efficient so that while swiping the view should not get stuck.

The method getThumbnail is not applicable for the type

I tried to use the following snippet to get a thumbnail from my URI of the original image.
Bitmap bitmap = MediaStore.Images.Thumbnails.getThumbnail(
context.getContentResolver(), uri,
MediaStore.Images.Thumbnails.MINI_KIND,
(BitmapFactory.Options) null );
My URI uri:
Uri uri = Uri.parse(ki.getEreignisbild());
Now, the getThumbnail function is red underlined and the error message says
The method getThumbnail(ContentResolver, long, int, BitmapFactory.Options)
in the type MediaStore.Images.Thumbnails is not applicable for the arguments
(ContentResolver, Uri, int, BitmapFactory.Options)
Googled it but not found anything. Any ideas what I can do?
EDIT:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderEreignis holder;
if(convertView == null){
convertView = inflator.inflate(R.layout.list_ereignis, parent, false);
holder = new ViewHolderEreignis((TextView) convertView.findViewById(R.id.enullline), (TextView) convertView.findViewById(R.id.efirstLine), (ImageView) convertView.findViewById(R.id.eimgv));
convertView.setTag(holder);
}
else{
holder = (ViewHolderEreignis) convertView.getTag();
}
Ereignis ki = (Ereignis) getItem(position);
holder.getEreignisname().setText(ki.getEreignisname());
holder.getEreignisdatum().setText(ki.getEreignisZeit());
Uri uri = Uri.parse(ki.getEreignisbild());
String imageUri;
try{
String path = ki.getEreignisbild();
Bitmap de = resizeBitmap(path);
Bitmap bitmap = MediaStore.Images.Thumbnails.getThumbnail(
context.getContentResolver(), uri,
MediaStore.Images.Thumbnails.MINI_KIND,
(BitmapFactory.Options) null );
// Drawable drawable = holder.getEreignisbild().setImageDrawable(R.drawable.male);
// holder.getEreignisbild().setImageResource(R.drawable.male);
}
catch(Exception e){
}
return convertView;
}
getThumbnail(ContentResolver, long, int, BitmapFactory.Options)
(ContentResolver, Uri, int, BitmapFactory.Options)
See the difference? You're passing the wrong type for the 2nd argument.

java.lang.outofmemory error at bitmap factory.decodefile in Android

First i call MediaStore.ACTION_IMAGE_CAPTURE intent to open camera then i get the saved captured image path from this function.
private String getLastImageId(){
String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
if(imageCursor.moveToFirst()){
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
//imageCursor.close();
return fullPath;
}else{
return "";
}
}
then i pass that path to a product object attribute as a parameter.
add that object to product list
that list is displayed by a customized adapter.
i am displaying the product title and image in the listView
in customized adapter class i get the product fetch product title and path from it
make a bitmap from path and asign it to the product holder that contain a image view
working this way for first photo is fine but on the second photo it gives the exception of java.lang.outofmemory i have also tried the solution given at
java.lang.OutOfMemoryError: bitmap size exceeds VM budget - Android
doing so as in product adapter
public class ProductAdopter extends ArrayAdapter<Product> {
Context context;
int layoutResourceId;
ArrayList<Product> data = null;
public ProductAdopter(Context context, int layoutResourceId, ArrayList<Product> product_data) {
// TODO Auto-generated constructor stub
super(context, layoutResourceId, product_data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = product_data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ProductHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((MainActivity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ProductHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder);
}
else
{
holder = (ProductHolder)row.getTag();
}
Product product = data.get(position);
holder.txtTitle.setText(product.getName());
File imgFile = new File(product.icon);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
holder.imgIcon.setImageBitmap(myBitmap);
//myBitmap.recycle();
}
return row;
}
static class ProductHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
if(imgFile.exists()){
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(),options);
holder.imgIcon.setImageBitmap(myBitmap);
//myBitmap.recycle();
}
Use inSampleSize to load scales bitmaps to memory. Using powers of 2 for inSampleSize values is faster and more efficient for the decoder. However, if you plan to cache the resized versions in memory or on disk, it’s usually still worth decoding to the most appropriate image dimensions to save space.
For more see Loading Large Bitmaps Efficiently
You will run into out of memory issues if you try to decode big images yourself.
Try using Universal Image loader. It will take care of all image loading from local storage or the internet.
https://github.com/nostra13/Android-Universal-Image-Loader
OutOfMemory can be tiring
here are some few options that you can look
try {
//Create your bitmap here
} catch (OutOfMemoryError ooM) {
// You got out of memory now do something to recycle images
// Yes you can catch OOM.
recycle();
}
If you do not have many images to handle then you can try this.
BitmapFactory.Options op = new BitmapFactory.Options();
op.inSampleSize = 8;
return BitmapFactory.decodeFile("<YOUR IMAGE FILE HERE>", op);
A combination of above can be useful if you have many images

Categories

Resources