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;
}
}
}
Related
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);
}
}
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();
}
}
I am trying to draw circles in the canvas. Currently I can do it on button click, but I also need to do the same when the Fragment is loaded. Below is my Fragment code.
public class StepTwentyOneFragment extends Fragment {
private CanvasView customCanvas;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.step21_fragment, container, false);
customCanvas=(CanvasView)v.findViewById(R.id.signature_canvas);
final Button button1=(Button)v.findViewById(R.id.step18button1);
float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
customCanvas.drawCircle(radius);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v.getId()==R.id.step18button1){
float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
customCanvas.drawCircle(radius);
Log.d("An_Width", "" + customCanvas.getCanvasWidth());
Log.d("An_Height" ,""+ customCanvas.getCanvasHeight());
v.setBackgroundResource(R.drawable.button_border_5);
button1.setTextColor(Color.WHITE);;
}
}
});
return v;
}
public static StepTwentyOneFragment newInstance() {
StepTwentyOneFragment f = new StepTwentyOneFragment();
Bundle b = new Bundle();
f.setArguments(b);
return f;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
Activity a = getActivity();
if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Below is my Canvas code
public class CanvasView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
private int canvasHeight, canvasWidth;
private float radius;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
mPath = new Path();
mPaint = new Paint();
mPaint.setStrokeWidth(3);
mPaint.setColor(Color.CYAN);
}
// override onDraw
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas=canvas;
Drawable d = getResources().getDrawable(R.drawable.circle_1);
canvasHeight= canvas.getHeight();
canvasWidth= canvas.getWidth();
Log.d("Height - "," / "+canvas.getHeight());
Log.d("Width - "," / "+canvas.getWidth());
// DisplayMetrics displaymetrics = new DisplayMetrics();
// ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
// int height = displaymetrics.heightPixels;
// int width = displaymetrics.widthPixels;
float h=canvasHeight/2;
float w=canvasWidth/2;
d.setBounds(0, 0, canvasWidth, canvasHeight);
d.draw(canvas);
canvas.drawCircle(w, h, radius, mPaint);
}
public void clear2(){
radius=0;
//important. Refreshes the view by calling onDraw function
invalidate();
}
public void drawCircle(float radius1) {
radius=radius1;
//important. Refreshes the view by calling onDraw function
invalidate();
}
public int getCanvasHeight()
{
return canvasHeight;
}
public int getCanvasWidth()
{
return canvasWidth;
}
}
Now my problem is , cannot draw a circle with loading of the fragment . It means the circle cannot draw without button action . But I want to do it when the fragment is loading .
Have any ideas ?
Thank you.
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);
I am starting to think that short of OpenGL I can't drag around a simple view. Seriously, I have read through 10-15 tutorials for dragging views, and EVERY tutorial shows you how to drag a drawable WITHIN a view, or drag an image INSIDE of an imageview (by matrix transformations). But NONE of the tutorials tell you how you can drag around a simple view in a superview. Its really that simple. I have a superview, I add lets say 10 subviews. Whatever subview my finger is touching drags around. I made an app for iOS http://www.facebook.com/MakeASnowman (hits the app store any day) and am trying to build it for Android. But there is no easy way to do things that are so simple in iOS (two finger rotate, drag around views, etc). This is what I want: I have a custom view that draws an image to its canvas. I then instantiate one or more of those custom views onto a "superview". I can drag/manipulate those views (meaning im not translating the drawables within those views, but the actual views themselves).
Here is my code that has the right manipulations, except it performs them of the drawable within the view:
package com.spentaklabs.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class MAView extends View
{
Drawable image;
private String imgName;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public MAView(Context context)
{
super(context);
}
public MAView(Context context,String imgName)
{
this(context);
this.imgName = imgName;
image = context.getResources().getDrawable(R.drawable.hatshairears0);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
public MAView(Context context, AttributeSet attrs, int defStyle)
{
super(context,attrs,defStyle);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.save();
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
image.draw(canvas);
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
{
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE:
{
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP:
{
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL:
{
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP:
{
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId)
{
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
Here is some code that would let you drag a View anywhere you want on the screen...
package com.matthieu;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.FrameLayout.LayoutParams;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.util.ArrayList;
import java.util.Arrays;
public class DragActivity extends Activity implements View.OnTouchListener, AdapterView.OnItemLongClickListener
{
private static final String TAG="DragActivity";
private static final int NOT_DRAGGING = 0;
private static final int DRAGGING = 1;
private int state=NOT_DRAGGING;
private ImageView draggable =null;
private int dragged_position;
float current_x, current_y;
int current_icon = R.drawable.notepad;
private ArrayList<String> names = new ArrayList<String>(Arrays.asList("Matt", "Xiaohui", "Yong", "Hunt", "Andy", "Ivy", "Guanglong", "Zeyan", "Yanxia",
"Chris", "Mark", "Matthieu"));
private ArrayList<Integer> icons = new ArrayList<Integer>(Arrays.asList( R.drawable.glasses, R.drawable.monkey, R.drawable.normal, R.drawable.smile, R.drawable.wink));
private ArrayList<Integer> matching;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupListContent();
ListView list = (ListView) findViewById(R.id.main_list);
list.setAdapter(new DragListAdapter());
list.setOnItemLongClickListener(this);
list.setOnTouchListener(this);
ImageView image = (ImageView) findViewById(R.id.main_image);
image.setImageResource(current_icon);
}
private void setupListContent() {
matching = new ArrayList<Integer>();
for (int i=0; i<names.size(); i++) {
matching.add((int) (icons.size() * Math.random()));
}
}
#SuppressWarnings("unchecked")
private class DragListAdapter extends ArrayAdapter {
public DragListAdapter() {
super(DragActivity.this, R.layout.list_item, names);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.list_item, parent, false);
}
row.setDrawingCacheEnabled(true);
TextView name = (TextView) row.findViewById(R.id.item_text);
ImageView icon = (ImageView) row.findViewById(R.id.item_icon);
name.setText(names.get(position));
icon.setImageResource(icons.get(matching.get(position)));
return row;
}
}
private boolean checkOnDropIcon(MotionEvent me) {
ImageView drop_icon = (ImageView) findViewById(R.id.main_image);
Rect icon_rect = new Rect();
drop_icon.getGlobalVisibleRect(icon_rect);
Log.d(TAG, "icon at " + icon_rect.left + "<- ->" + icon_rect.right + ", " +
icon_rect.top + " ^ v" + icon_rect.bottom);
if ((me.getRawX()<icon_rect.left) || (me.getRawX()>icon_rect.right) ||
(me.getRawY()<icon_rect.top) || (me.getRawY()>icon_rect.bottom)) {
return false;
}
else {
return true;
}
}
private void checkOnDrop(MotionEvent me) {
boolean onDropIcon = checkOnDropIcon(me);
ImageView image = (ImageView) findViewById(R.id.main_image);
if ((onDropIcon) && (current_icon==R.drawable.notepad)) {
current_icon = R.drawable.exit;
image.setImageResource(current_icon);
image.invalidate();
return;
}
if ((!onDropIcon) && (current_icon==R.drawable.exit)) {
current_icon = R.drawable.notepad;
image.setImageResource(current_icon);
image.invalidate();
return;
}
}
public boolean onTouch(View view, MotionEvent me) {
if (state == NOT_DRAGGING) {
// get the position of the touch so we know where to place the dragging item if it is a long press
current_x = me.getRawX();
current_y = me.getRawY();
return false;
}
else {
FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space);
if (me.getAction()==MotionEvent.ACTION_UP) {
frame.removeAllViews();
draggable=null;
frame.setVisibility(View.GONE);
state=NOT_DRAGGING;
// check if we dropped a name
if (checkOnDropIcon(me)) {
names.remove(dragged_position);
matching.remove(dragged_position);
ListView list = (ListView) findViewById(R.id.main_list);
DragListAdapter adapter = (DragListAdapter) list.getAdapter();
adapter.notifyDataSetChanged();
}
// restore the icon
ImageView image = (ImageView) findViewById(R.id.main_image);
current_icon = R.drawable.notepad;
image.setImageResource(current_icon);
image.invalidate();
}
if (me.getAction()==MotionEvent.ACTION_MOVE) {
int frame_position[] = new int[2];
frame.getLocationOnScreen(frame_position);
draggable.setPadding(
(int) me.getRawX()-frame_position[0]-(draggable.getDrawable().getIntrinsicWidth()/2),
(int) me.getRawY()-frame_position[1]-(draggable.getDrawable().getIntrinsicHeight()/2),
0, 0);
draggable.invalidate();
checkOnDrop(me);
}
return true;
}
}
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
if (state == DRAGGING) {
Log.d(TAG, "already have an object moving... ?");
return false;
}
FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space);
int frame_position[] = new int[2];
frame.getLocationOnScreen(frame_position);
// setup everything for dragging
state = DRAGGING;
dragged_position = i;
draggable = new ImageView(this);
Bitmap bm = view.getDrawingCache();
draggable.setImageBitmap(bm);
draggable.setAlpha(150);
draggable.setScaleType(ImageView.ScaleType.CENTER);
draggable.setDrawingCacheEnabled(true);
draggable.setPadding((int) current_x-frame_position[0]-(bm.getWidth()/2), (int) current_y-frame_position[1]-(bm.getHeight()/2), 0, 0);
frame.setVisibility(View.VISIBLE);
frame.addView(draggable, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
return true;
}
}
Here is the main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="#+id/main_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<ImageView
android:id="#+id/main_image"
android:layout_width="fill_parent"
android:layout_height="32sp"
/>
</LinearLayout>
<FrameLayout
android:id="#+id/drag_space"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"/>
</FrameLayout>
And the list_item.xml
<?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="horizontal">
<ImageView
android:id="#+id/item_icon"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_margin="3sp"/>
<TextView
android:id="#+id/item_text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
Hope that helps.