Image slider using viewPager. freeze while sliding - java

I'm created app, which gets images from gallery, shows in VewPager and we can slide it. There only problem is that if the image size is more than 1mb, the slide freezes, lagging. If i add images in gallery 100-200kb, that not freeze. Any solution? Thanks.
Here the adapter.
public class PhotoPagerAdapter extends PagerAdapter {
private ImageView imageView;
private Context context;
private LayoutInflater inflater;
private ArrayList<String> listOfAllImages = new ArrayList<>();
private ArrayList<Bitmap> listOfAllBitmap = new ArrayList<>();
public PhotoPagerAdapter(Context context) {
this.context = context;
getAllShownImagesPath();
}
#Override
public int getCount() {
return listOfAllImages.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.photopager, null);
imageView = (ImageView) view.findViewById(R.id.photoView2);
imageView.setImageBitmap(listOfAllBitmap.get(position));
imageView.setRotation(90);
ViewPager viewPager = (ViewPager) container;
viewPager.addView(view, 0);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
ViewPager vp = (ViewPager) container;
View view = (View) object;
vp.removeView(view);
}
private void getAllShownImagesPath() {
Uri uri;
Cursor cursor;
int column_index_data;
String absolutePathOfImage;
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
cursor = context.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(absolutePathOfImage);
listOfAllBitmap.add(BitmapFactory.decodeFile(absolutePathOfImage));
}
cursor.close();
}
}
And here's the fragment.
public class ShowCamera2 extends BaseFragment{
private View mainView;
private ViewPager viewPager;
private PhotoPagerAdapter photoPagerAdapter;
private Button prev, next;
private TextView imageCount;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.camera_fragment, container, false);
prev = (Button) mainView.findViewById(R.id.prevPhoto2);
next = (Button) mainView.findViewById(R.id.nextPhoto2);
viewPager = (ViewPager) mainView.findViewById(R.id.viewPager);
photoPagerAdapter = new PhotoPagerAdapter(this.getActivity());
viewPager.setAdapter(photoPagerAdapter);
prev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
}
});
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
}
});
return mainView;
}
}
Anyone can help me? Thank you for reading.
Here the update.
public class PhotoPagerAdapter extends PagerAdapter {
private ImageView imageView;
private Context context;
private LayoutInflater inflater;
private ArrayList<String> listOfAllImages = new ArrayList<>();
private ArrayList<Bitmap> listOfAllBitmap = new ArrayList<>();
public PhotoPagerAdapter(Context context) {
this.context = context;
getAllShownImagesPath();
}
#Override
public int getCount() {
return listOfAllBitmap.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.photopager, null);
imageView = (ImageView) view.findViewById(R.id.photoView2);
imageView.setImageBitmap(listOfAllBitmap.get(position));
imageView.setRotation(90);
ViewPager viewPager = (ViewPager) container;
viewPager.addView(view, 0);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
ViewPager vp = (ViewPager) container;
View view = (View) object;
vp.removeView(view);
}
private void getAllShownImagesPath() {
Uri uri;
Cursor cursor;
int column_index_data;
String absolutePathOfImage;
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
cursor = context.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
//listOfAllImages.add(absolutePathOfImage);
listOfAllBitmap.add(decodeBitmapURI(context, absolutePathOfImage, 1000, 500));
}
cursor.close();
}
public Bitmap decodeBitmapURI(Context context, String uri, int imageWidth, int imageHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(Uri.parse(uri)), null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, imageWidth, imageHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(Uri.parse(uri)), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}

Try this code
Picasso.with(mContext).
load(url) // from gallery load("file://" + url)
.centerCrop().placeholder(placeHolderRecource)
.resize(Utilities.dpToPx(100, mContext), Utilities.dpToPx(100, mContext)).into(imgView);
public static int dpToPx(int dp, Context mContext)
{
DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}

Replace this linelistOfAllBitmap.add(BitmapFactory.decodeFile(absolutePathOfImage));
with
listOfAllBitmap.add(decodeBitmapURI(context, Uri.parse(new File(absolutePathOfImage).toString()), 700, 350););
Check below solution for Loading Large Images, as android docs:
public Bitmap decodeBitmapURI(Context context, Uri uri,int imageWidth, int imageHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, imageWidth, imageHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}

I used Glide, and this helped me.
public class ImageAdapter extends PagerAdapter {
private ImageView imageView;
private Context context;
private LayoutInflater inflater;
private ArrayList<String> listOfAllImages = new ArrayList<>();
public ImageAdapter(Context context) {
this.context = context;
getAllShownImagesPath();
}
#Override
public int getCount() {
return listOfAllImages.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.photopager, null);
imageView = (ImageView) view.findViewById(R.id.photoView2);
Glide.with(context).load(listOfAllImages.get(position))
.thumbnail(1f)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
ViewPager viewPager = (ViewPager) container;
viewPager.addView(view, 0);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
ViewPager vp = (ViewPager) container;
View view = (View) object;
vp.removeView(view);
}
private void getAllShownImagesPath() {
Uri uri;
Cursor cursor;
int column_index_data;
String absolutePathOfImage;
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
cursor = context.getContentResolver().query(uri, projection, null,
null, null);
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(absolutePathOfImage);
}
cursor.close();
}
}

Related

ViewPager carousel not showing properly with small images

Hi I'm new in android and recently I made a carousel with viewpager using this and it works fine with full width height images but when i resize images it doesn't work properly by that I mean it takes the entire width of the screen instead of specified width.
The actual idea is to have a carousel at the bottom of the page with small images.
So this is where I'm stuck and need some help actually I don't have much idea about this so I would appreciate some help.
Thank you
My code are below as follows
CarouselTransformer.class
public class CarouselEffectTransformer implements ViewPager.PageTransformer {
private int maxTranslateOffsetX;
private ViewPager viewPager;
public CarouselEffectTransformer(Context context) {
this.maxTranslateOffsetX = dp2px(context, 180);
}
public void transformPage(View view, float position) {
if (viewPager == null) {
viewPager = (ViewPager) view.getParent();
}
int leftInScreen = view.getLeft() - viewPager.getScrollX();
int centerXInViewPager = leftInScreen + view.getMeasuredWidth() / 2;
int offsetX = centerXInViewPager - viewPager.getMeasuredWidth() / 2;
float offsetRate = (float) offsetX * 0.38f / viewPager.getMeasuredWidth();
float scaleFactor = 1 - Math.abs(offsetRate);
if (scaleFactor > 0) {
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setTranslationX(-maxTranslateOffsetX * offsetRate);
//ViewCompat.setElevation(view, 0.0f);
}
ViewCompat.setElevation(view, scaleFactor);
}
/**
* Dp to pixel conversion
*/
private int dp2px(Context context, float dipValue) {
float m = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * m + 0.5f);
}
}
PagerAdapter
public class MyPagerAdapter extends PagerAdapter{
Context context;
int adapterType;
ArrayList<NearbyDataProvider> arrayList = new ArrayList<>();
public MyPagerAdapter(Context context,ArrayList<NearbyDataProvider> arrayList, int adapterType) {
this.context = context;
this.arrayList = arrayList;
this.adapterType=adapterType;
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
View view = LayoutInflater.from(context).inflate(R.layout.item_cover, null);
try {
NearbyDataProvider nearbyDataProvider = arrayList.get(position);
LinearLayout linMain = (LinearLayout) view.findViewById(R.id.linMain);
RoundedImageView imageCover = (RoundedImageView) view.findViewById(R.id.imageCover);
CustomTextViewMedium customTextViewMedium = (CustomTextViewMedium)view.findViewById(R.id.imageTitle);
CustomTextViewMedium customTextViewMedium1 =(CustomTextViewMedium)view.findViewById(R.id.imageContent);
linMain.setTag(position);
switch (adapterType)
{
case NearbyFragment.ADAPTER_TYPE_TOP:
break;
case NearbyFragment.ADAPTER_TYPE_BOTTOM:
linMain.setBackgroundResource(0);
break;
}
GlideApp.with(context)
.load(arrayList.get(position).getImage())
.into(imageCover);
customTextViewMedium.setText(nearbyDataProvider.getPlace());
container.addView(view);
} catch (Exception e) {
e.printStackTrace();
}
return view;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return (view == object);
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((View) object);
}
}

parent.getMeasuredWidth() and parent.getMeasuredHeight() return 0 in ImageAdapter for GridView

I have 6 drawable images. I put this images in a GridView in 2x3 if it's portraite and 3x2 if it's landscape, but i have a problem: if i try to put measures based on parent.getMeasuredWidth() and parent.getMeasuredHeight();
first drawable have always 0 as width and hight;
From LOG:
w: 0 h:0
Code ImageAdapter:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {mContext = c;}
public int getCount() {return mThumbIds.length;}
public Object getItem(int position) {return null;}
public long getItemId(int position) {return 0;}
public View getView(int position, View convertView, final ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
int width = parent.getMeasuredWidth();
int height = parent.getMeasuredHeight();
int orientation = parent.getResources().getConfiguration().orientation;
int vh,vo;
if(orientation == 1){
vh = width/2;
vo = height/3;
} else {
vh = (width/3);
vo = (height/2);
}
Log.e(TAG,"w: "+vh+" h:"+vo);
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(vh, vo));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(0, 0, 0, 0);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.gradient_bg_t1,
R.drawable.gradient_bg_t2,
R.drawable.gradient_bg_t4,
R.drawable.gradient_bg_t5,
R.drawable.gradient_bg_t6,
R.drawable.gradient_bg_t3
};
}
Code MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
}
});
}
Thank you.
it returns zero because the parent view isnt drawn yet. you can post your code to the parent view so it runs after parent view was drawn.
use below code:
parent.post(new Runnable() {
#Override
public void run() {
int w = parent.getMeasuredWidth();
int h = parent.getMeasuredHeight();
...
}
});
I already tried the code of #Amir Ziarati in ImageAdapter (found it in StackOverflow), but i can't get the values out of scope.
After i drink a little coffee i changed the code a litle:
I created in ImageAdapter 2 new int variable w,h for width and height:
private Context mContext;
private int w,h;
public ImageAdapter(Context c,int width,int height) {
mContext = c;
w = width;
h = height;
}
and in MainActivity:
gridview = (GridView) findViewById(R.id.gridview);
gridview.post(new Runnable() {
#Override
public void run() {
int w = gridview.getMeasuredWidth();
int h = gridview.getMeasuredHeight();
gridview.setAdapter(new ImageAdapter(MainActivity.this,w,h));
}
});
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
}
});
And it's working.

Background color or Images shuffling on scrolling in recyclerview?

I am wondering that my images and color of layouts shuffling when i scrolls downwards or upwards, I created cardview using recyclerview. and set an image(changes color on click like to know if its user's favourite item) and setbackgroundcolor(randomly chossen) to the parent layout to make cardview attractive. but when i scrolls
1. the image that image changes position,
2. the layout background changes color automatically.
I am posting my adapter's code here.
public class TOAdapter extends RecyclerView.Adapter<TOAdapter.ViewHolder> {
JSONArray jsonArray;
private String title;
private String image;
private ImageLoader imageLoader;
private String subtitle;
private String subti;
private Context context;
private ImageView clip;
public TOAdapter(JSONArray jsonArray) {
this.jsonArray = jsonArray;
}
// Create new views (invoked by the layout manager)
#Override
public TOAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.top_twenty_list, parent, false);
final ViewHolder viewHolder = new ViewHolder(itemLayoutView);
final Random random = new Random(System.currentTimeMillis());// We add 155 since we want at least 155 in each channel.// Then we add to it a random number between 0 and 100.
int r = 155 + random.nextInt(101);
int g = 155 + random.nextInt(101);
int b = 155 + random.nextInt(101);
int color = Color.rgb(r, g, b);
viewHolder.frame.setBackgroundColor(color);
viewHolder.layer.setBackgroundColor(color);
clip = (ImageView) itemLayoutView.findViewById(R.id.ic_clip);
clip.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int iColor = Color.parseColor("#0000FF");
int red = (iColor & 0xFF0000) / 0xFFFF;
int green = (iColor & 0xFF00) / 0xFF;
int blue = iColor & 0xFF;
float[] matrix = {0, 0, 0, 0, red
, 0, 0, 0, 0, green
, 0, 0, 0, 0, blue
, 0, 0, 0, 1, 0};
ColorFilter colorFilter = new ColorMatrixColorFilter(matrix);
clip.setColorFilter(colorFilter);
}
});
return viewHolder;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder viewHolder, int position) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
// myTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/RobotoCondensedBoldItalic.ttf");
try {
JSONObject obj = jsonArray.getJSONObject(position);
title = obj.getString("title");
image = obj.getString("brand_logo");
subtitle = obj.getString("sub_title");
} catch (JSONException e) {
e.printStackTrace();
}
viewHolder.txtViewTitle.setText(subtitle);
viewHolder.subtitle.setText(title);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
String full_Url = "http://mycompany/assets/new" + image;
viewHolder.thumbnail.setImageUrl(full_Url, imageLoader);
viewHolder.btn_get_deal.setTag(position);
viewHolder.btn_get_deal.setOnClickListener(new View.OnClickListener() {
public JSONObject obj;
public ArrayList<String> offerlist = new ArrayList();
#Override
public void onClick(View view) {
Intent offerpage = new Intent(AppController.getInstance().getApplicationContext(), OfferDetails.class);
Integer pos = (Integer) view.getTag();
try {
obj = jsonArray.getJSONObject(pos);
offerpage.putExtra("jsonObj", obj.toString());
} catch (JSONException e) {
e.printStackTrace();
}
//offerpage.getParcelableArrayListExtra(offerlist);
offerpage.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
AppController.getInstance().getApplicationContext().startActivity(offerpage);
}
});
//viewHolder.txtViewTitle.setTypeface(myTypeface);
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {
private final NetworkImageView thumbnail;
private final RelativeLayout frame;
private final RelativeLayout layer;
public TextView txtViewTitle;
public TextView subtitle;
public ImageView clip;
public CardView btn_get_deal;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.txttitle_toptwenty);
subtitle = (TextView) itemLayoutView.findViewById(R.id.sub_title_toptwenty);
thumbnail = (NetworkImageView) itemLayoutView.findViewById(R.id.thumbnail_topwenty);
frame = (RelativeLayout) itemLayoutView.findViewById(R.id.frame);
layer = (RelativeLayout) itemLayoutView.findViewById(R.id.layer);
btn_get_deal = (CardView) itemLayoutView.findViewById(R.id.card_view);
}
}
// Return the size of your itemsData (invoked by the layout manager)
#Override
public int getItemCount() {
return jsonArray.length();
}
}
I have created a working example of what you are trying to accomplish. The source of the errors you experience is mostly that you don't understand view recycling. I am not going to explain the whole thing to you now, but anyway here is the example:
For the example I used this layout for each row:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="#+id/background"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
I used this model:
public class ExampleModel {
private final int mColor;
private final String mText;
public ExampleModel(int color, String text) {
mColor = color;
mText = text;
}
public int getColor() {
return mColor;
}
public String getText() {
return mText;
}
}
And this view holder:
public class ExampleViewHolder extends RecyclerView.ViewHolder {
private final FrameLayout mBackground;
private final TextView mTextView;
public ExampleViewHolder(View itemView) {
super(itemView);
mBackground = (FrameLayout) itemView.findViewById(R.id.background);
mTextView = (TextView) itemView.findViewById(R.id.textView);
}
public void bind(ExampleModel model) {
mBackground.setBackgroundColor(model.getColor());
mTextView.setText(model.getText());
}
}
As you can see nothing special, the Adapter implementation is equally simple:
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final LayoutInflater mInflater;
private final List<ExampleModel> mModels;
public ExampleAdapter(Context context, List<ExampleModel> models) {
mInflater = LayoutInflater.from(context);
mModels = models;
}
#Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View itemView = mInflater.inflate(R.layout.item_example, parent, false);
return new ExampleViewHolder(itemView);
}
#Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mModels.get(position);
holder.bind(model);
}
#Override
public int getItemCount() {
return mModels.size();
}
}
And you use the whole thing like this:
final Random mRandom = new Random(System.currentTimeMillis());
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
final List<ExampleModel> models = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final int randomColor = generateRandomPastelColor();
models.add(new ExampleModel(randomColor, String.valueOf(i)));
}
final ExampleAdapter adapter = new ExampleAdapter(getActivity(), models);
recyclerView.setAdapter(adapter);
}
public int generateRandomPastelColor() {
final int baseColor = Color.WHITE;
final int red = (Color.red(baseColor) + mRandom.nextInt(256)) / 2;
final int green = (Color.green(baseColor) + mRandom.nextInt(256)) / 2;
final int blue = (Color.blue(baseColor) + mRandom.nextInt(256)) / 2;
return Color.rgb(red, green, blue);
}
This should do what you are looking for and you can use it as an example of how to implement your Adapter.
I got the same problem ,when i used the radioButton in my listView row, I solved it. As in every scrolling the Cache is cleared, you have to store the changed data in every row. just check my code
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
// if(position==0)
// Toast.makeText(context, ""+QuestionViewPageAdapter.mRadioGroupData, Toast.LENGTH_SHORT).show();
final ViewHolder viewHolder;
View row=convertView;
radioButton=new RadioButton[Integer.parseInt(mNoOfCategoryGreading)];
LayoutInflater inflater =LayoutInflater.from(context);//(LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.question_row, parent, false);
viewHolder=new ViewHolder();
viewHolder.tv_qContent=(TextView)row.findViewById(R.id.tv_question);
viewHolder.rg=(RadioGroup)row.findViewById(R.id.rgrp);
for(int i=0;i<Integer.parseInt(mNoOfCategoryGreading);i++)
{
radioButton[i]=new RadioButton(context);
radioButton[i].setLayoutParams(new RadioGroup.LayoutParams(0, LayoutParams.WRAP_CONTENT,1f));
//1f for layout_weight="1"
radioButton[i].setId(i);
radioButton[i].setText(""+(i+1));
viewHolder.rg.addView(radioButton[i]);
}
row.setTag(viewHolder);
for(int i=0;i<QuestionViewPageAdapter.mRadioGroupData.size();i++){
int p=Integer.parseInt(""+QuestionViewPageAdapter.mRadioGroupData.get(i).get("position"));
String id=QuestionViewPageAdapter.mRadioGroupData.get(i).get("Id");
if(p!=-1 && id.equals(""+data.get(position).get(AppData.question_Set_category_QuestionID)))
{//radioButton[p].setSelected(true);
viewHolder.rg.check(p-1);}
//Toast.makeText(context, "Yes "+p, Toast.LENGTH_LONG).show();}
}
viewHolder.tv_qContent.setText((position+1)+". "+data.get(position).get(AppData.question_Set_category_QuestionContent));
viewHolder.tv_qContent.setTypeface(typeface_muso_regular300);
viewHolder.rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
String s=data.get(position).get(AppData.question_Set_category_QuestionID);
isAvailabel(s);
int radioButtonID = viewHolder.rg.getCheckedRadioButtonId();
View radioButton = viewHolder.rg.findViewById(radioButtonID);
int idx = viewHolder.rg.indexOfChild(radioButton);
HashMap<String, String> map=new HashMap<String, String>();
map.put("position", ""+(idx+1));
map.put("Id", ""+data.get(position).get(AppData.question_Set_category_QuestionID));
map.put("CategoryId", ""+mCategoryId);
QuestionViewPageAdapter.mRadioGroupData.add(map);
}
});
return row;
}
private void isAvailabel(String qId){
for(int i=0;i<QuestionViewPageAdapter.mRadioGroupData.size();i++){
if(qId.equals(QuestionViewPageAdapter.mRadioGroupData.get(i).get("Id"))){
position=i;
QuestionViewPageAdapter.mRadioGroupData.remove(i);
}
}
}
class ViewHolder {
TextView tv_qContent ,tv_1,tv_2,tv_3;
RadioGroup rg;
RadioButton rBtn1,rBtn2,rBtn3,rBtn4,rBtn5;
}
After days of struggle and headache, i have found a very simple solution.
In your adapter you just need to override 2 methods.
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
Helped me resolve the shuffling issue of recycler view.
In my case overriding getItemId and setting sethasStableIds to true solved the shuffling issue.
in adapter:
#Override
public long getItemId(int position) {
Object listItem = feeds.get(position);
return listItem.hashCode();
}
in main activity/fragment :
adapter = new FeedAdapter(feeds, getContext());
adapter.setHasStableIds(true);

GridView OutOfMemory Bitmap

So i have the problem that my app is crashing because of OutOfMemory.
There are really good and a lot of solutions first my Adaptercode:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
// Keep all Images in array
public Integer[] mThumbIds = {
R.drawable.accidentally_open_internet_explorer,
R.drawable.angry_shaking, R.drawable.are_you_fucking_kidding_me,
R.drawable.angry_with_pc,
R.drawable.sample_7, R.drawable.awkward_moment,
R.drawable.awkward_moment,
R.drawable.beer_guy,
R.drawable.beng,
R.drawable.accidentally_open_internet_explorer, R.drawable.boobs,
R.drawable.big_smile, R.drawable.cereal_guy,
R.drawable.challenge_accepted_drunk, R.drawable.challenge_accepted,
R.drawable.bad_pokerface, R.drawable.challenge_considered,
R.drawable.challenge_denied, R.drawable.challenge_failed,
R.drawable.classic_rage, R.drawable.one_does_not_simply,
R.drawable.computer_stare, R.drawable.computer_slice,
R.drawable.concentrated, R.drawable.concentrate,
R.drawable.concentrated_teeth, R.drawable.cry_pc,
R.drawable.dat_ass, R.drawable.desk_flip,
R.drawable.double_facepalm, R.drawable.duck_yeah,
R.drawable.fap, R.drawable.fap_accepted,
R.drawable.fap_gentleman, R.drawable.feels_good_man,
R.drawable.forever_a_gamer, R.drawable.forever_alone_clean,
R.drawable.forever_alone_sad, R.drawable.forever_alone_together,
R.drawable.fuck_that_bitch_yao_pff, R.drawable.fuck_that_yao_ming,
R.drawable.fuck_yeah, R.drawable.fuck_yeah_close_enough,
R.drawable.gentleman_troll, R.drawable.happy_smoking,
R.drawable.haters_gonna_hate, R.drawable.if_you_know_what_i_mean_mr_bean,
R.drawable.if_you_know_what_i_mean_mr_bean_blank, R.drawable.if_you_know_what_i_mean_mr_bean_blank,
R.drawable.impossibru, R.drawable.indeed,
R.drawable.jesus, R.drawable.keyboard_break,
R.drawable.knowthatfeel, R.drawable.like_a_sir,
R.drawable.long_long_neck_surprise, R.drawable.look_from_bottom,
R.drawable.me_gusta, R.drawable.me_gusta_creepy,
R.drawable.me_gusta_makeup, R.drawable.not_sure_if_gusta,
R.drawable.now_kiss, R.drawable.one_does_not_simply,
R.drawable.sample_1, R.drawable.sample_4,
R.drawable.sample_7, R.drawable.sample_12,
R.drawable.sample_13, R.drawable.today_is_monday,
R.drawable.trees_smile, R.drawable.trees_stoned,
R.drawable.trees_stoned_exhale, R.drawable.trees_stoned_inhale,
R.drawable.wonka, R.drawable.y_u_no,
R.drawable.yea_science, R.drawable.you_are_the_man
};
// Constructor
public ImageAdapter(Context c){
mContext = c;
}
#Override
public int getCount() {
return mThumbIds.length;
}
#Override
public Object getItem(int position) {
return mThumbIds[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
.....
Then i tried 2 Solutions:
First:
public View getView(int position, View convertView, ViewGroup parent) {
//This actually is a bad solution, because every time convertView is reused, you will still initialize new ImageView, which is wrong
//ImageView imageView = new ImageView(this.mContext);
//new BitmapWorkerTask(imageView).execute(Tattoos[position]);
//return imageView;
//Better solution
ImageView imageView = null;
if (convertView == null) {
imageView = new ImageView(this.mContext);
new BitmapWorkerTask(imageView).execute(Tattoos[position]);
//create new ImageView if it is not present and populate it with some image
} else {
imageView = (ImageView) convertView;
//re-use ImageView that already exists in memory
}
return imageView;
}
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(ImageAdapter.this.mContext.getResources(), data, 100, 100);
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(100, 70));
}
}
}
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
But my problem is that the pictures are on each other so they lie on top of each other why???
2 Solution:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
// TextView txt = new TextView(mContext);
imageView.setImageResource(mThumbIds[position]);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(
new GridView.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
Bitmap m_d = BitmapFactory.decodeResource(mContext.getResources(),
mThumbIds[position]);
if (m_d != null)
{
Bitmap resizedBitmap = Bitmap.createScaledBitmap(m_d, 205, 205, true);
imageView.setImageBitmap(resizedBitmap);
};
return imageView;}}
But that´s laggy as hell why???
thank you dudes for helping!!!
Whenever you create a Bitmap using BitmapFactory, you must be sure to call .recycle() on that bitmap instance when you're done with it, or else you'll very quickly run out of memory.
Your first solution is closer to correct because you need to recycle those convertView objects, so just make sure that your convertView exists, and that you've recycled any bitmaps that it might already be holding onto before you create new ones.
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = null;
if (convertView == null) {
imageView = new ImageView(this.mContext);
} else {
imageView = (ImageView) convertView;
}
// clean up your old bitmap first, if there is one.
if(imageView.getDrawable() instanceof BitmapDrawable){
BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
imageView.setDrawable(null);
if(bd.getBitmap() != null){
bd.getBitmap().recycle();
}
bd = null;
}
new BitmapWorkerTask(imageView).execute(Tattoos[position]);
return imageView;
}

Trying to fix my code but I keep failing :(

I've got this code that makes the image turn into a circle using a ListView. But as seen in the image, it dies when it goes to the end of the photo (the last few pixels are carried on when there not supposed to).
I don't want the photo to take up the whole page, just the size of the photo. Here's the code and XML:
Stream item xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</RelativeLayout>
activity stream xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:divider="#null"
android:dividerHeight="0px"
android:drawSelectorOnTop="true"
tools:context=".StreamActivity" />
main code:
public class StreamActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream);
StreamAdapter adapter = new StreamAdapter(this);
((ListView) findViewById(R.id.main_list)).setAdapter(adapter);
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
}
class StreamItem {
final Bitmap mBitmap;
StreamItem(Context c, int resid, String line1, String line2) {
mBitmap = BitmapFactory.decodeResource(c.getResources(), resid);
}
}
class StreamDrawable extends Drawable {
private static final boolean USE_VIGNETTE = true;
private final float mCornerRadius;
private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;
StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
mCornerRadius = cornerRadius;
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
if (USE_VIGNETTE) {
RadialGradient vignette = new RadialGradient(
mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
Shader.TileMode.CLAMP);
Matrix oval = new Matrix();
oval.setScale(1.0f, 0.7f);
vignette.setLocalMatrix(oval);
mPaint.setShader(
new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
}
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
class StreamAdapter extends ArrayAdapter<StreamItem> {
private static final int CORNER_RADIUS =100; // dips
private static final int MARGIN = 1; // dips
private final int mCornerRadius;
private final int mMargin;
private final LayoutInflater mInflater;
public StreamAdapter(Context context) {
super(context, 0);
final float density = context.getResources().getDisplayMetrics().density;
mCornerRadius = (int) (CORNER_RADIUS * density + 0.5f);
mMargin = (int) (MARGIN * density + 0.5f);
mInflater = LayoutInflater.from(getContext());
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewGroup view = null;
if (convertView == null) {
view = (ViewGroup) mInflater.inflate(R.layout.stream_item, parent, false);
} else {
view = (ViewGroup) convertView;
}
StreamItem item = getItem(position);
StreamDrawable d = new StreamDrawable(item.mBitmap, mCornerRadius, mMargin);
view.setBackgroundDrawable(d);
int w = item.mBitmap.getWidth();
int h = item.mBitmap.getHeight();
float ratio = w / (float) h;
LayoutParams lp = view.getLayoutParams();
lp.width = getContext().getResources().getDisplayMetrics().widthPixels;
lp.height = (int) (lp.width / ratio);
return view;
}
}
}

Categories