I am using Picasso library to load images into ImageView, Like i have only one item in a ListView, so its showing progress loader even image has been downloaded successfully and visible in ImageView.
So how may i do control over it ?
viewHolder.progressBar.setVisibility(View.VISIBLE);
Picasso.with(MainActivity.this)
.load(imageURL) // web image URL
.fit().centerInside()
.transform(transformation)
.error(R.drawable.ic_launcher)
.placeholder(R.drawable.ic_launcher)
.rotate(90)
.into(viewHolder.imageViewReport , new Callback() {
#Override
public void onSuccess() {
// TODO Auto-generated method stub
viewHolder.progressBar.setVisibility(View.GONE);
}
#Override
public void onError() {
// TODO Auto-generated method stub
viewHolder.progressBar.setVisibility(View.GONE);
}
});
Usually, I am facing this issue for the first list item ...
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// convert view = design
View view = convertView;
if (view == null) {
viewHolder = new ViewHolder();
view = layoutInflater.inflate(Resource, null);
viewHolder.imageView = (ImageView) view.findViewById(R.id.imageView);
viewHolder.progressBar = (ProgressBar) view.findViewById(R.id.progressBar1);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
final Transformation transformation = new Transformation() {
#Override
public Bitmap transform(Bitmap source) {
int targetWidth = viewHolder.imageViewReport.getWidth();
double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
int targetHeight = (int) (targetWidth * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
// Same bitmap is returned if sizes are the same
source.recycle();
}
return result;
}
#Override
public String key() {
// TODO Auto-generated method stub
return null;
}
};
Related
I need to create and set customize bitmap image on each row of listview. I am doing that using picasso. My code inside getView of adapter is like below,
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
View rowView = convertView;
if (rowView == null){
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.horizontal_listview_list_sample, parent, false);
viewHolder = new ViewHolder();
viewHolder.imgDot = (ImageView) rowView.findViewById(R.id.rowIcon);
viewHolder.rowIconBackround = (ImageView) rowView.findViewById(R.id.rowIconBackground);
rowView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) rowView.getTag();
}
//Start Custom Image View///////
String photoUrl1 = arrayList.get(position).getPhotoUrl();
if (photoUrl1.length()<8){
photoUrl1 = "SOME_URL";
}
final String photoUrl = photoUrl1;
final ImageView imgDot = viewHolder.imgDot;
// final viewHolder.imgDot = (ImageView) rowView.findViewById(R.id.rowIcon);
final View finalRowView = rowView;
final ViewHolder finalViewHolder = viewHolder;
final Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap2, Picasso.LoadedFrom from) {
Log.d("PICASO", " called: " + "onBitmapLoaded called");
Bitmap original;
original = new MyProfile().getResizedBitmap(bitmap2, (int) new MainActivity().dipToPixels(MainActivity.getInstance(), 63), (int) new MainActivity().dipToPixels(MainActivity.getInstance(), 63));
BitmapDrawable bitmap = (BitmapDrawable) finalRowView.getResources().getDrawable(R.drawable.drawer_pro_pic_placeholder);
int bitmapHeight= bitmap .getBitmap().getHeight();
int bitmapWidth = bitmap .getBitmap().getWidth();
Bitmap mask = BitmapFactory.decodeResource(finalRowView.getResources(), R.drawable.drawer_pro_pic_placeholder);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
int width = mask.getWidth();
int height = mask.getHeight();
float centerX = (width - original.getWidth()) * 0.5f;
float centerY = (height- original.getHeight()) * 0.5f;
mCanvas.drawBitmap(original, centerX, centerY, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
imgDot.getLayoutParams().height = bitmapHeight;
imgDot.getLayoutParams().width = bitmapWidth;
imgDot.setScaleType(ImageView.ScaleType.CENTER_CROP);
imgDot.setImageBitmap(result);
imgDot.setAdjustViewBounds(true);
Picasso.with(context).cancelRequest(finalViewHolder.imgDot);
targets.remove(this);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d("PICASO", " called: " + "onBitmapFailed called");
Picasso.with(context).cancelRequest(finalViewHolder.imgDot);
targets.remove(this);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d("PICASO", "responseForRegistration called: " + "onPrepareLoad called");
}
};
targets.add(target);
// imgDot.setTag(target);
Picasso.with(context).load(photoUrl).into(target);
//End Custom Image View////////////
return rowView;
}
Suppose, there is two row so two customize bitmap will be created. When first one is created its showing nice but when second one created then this last image is showing in both row's imageview.
What I need to change in my code?
Any help will be appreciated.
You could try something by creating handler as subclass of your adapter and passing specific reference of your view holder and position which will help us to avoid overriding issue of target listener
// construct the handler inside your adapter's constructor so you know it is on the UI thread
Handler myHandler = new Handler();
class LoadImage implements Runnable {
ImageView iv;
int position;
public LoadImage(ImageView iv, int position) {
this.iv = iv;
this.position = position;
}
#Override
public void run() {
// keep your target listener stuffs here
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap2, Picasso.LoadedFrom from) {
Log.d("PICASO", " called: " + "onBitmapLoaded called");
Bitmap original;
original = new MyProfile().getResizedBitmap(bitmap2, (int) new MainActivity().dipToPixels(MainActivity.getInstance(), 63), (int) new MainActivity().dipToPixels(MainActivity.getInstance(), 63));
BitmapDrawable bitmap = (BitmapDrawable) finalRowView.getResources().getDrawable(R.drawable.drawer_pro_pic_placeholder);
int bitmapHeight= bitmap .getBitmap().getHeight();
int bitmapWidth = bitmap .getBitmap().getWidth();
Bitmap mask = BitmapFactory.decodeResource(finalRowView.getResources(), R.drawable.drawer_pro_pic_placeholder);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
int width = mask.getWidth();
int height = mask.getHeight();
float centerX = (width - original.getWidth()) * 0.5f;
float centerY = (height- original.getHeight()) * 0.5f;
mCanvas.drawBitmap(original, centerX, centerY, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
iv.getLayoutParams().height = bitmapHeight;
iv.getLayoutParams().width = bitmapWidth;
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv.setImageBitmap(result);
iv.setAdjustViewBounds(true);
Picasso.with(context).cancelRequest(iv);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d("PICASO", " called: " + "onBitmapFailed called");
Picasso.with(context).cancelRequest(iv);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d("PICASO", "responseForRegistration called: " + "onPrepareLoad called");
}
};
Picasso.with(context).load(photoList.get(position)).into(target);
}
}
And you will call it from your getView by :
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
View rowView = convertView;
if (rowView == null){
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.horizontal_listview_list_sample, parent, false);
viewHolder = new ViewHolder();
viewHolder.imgDot = (ImageView) rowView.findViewById(R.id.rowIcon);
viewHolder.rowIconBackround = (ImageView) rowView.findViewById(R.id.rowIconBackground);
rowView.setTag(viewHolder);
//Change is here
viewHolder.mRunnable = new LoadImage(viewHolder.imgDot, position);
}else {
viewHolder = (ViewHolder) rowView.getTag();
//Change is here
myHandler.removeCallbacks(viewHolder.mRunnable);
}
//Start Custom Image View///////
String photoUrl1 = arrayList.get(position).getPhotoUrl();
if (photoUrl1.length()<8){
photoUrl1 = "SOME_URL";
}
final String photoUrl = photoUrl1;
final ImageView imgDot = viewHolder.imgDot;
// final viewHolder.imgDot = (ImageView) rowView.findViewById(R.id.rowIcon);
final View finalRowView = rowView;
final ViewHolder finalViewHolder = viewHolder;
//Change is here
myHandler.postDelayed(viewHolder.mRunnable, 3000);
return rowView;
}
I got the following getView in listView's adapter:
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View view = convertView;
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.item_message, null);
}
final Message msg = getItem(position);
final AQuery aq = new AQuery(view);
aq.id(R.id.message_baloon).background(myMessage ? R.drawable.chat_message_own : R.drawable.chat_message_other);
// shared image
if (msg.getPhotos() != null && msg.getPhotos().size() != 0) {
aq.id(R.id.sent_photo).visible();
aq.image(msg.getPhotos().get(0).getUrl(), true, true, 540, R.drawable.room_details_gallery_placeholder);
aq.clicked(new View.OnClickListener() {
#Override
public void onClick(View v) {
//show fullsecreen photo
}
});
} else {
aq.id(R.id.sent_photo).gone();
}
if (msg.getText() == null || msg.getText().length() == 0) {
aq.id(R.id.message).gone();
} else {
aq.id(R.id.message).text(msg.getText());
aq.id(R.id.message).visible();
}
return view;
}
The method is actually a longer but this part contains everything related to that ImageView. So, as the title states, when scrolling really fast the ImageView, with "R.id.sent_photo", is visible for a position which doesn't have a photo and not for a fraction of a second, it remains visible (that's AndroidQuery library that I'm using).
Thank you!
I was got same problem so, i had used following methods in my custom adapter, i got solution.
Add following methods inside your ListViewItemsAdapter:
#Override
public int getCount() {
return alUpgradeTour.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return getCount();
}
Try it, you will also get solution.
Try this, it seems that AndroidQuery library don't put placeholder image before download
if (msg.getPhotos() != null && msg.getPhotos().size() != 0) {
aq.id(R.id.sent_photo).visible();
aq.id(R.id.sent_photo).setImageResource(R.drawable.room_details_gallery_placeholder);
aq.image(msg.getPhotos().get(0).getUrl(), true, true, 540, R.drawable.room_details_gallery_placeholder);
aq.clicked(new View.OnClickListener() {
#Override
public void onClick(View v) {
//show fullsecreen photo
}
});
} else {
aq.id(R.id.sent_photo).gone();
}
The solution is not using memory cache:
aq.image(msg.getPhotos().get(0).getUrl(), false, true, 540, R.drawable.room_details_gallery_placeholder);
AndroidQuery somewhere along that image function does the following
public static void async(Activity act, Context context, ImageView iv, String url, boolean memCache, boolean fileCache, int targetWidth, int fallbackId, Bitmap preset, int animation, float ratio, float anchor, Object progress, AccountHandle ah, int policy, int round, HttpHost proxy, String networkUrl){
Bitmap bm = null;
if(memCache){
bm = memGet(url, targetWidth, round);
}
if(bm != null){
iv.setTag(AQuery.TAG_URL, url);
Common.showProgress(progress, url, false);
setBmAnimate(iv, bm, preset, fallbackId, animation, ratio, anchor, AjaxStatus.MEMORY);
}else{
Bit...
So if it got a bitmap from memCache it calls setBmAnimate
private static void setBmAnimate(ImageView iv, Bitmap bm, Bitmap preset, int fallback, int animation, float ratio, float anchor, int source){
bm = filter(iv, bm, fallback);...
And filter is:
private static Bitmap filter(View iv, Bitmap bm, int fallback){
//ignore 1x1 pixels
if(bm != null && bm.getWidth() == 1 && bm.getHeight() == 1 && bm != empty){
bm = null;
}
if(bm != null){
iv.setVisibility(View.VISIBLE);
}else if(fallback == AQuery.GONE){
iv.setVisibility(View.GONE);
}else if(fallback == AQuery.INVISIBLE){
iv.setVisibility(View.INVISIBLE);
}
return bm;
I am loading remote image into row of listView using picaso callback. But image changes multiple times when listView is scrolled very fast. I guess its due to row reuse. How can I correct it and show correct image without reloading of different images in imageView.
I also setting null bitmap into ImageView. So that it doesn't use previous image while reusing image
Here is My Code:
#Override
public View getView(int position, View convertView, ViewGroup arg2)
{
ViewHolder holder = null;
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.row_health, arg2, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
holder.imageOfDoctor_select.setImageBitmap(null);
}
loadImage("imageViewURL", relLyt_txtPicInitials, imgVw);
}
private void loadImage(String imgURL, RoundedImage imgVw, RelativeLayout relLyt_txtPicInitials){
Target target = new Target() {
#Override
public void onBitmapFailed(Drawable arg0)
{
// TODO Auto-generated method stub
}
#Override
public void onPrepareLoad(Drawable arg0)
{
// TODO Auto-generated method stub
}
#Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom arg1)
{
if(bitmap != null){
imgVw.setVisibility(View.VISIBLE);
imgVw.setImageBitmap(bitmap);
relLyt_txtPicInitials.setVisibility(View.GONE);
}
}
};
if (!TextUtils.isEmpty(imgURL) && !imgURL.equalsIgnoreCase("null") && URLUtil.isValidUrl(imgURL))
{
Picasso.with(context).load(imgURL).into(target);
}
}
RoundedImage.java
public class RoundedImage extends ImageView
{
private float cornerRadius;
private float bitmapCornerRadius;
public RoundedImage(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
getXMLAttribute(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundedImage(Context context, AttributeSet attrs)
{
super(context, attrs);
getXMLAttribute(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundedImage(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
#Override
public void setImageBitmap(Bitmap bm)
{
if (bm != null)
{
bm = Utils.getRoundedCornerBitmap(bm, 50);
}
super.setImageBitmap(bm);
}
private void getXMLAttribute(Context context, AttributeSet attrs)
{
// Get proportion.
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornerImageView);
cornerRadius = a.getDimension(R.styleable.RoundedCornerImageView_cornerRadius, 0);
a.recycle();
}
public void setCornerRadius(int radius)
{
this.cornerRadius = radius;
}
#Override
protected void onDraw(Canvas canvas)
{
boolean applyCornerToBitmap = false;
Drawable drawable = getDrawable();
if (drawable != null)
{
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap != null)
{
int viewWidth = getWidth();
if (viewWidth != 0f)
{ // Only round the corner if view width is not zero.
// Calculate the corner radius on the real bitmap, based on
// the
// corner radius of the view.
int bitmapWidth = bitmap.getWidth();
float newBitmapCornerRadius = cornerRadius * bitmapWidth / viewWidth;
// If newBitmapCornerRadius equals to bitmapCornerRadius,
// then it is not needed to set the round the corner bitmap
// to the drawable again.
if (bitmapCornerRadius != newBitmapCornerRadius)
{
applyCornerToBitmap = true;
// Create bitmap with rounded corner.
int bitmapHeight = bitmap.getHeight();
bitmapCornerRadius = newBitmapCornerRadius;
bitmap = Utils.getRoundedCornerBitmap(bitmap, 50);
// Set rounded corner bitmap to the view's drawable.
setImageBitmap(bitmap); // This will call onDraw()
// again.
}
}
}
}
// Call super onDraw() if the drawable has already been rounded.
if (!applyCornerToBitmap)
{
super.onDraw(canvas);
}
}
}
Modify like this, you guessed right, issue is related to views recycling, and in every getView method, all images must clear, for example set placeholder or set null, I don't know exactly imgVw or holder.imageOfDoctor_select must reset, try them both
How can I correct it and show correct image without reloading of different images in imageView.
You can't, because ImageView still holds previous image
#Override
public View getView(int position, View convertView, ViewGroup arg2) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.row_health, arg2, false);
holder = new ViewHolder();
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageOfDoctor_select.setImageBitmap(null); //Or put placeholder here, until image loaded
loadImage("imageViewURL", relLyt_txtPicInitials, imgVw);
}
I can suggerst an another solution, without a target, just use public void into(android.widget.ImageView target, com.squareup.picasso.Callback callback) this overload similar this
Picasso.with(getContext())
.load(imgVw)
.into(imgVw, new Callback() {
#Override
public void onSuccess() {
imgVw.setVisibility(View.VISIBLE);
relLyt_txtPicInitials.setVisibility(View.GONE);
}
#Override
public void onError() {
}
});
I am using a GridView to display images. The images are downloaded from a feed and added to a BitmapCache. The GridView is inside of a ViewFlipper (which has a ListView as second View). I'm using GridView for the first time but I've worked with Adapters many times when I used ListViews.
At the moment, the feed only delivers two images. But when I start my Fragment containing the GridView I get an OutOfMemoryError caused bei BitmapFactory.decodeStream(). When I took a deeper look into the logcat, I noticed that getView() inside of my Adapter for the GridView is called many many times.
I know that it's nothing special if getView() is called more than once, but the getView()-method in my Adapter gets called over 120 times only for position 0. And I don't really understand why it's called so often. But I'm pretty sure that this caused my memory problem as this method tries to load a bitmap over 100 times in just a few seconds.
As I'm already trying to recycle my view with a ViewHolder I'm quite helpless at the moment and I hope somebody can explain me this massive calls of getView() and/or might give me a hint to solve my problem.
The getView()-mthod of my adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.pictures_grid_item, parent, false);
holder.image = (ImageView) convertView.findViewById(R.id.picturesGridImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.image.setImageBitmap(null);
}
Picture picture = (Picture) pictureList.get(position);
String imageUrl = picture.getUrl();
if (!TextUtils.isEmpty(imageUrl)) {
holder.image.setTag(imageUrl);
ImageLoader.getInstance(context).loadImageWithTagCheck(holder.image);
}
return convertView;
}
private static class ViewHolder {
ImageView image;
}
The loadImageWithTagCheck()-method just checks if the image has already been downloaded (which deffinitely should be the case)
The Fragment which holds the View:
public class PicturesFragment extends BaseFragment {
private List<Parcelable> pictureList;
private PicturesGridAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.pictures_fragment, container, false);
// TODO: Remove final after development
final MediaActivity activity = (MediaActivity) getActivity();
pictureList = activity.getPictures();
adapter = new PicturesGridAdapter(activity, pictureList);
GridView gridview = (GridView) view.findViewById(R.id.picturesGrid);
gridview.setAdapter(adapter);
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
BTW: I'm not using *wrap_content* anywhere.
Edit:
Here's the code of the imageloader. Ofcourse, the ImageLoader is the problem which causes the outOfMemoryError. But I think that the problem is rather something with the adapter because 120 calls of getView() for position 0 just after creating the view can't be right. And the Adapter is just created once so it's >120 calls in a single instance of my adapter.
(this is a pretty huge and complex project so the "simple" imageloader has a lot of code)
public void loadImageWithTagCheck(final ImageView view) {
final String url = (String) view.getTag();
final Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
}
};
if (imageHandler != null) {
imageHandler.post(new Runnable() {
#Override
public void run() {
final Bitmap bmp = getImage(url, view);
uiHandler.post(new Runnable() {
#Override
public void run() {
String tagUrl = (String) view.getTag();
if (tagUrl.equals(url) && bmp != null
&& !bmp.isRecycled()) {
scaleBitmapAndAdjustViewByHeight(view, bmp);
} else if (bmp != null) {
bmp.recycle();
}
}
});
}
});
}
}
private Bitmap getImage(String url, View v) {
Bitmap bmp = null;
if (url != null && !TextUtils.isEmpty(url)) {
String md5Url = Utility.md5(url);
if (cache.containsKey(md5Url)) {
bmp = cache.getBitmap(md5Url);
} else {
HttpGet httpGet = new HttpGet();
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = null;
try {
URI uri = new URI(url);
httpGet.setURI(uri);
response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
final BufferedInputStream buffIn = new BufferedInputStream(
entity.getContent(), Utils.IO_BUFFER_SIZE);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.outWidth = v.getWidth();
options.outHeight = v.getHeight();
options.inPurgeable = true;
options.inInputShareable = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
bmp = BitmapFactory.decodeStream(buffIn, null,
options);
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
if (bmp != null) {
cache.put(md5Url, bmp);
}
}
}
return bmp;
}
private void scaleBitmapAndAdjustViewByHeight(final ImageView view,
final Bitmap bmp) {
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
// Get current dimensions
int width = bmp.getWidth();
int height = bmp.getHeight();
// Determine how much to scale: the dimension requiring less
// scaling is closer to the its side. This way the image always
// stays inside your bounding box AND either x/y axis touches
// it.
int imageViewHeightFromXMLinPixels = view.getHeight();
float xScale = (float) ((imageViewHeightFromXMLinPixels * 2.75) / width);
float yScale = ((float) imageViewHeightFromXMLinPixels)
/ height;
float scale = (xScale <= yScale) ? xScale : yScale;
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap
Bitmap scaledBitmap = Bitmap.createBitmap(bmp, 0, 0, width,
height, matrix, true);
width = scaledBitmap.getWidth(); // re-use
view.setImageBitmap(scaledBitmap);
view.getLayoutParams().width = width;
}
});
view.requestLayout();
}
Get rid of the scaleBitmapAndAdjustViewByHeight(...) method.
Instead, do a simple view.setImageBitmap(bmp).
Why?
scaleBitmapAndAdjustViewByHeight(...) calls view.requestLayout() which probably leads to calling your adapters getView(...) and ends in a deadlock and finally the OutOfMemoryError.
I am new to android. I am displaying images in gridview by using AsyncTask. But there are some issues like:
1: onScroll AsyncTask tasks gets call again.
2: Images are not displaying correctly ( Once I scroll it shows top image and load the original latter).
here is my code:
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ListRowHolder listRowHolder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.ll_sponsor_list_item,
parent, false);
listRowHolder = new ListRowHolder();
listRowHolder.imgSponsor = (ImageView) convertView
.findViewById(R.id.imggrid_item_image);
convertView.setTag(listRowHolder);
} else {
listRowHolder = (ListRowHolder) convertView.getTag();
}
try {
task = new BitmapWorkerTask(listRowHolder.imgSponsor);
task.image_path = ImageName.get(position);
task.execute(1);
} catch (Exception e) {
if (thisLogger != null) {
thisLogger.error(e.toString());
thisLogger.error("\r\n");
}
}
return convertView;
}
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String image_path;
public BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Bitmap doInBackground(Integer... params) {
try {
while (running) {
Bitmap picture = BitmapFactory.decodeFile(image_path);
int width = picture.getWidth();
int height = picture.getHeight();
float aspectRatio = (float) width / (float) height;
int newWidth = 98;
int newHeight = (int) (98 / aspectRatio);
Log.v("ImageList", "L");
return picture = Bitmap.createScaledBitmap(picture,
newWidth, newHeight, true);
}
} catch (Exception e) {
if (thisLogger != null) {
thisLogger.error(e.toString());
thisLogger.error("\r\n");
}
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
Please let me know whats wrong here.