ItemTouchHelper - Can't scroll RecyclerView, Swipe doesn't work - java

Well, at the beginning of the Implementation of ItemTouchHelper, I chose to use only the Swipe function from it. Everything worked - with the help of Swipe I could delete items in RecyclerView etc. But then I thought I'd add up-down movement so that the user could change the order in which the item appears in the list.
Then the problems began - the user can change the order in which items are displayed, but can no longer:
Scroll RecyclerView (even if changing item up-down position is disabled)
Swipe functions have stopped working - onSwiped does not return the side (ItemTouchHelper.LEFT, ItemTouchHelper.RIGHT) in which the item was swiped
I changed the View on which is trigger OnStartDragListener from _view to just ImageView and I can scroll now but there are now other problems:
Swipe works on that ImageView too - I want to be able to swipe item whereever user click on item (_view)
Swipe functions still doesn't work - onSwiped does not return the side (ItemTouchHelper.LEFT, ItemTouchHelper.RIGHT) in which the item was swiped
Video how the problem looks
FIXED
I Changed
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags =
mDraggable
? ItemTouchHelper.UP
| ItemTouchHelper.DOWN
| ItemTouchHelper.START
| ItemTouchHelper.END
: 0;
if (mDraggable) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
} else {
dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
}
return makeMovementFlags(dragFlags, 0);
}
To
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = 0;
int swipeFlags = 0;
if (mDraggable) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
} else {
swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(0, swipeFlags);
}
}
RecyclerView Adapter:
package tw.codeassist.plus;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import tw.codeassist.plus.SwipeToDeleteCallback;
public class CodeAdapter extends RecyclerView.Adapter<CodeAdapter.ViewHolder> implements SwipeToDeleteCallback.ItemTouchHelperAdapter {
ArrayList<HashMap<String, Object>> _data;
Context context;
SharedPreferences snippets;
OnItemClickListener mItemClickListener;
private static final int TYPE_ITEM = 0;
//private final LayoutInflater mInflater;
private final tw.codeassist.plus.SwipeToDeleteCallback.OnStartDragListener mDragStartListener;
public CodeAdapter(
android.content.Context appCont,
ArrayList<HashMap<String, Object>> _arr,
tw.codeassist.plus.SwipeToDeleteCallback.OnStartDragListener dragListner) {
_data = _arr;
context = appCont;
mDragStartListener = dragListner;
snippets = context.getSharedPreferences("snippets", Activity.MODE_PRIVATE);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater _inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View _v = _inflater.inflate(R.layout.codesnippets, null);
RecyclerView.LayoutParams _lp =
new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
_v.setLayoutParams(_lp);
return new ViewHolder(_v);
}
#Override
public void onBindViewHolder(ViewHolder _holder, final int _position) {
View _view = _holder.itemView;
final androidx.cardview.widget.CardView cardview1 = _view.findViewById(R.id.cardview1);
final LinearLayout main_linear = (LinearLayout) _view.findViewById(R.id.main_linear);
final LinearLayout color_linear = (LinearLayout) _view.findViewById(R.id.color_linear);
final LinearLayout linear3 = (LinearLayout) _view.findViewById(R.id.linear3);
final TextView title_txt = (TextView) _view.findViewById(R.id.title_txt);
final TextView desc_txt = (TextView) _view.findViewById(R.id.desc_txt);
title_txt.setTypeface(
Typeface.createFromAsset(context.getAssets(), "fonts/product_sans_bold.ttf"), 0);
desc_txt.setTypeface(
Typeface.createFromAsset(context.getAssets(), "fonts/product_sans_regular.ttf"), 0);
title_txt.setText(_data.get((int) _position).get("Title").toString());
desc_txt.setText(_data.get((int) _position).get("Description").toString());
color_linear.setBackgroundColor(
Color.parseColor(_data.get((int) _position).get("Color").toString()));
RecyclerView.LayoutParams _lp =
new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
_view.setLayoutParams(_lp);
_view.setOnTouchListener(
new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(_holder);
}
return false;
}
});
}
#Override
public int getItemCount() {
return _data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, ItemTouchHelperViewHolder {
public ViewHolder(View v) {
super(v);
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, getAdapterPosition());
}
}
#Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
#Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
}
#Override
public void onItemDismiss(int position) {
_data.remove(position);
notifyItemRemoved(position);
}
#Override
public boolean onItemMove(int fromPosition, int toPosition) {
Log.d("onItemMove", "Log position" + fromPosition + " " + toPosition);
if (fromPosition < _data.size() && toPosition < _data.size()) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(_data, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(_data, i, i - 1);
}
}
Collections.reverse(_data);
snippets.edit().putString("CodeSnippets", new Gson().toJson(this._data)).commit();
notifyItemMoved(fromPosition, toPosition);
}
return true;
}
public void showMessage(String message) {
Toast.makeText((Activity) context, message, Toast.LENGTH_SHORT).show();
}
public void updateList(ArrayList<HashMap<String, Object>> list) {
_data = list;
notifyDataSetChanged();
}
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public void removeAt(int position) {
_data.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, _data.size());
}
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
}
ItemTouchHelper Callback
package tw.codeassist.plus;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.google.gson.Gson;
public class SwipeToDeleteCallback extends ItemTouchHelper.Callback {
private CodeAdapter mAdapter;
Context context;
private SharedPreferences snippets;
private Drawable icon;
private Drawable icon2;
private GradientDrawable background; // ColorDrawable Before
boolean mDraggable = true;
public SwipeToDeleteCallback(Context con, CodeAdapter adapter, boolean canEdit) {
mAdapter = adapter;
context = con;
setDraggable(canEdit);
DisplayMetrics dm = new DisplayMetrics();
((Activity) con).getWindowManager().getDefaultDisplay().getMetrics(dm);
float densityScale = dm.density;
// DELETE ICON
Drawable dr = con.getResources().getDrawable(R.drawable.ic_delete);
Bitmap bitmap = ((BitmapDrawable) dr).getBitmap();
icon =
new BitmapDrawable(
con.getResources(),
Bitmap.createScaledBitmap(
bitmap,
(int) (150 * densityScale / 3),
(int) (150 * densityScale / 3),
true));
// COPY ICON
Drawable dr2 = con.getResources().getDrawable(R.drawable.ic_copy);
Bitmap bitmap2 = ((BitmapDrawable) dr2).getBitmap();
icon2 =
new BitmapDrawable(
con.getResources(),
Bitmap.createScaledBitmap(
bitmap2,
(int) (200 * densityScale / 3),
(int) (200 * densityScale / 3),
true));
// TO INIT THE background
int startColor = Color.WHITE;
int endColor = Color.RED;
background =
new GradientDrawable(
GradientDrawable.Orientation.LEFT_RIGHT, new int[] {startColor, endColor});
background.setCornerRadius(20);
}
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags =
mDraggable
? ItemTouchHelper.UP
| ItemTouchHelper.DOWN
| ItemTouchHelper.START
| ItemTouchHelper.END
: 0;
if (mDraggable) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
} else {
dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
}
return makeMovementFlags(dragFlags, 0);
}
public void setDraggable(boolean value) {
mDraggable = value;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean onMove(
RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
if (mDraggable) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
} else {
return false;
}
}
void showMessage(String message) {
Toast.makeText(((Activity) context), message, Toast.LENGTH_SHORT).show();
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
showMessage(String.valueOf(direction));
if (direction == 8) { // RIGHT TO LEFT
// copy
VibrateNotify(200);
String getCode = mAdapter._data.get((int) position).get("Code").toString();
CharSequence code = getCode;
LinearLayout linearSnack =
(LinearLayout) ((FragmentActivity) context).findViewById(R.id.linear1);
((ClipboardManager) context.getSystemService(context.CLIPBOARD_SERVICE))
.setPrimaryClip(ClipData.newPlainText("", code));
com.google.android.material.snackbar.Snackbar.make(
context,
linearSnack,
"Code Copied!",
com.google.android.material.snackbar.Snackbar.LENGTH_LONG)
.setAction(
"",
new View.OnClickListener() {
#Override
public void onClick(View _view) {}
})
.show();
mAdapter.notifyItemChanged(position);
} else if (direction == 4) { // 4 = LEFT TO RIGHT
// delete
mAdapter.removeAt(position);
VibrateNotify(500);
snippets = context.getSharedPreferences("snippets", context.MODE_PRIVATE);
snippets.edit().putString("CodeSnippets", new Gson().toJson(mAdapter._data)).commit();
mAdapter.notifyItemRemoved(position);
}
}
public void VibrateNotify(long duration) {
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.EFFECT_DOUBLE_CLICK));
} else {
// deprecated in API 26
v.vibrate(duration);
}
}
#Override
public void onChildDraw(
Canvas c,
RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
float dX,
float dY,
int actionState,
boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
View itemView = viewHolder.itemView;
int backgroundCornerOffset = 15; // so background is behind the rounded corners of itemView
int alpha = 128;
int colorGreen = Color.parseColor("#FF0000FF");
icon.setAlpha(alpha);
icon2.setAlpha(alpha);
int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 3;
int iconTop = itemView.getTop() + (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
int iconBottom = iconTop + icon.getIntrinsicHeight();
if (dX > 0) { // Swiping to the right
int iconLeft = itemView.getLeft() + iconMargin; // icon.getIntrinsicWidth()
int iconRight = iconLeft + icon.getIntrinsicWidth(); // itemView.getLeft()
icon2.setBounds(iconLeft, iconTop, iconRight, iconBottom);
int START = 0xFF90A4AE;
int END = Color.TRANSPARENT;
background =
new GradientDrawable(
GradientDrawable.Orientation.LEFT_RIGHT, new int[] {START, END});
background.setCornerRadius(20);
background.setBounds(
itemView.getLeft(),
itemView.getTop(),
itemView.getLeft() + ((int) dX) + backgroundCornerOffset,
itemView.getBottom());
} else if (dX < 0) { // Swiping to the left
int iconLeft = itemView.getRight() - iconMargin - icon.getIntrinsicWidth();
int iconRight = itemView.getRight() - iconMargin;
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
int START = Color.TRANSPARENT;
int END = 0xFFE57373;
background =
new GradientDrawable(
GradientDrawable.Orientation.LEFT_RIGHT, new int[] {START, END});
background.setCornerRadius(20);
background.setBounds(
itemView.getRight() + ((int) dX) - backgroundCornerOffset,
itemView.getTop(),
itemView.getRight(),
itemView.getBottom());
} else { // view is unSwiped
icon.setBounds(0, 0, 0, 0);
icon2.setBounds(0, 0, 0, 0);
background.setBounds(0, 0, 0, 0);
}
background.setStroke(25, Color.TRANSPARENT);
// background.setPadding(0, paddingTop, 0, paddingBottom); //left, top, right, bottom
background.draw(c);
icon.draw(c);
icon2.draw(c);
}
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
public interface ItemTouchHelperAdapter {
boolean onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
}
Fragment where the RecyclerView is:
package tw.codeassist.plus;
import android.animation.*;
import android.app.*;
import android.app.Activity;
import android.content.*;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.*;
import android.graphics.*;
import android.graphics.Typeface;
import android.graphics.drawable.*;
import android.media.*;
import android.net.*;
import android.os.*;
import android.text.*;
import android.text.style.*;
import android.util.*;
import android.view.*;
import android.view.View;
import android.view.View.*;
import android.view.animation.*;
import android.webkit.*;
import android.widget.*;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.*;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.*;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.github.angads25.filepicker.*;
import com.github.dhaval2404.colorpicker.*;
import com.google.android.flexbox.*;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zip4j.*;
import io.github.rosemoe.sora.*;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.*;
import org.json.*;
public class TutorialsFragmentActivity extends Fragment
implements SwipeToDeleteCallback.OnStartDragListener {
private FloatingActionButton _fab;
private CodeAdapter codeAdapter;
private ArrayList<HashMap<String, Object>> dataToShow = new ArrayList<>();
public LinearLayout linear1;
private TextView textview1;
private TextView goneTxt;
private TextView editBttn;
private RecyclerView recyclerView;
private LinearLayout noCodesView;
TutorialsFragmentActivity tfa = this;
private SharedPreferences.OnSharedPreferenceChangeListener listener;
private Intent intent = new Intent();
private SharedPreferences snippets;
private SharedPreferences settings;
private ItemTouchHelper itemTouchHelper;
boolean isEditMode = false;
#NonNull
#Override
public View onCreateView(
#NonNull LayoutInflater _inflater,
#Nullable ViewGroup _container,
#Nullable Bundle _savedInstanceState) {
View _view = _inflater.inflate(R.layout.tutorials_fragment, _container, false);
initialize(_savedInstanceState, _view);
com.google.firebase.FirebaseApp.initializeApp(getContext());
initializeLogic();
return _view;
}
private void initialize(Bundle _savedInstanceState, View _view) {
_fab = _view.findViewById(R.id._fab);
settings = getContext().getSharedPreferences("settings", Activity.MODE_PRIVATE);
noCodesView = _view.findViewById(R.id.linearNoCodes);
linear1 = _view.findViewById(R.id.linear1);
goneTxt = _view.findViewById(R.id.txGone);
editBttn = _view.findViewById(R.id.edit);
textview1 = _view.findViewById(R.id.textview1);
recyclerView = _view.findViewById(R.id.recyclerView);
snippets = getContext().getSharedPreferences("snippets", Activity.MODE_PRIVATE);
listener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("CodeSnippets")) {
if (settings.getString("ShouldRefresh", "") == "true") {
itemTouchHelper.attachToRecyclerView(null);
dataToShow =
new Gson()
.fromJson(
snippets.getString("CodeSnippets", ""),
new TypeToken<
ArrayList<
HashMap<
String,
Object>>>() {}.getType());
Collections.reverse(dataToShow);
codeAdapter = new CodeAdapter(getContext(), dataToShow, tfa);
recyclerView.setAdapter(codeAdapter);
//recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
itemTouchHelper =
new ItemTouchHelper(
new SwipeToDeleteCallback(
getContext(), codeAdapter, false));
itemTouchHelper.attachToRecyclerView(recyclerView);
settings.edit().putString("ShouldRefresh", "false").commit();
} else {
}
}
}
};
snippets.registerOnSharedPreferenceChangeListener(listener);
goneTxt.setVisibility(View.INVISIBLE);
editBttn.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View _view) {
if (!isEditMode) {
isEditMode = true;
editBttn.setText("Close");
goneTxt.setText("Close");
} else {
isEditMode = false;
editBttn.setText("Edit");
goneTxt.setText("Edit");
}
itemTouchHelper.attachToRecyclerView(null);
itemTouchHelper =
new ItemTouchHelper(
new SwipeToDeleteCallback(
getContext(), codeAdapter, isEditMode));
itemTouchHelper.attachToRecyclerView(recyclerView);
}
});
_fab.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View _view) {
editBttn.setText("Edit");
goneTxt.setText("Edit");
isEditMode = false;
itemTouchHelper.attachToRecyclerView(null);
itemTouchHelper =
new ItemTouchHelper(
new SwipeToDeleteCallback(
getContext(), codeAdapter, isEditMode));
itemTouchHelper.attachToRecyclerView(recyclerView);
intent.setClass(
getContext().getApplicationContext(), AddSnippetActivity.class);
startActivity(intent);
}
});
}
#Override
public void onResume() {
}
#Override
public void onStart() {
super.onStart();
}
public void onPause() {
super.onPause();
}
private void initializeLogic() {
{
android.graphics.drawable.GradientDrawable SketchUi =
new android.graphics.drawable.GradientDrawable();
int clrs[] = {0xFFFFFFFF, 0xFFE0E0E0};
SketchUi =
new android.graphics.drawable.GradientDrawable(
android.graphics.drawable.GradientDrawable.Orientation.TOP_BOTTOM,
clrs);
linear1.setBackground(SketchUi);
}
noCodesView.setVisibility(View.GONE);
textview1.setTypeface(
Typeface.createFromAsset(getContext().getAssets(), "fonts/product_sans_bold.ttf"),
0);
dataToShow =
new Gson()
.fromJson(
snippets.getString("CodeSnippets", ""),
new TypeToken<ArrayList<HashMap<String, Object>>>() {}.getType());
Collections.reverse(dataToShow);
codeAdapter = new CodeAdapter(this.getContext(), dataToShow, this);
recyclerView.setAdapter(codeAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
itemTouchHelper =
new ItemTouchHelper(new SwipeToDeleteCallback(getContext(), codeAdapter, false));
itemTouchHelper.attachToRecyclerView(recyclerView);
removeScrollBar(recyclerView);
if (dataToShow.size() == 0) {
noCodesView.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
noCodesView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
}
public void removeScrollBar(View _view) {
_view.setVerticalScrollBarEnabled(false);
_view.setHorizontalScrollBarEnabled(false);
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
itemTouchHelper.startDrag(viewHolder);
}
}

FIXED
I Changed
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags =
mDraggable
? ItemTouchHelper.UP
| ItemTouchHelper.DOWN
| ItemTouchHelper.START
| ItemTouchHelper.END
: 0;
if (mDraggable) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
} else {
dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
}
return makeMovementFlags(dragFlags, 0);
}
To
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = 0;
int swipeFlags = 0;
if (mDraggable) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
} else {
swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(0, swipeFlags);
}
}

Related

How to set Item position in order after using ItemTouchHelper.Callback

I am creating a document arrangement activity with RecyclerView. I want to arrange the document with drag and drop. It was done by using ItemTouchHelper.Callbackbut after that I can't set the page number after the OnItemMove callback. what should I do?
EDIT: added code snippet
package adapters;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.mobilix.docscanner.R;
import java.util.ArrayList;
import java.util.Collections;
import helper.ItemTouchHelperAdapter;
import helper.ItemTouchHelperViewHolder;
import helper.OnStartDragListener;
import helper.SimpleItemTouchHelperCallback;
public class PageAjdustAdapter extends RecyclerView.Adapter<PageAjdustAdapter.PageAdjustHolder> implements ItemTouchHelperAdapter, OnStartDragListener {
private final String TAG = getClass().getName();
Context mContext;
ArrayList<PdfPage> pdfPages = new ArrayList<>();
private ItemTouchHelper itemTouchHelper;
public PageAjdustAdapter(Context context, ArrayList<PdfPage> pages) {
this.mContext = context;
pdfPages = pages;
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(this);
itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(((Activity) context).findViewById(R.id.rcvPageArrange));
}
#NonNull
#Override
public PageAdjustHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_page_adajustment, parent, false);
return new PageAdjustHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PageAdjustHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: ");
holder.ivPage.setImageBitmap(pdfPages.get(position).bitmap);
holder.cbPage.setChecked(pdfPages.get(position).isSelected);
holder.tvPageNo.setText(String.valueOf(position + 1));
holder.cbPage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
pdfPages.get(holder.getAdapterPosition()).isSelected = isChecked;
}
});
holder.ivRotate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
pdfPages.get(pos).bitmap = Bitmap.createBitmap(//
pdfPages.get(pos).bitmap, 0, 0, pdfPages.get(pos).bitmap.getWidth(),//
pdfPages.get(pos).bitmap.getHeight(), pdfPages.get(pos).matrix, true);//
notifyItemChanged(pos);
}
});
}
#Override
public int getItemCount() {
return pdfPages.size();
}
#Override
public boolean onItemMove(int fromPosition, int toPosition) {
Log.d(TAG, "onItemMove: ->fp " + (fromPosition + 1) + " tp-> " + (toPosition + 1));
Collections.swap(pdfPages, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return false;
}
#Override
public void onItemDismiss(int position) {
pdfPages.remove(position);
notifyItemRemoved(position);
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
itemTouchHelper.startDrag(viewHolder);
}
public static class PageAdjustHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
ImageView ivPage, ivRotate;
CheckBox cbPage;
TextView tvPageNo;
public PageAdjustHolder(#NonNull View itemView) {
super(itemView);
ivPage = itemView.findViewById(R.id.ivPage);
ivRotate = itemView.findViewById(R.id.ivRotate);
cbPage = itemView.findViewById(R.id.cbPage);
tvPageNo = itemView.findViewById(R.id.tvPageNo);
}
#Override
public void onItemSelected() {
}
#Override
public void onItemClear() {
}
}
public static class PdfPage {
PdfRenderer.Page page;
Bitmap bitmap;
boolean isSelected;
Matrix matrix;
int rotate = 0;
public PdfPage(PdfRenderer.Page page, Bitmap bitmap) {
this.page = page;
this.bitmap = bitmap;
matrix = new Matrix();
rotate += 90;
matrix.postRotate(90);//martix work on +=90
}
}
}
You have to call notifyDataSetChanged() when an item position is changed. The easiest way it to used onItemClear(), it will be called when an item is de-selected. Add it like following.
#Override
public void onItemClear() {
notifyDataSetChanged();
}
One thing you have to add is check weather the position is actually changed after the drag operation or not other wise it will always update the whole dataset whenever an item is selected and than de-selected.
Edit
Create a local variable in view-holder class. Than you just have to set it in onItemSelected() and check it in onItemClear();
#Override
public void onItemSelected() {
lastpos = getAdapterPosition();
}
#Override
public void onItemClear() {
if(lastpos != getAdapterPosition())
notifyDataSetChanged();
}

Why my recyclerview isn't showing any item?

I just created my recyclerview to show a cardview when I just filling the required data on AddNewTimerFragment.java. But somehow it wont show the card that contains the data that I've fill in before. I've tried to changes something, but doesn't work.
Code :
MainActivity.java
package com.mobprog.ius.dwasu;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.LinkedList;
public class MainActivity extends AppCompatActivity {
private ArrayList<MyListDataTimer> mintervalTimeList = new ArrayList();
private RecyclerView mRecyclerView;
private alarmListAdapter mAdapter;
public boolean isFragmentAddNewAlarmDisplayed = false;
static final String STATE_FRAGMENT = "state_of_fragment";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((TextView) findViewById(R.id.textUserName)).setText("Hello " + getSharedPreferences("Dwasu", 0).getString("user", ""));
if (getSharedPreferences("Dwasu", 0) == null || !getSharedPreferences("Dwasu", 0).contains("user")) {
startActivity(new Intent(MainActivity.this, LoginActivity.class));
finish();
}
// Create recycler view.
mRecyclerView = findViewById(R.id.recyclerView);
// Create an adapter and supply the data to be displayed.
mAdapter = new alarmListAdapter(getApplicationContext(), mintervalTimeList);
// Connect the adapter with the recycler view.
mRecyclerView.setAdapter(mAdapter);
// Give the recycler view a default layout manager.
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
if (savedInstanceState != null)
isFragmentAddNewAlarmDisplayed = savedInstanceState.getBoolean(STATE_FRAGMENT);
Button mnewReminderButton = findViewById(R.id.newReminder);
mnewReminderButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(MainActivity.class.getSimpleName(),"Button Clicked");
displayFragment();
}
});
ImageButton mlogOutButton = findViewById(R.id.logOutButton);
findViewById(R.id.logOutButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSharedPreferences("Dwasu", 0).edit().clear().apply();
startActivity(new Intent(MainActivity.this, MainActivity.class));
finish();
}
});
// // Get the Drawable custom_progressbar
// Drawable draw = ResourcesCompat.getDrawable(getResources(), R.drawable.progress_bar, null);
// // set the drawable as progress drawable
// ProgressBar.setProgressDrawable(draw);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the state of the fragment (true=open, false=closed).
savedInstanceState.putBoolean(STATE_FRAGMENT, isFragmentAddNewAlarmDisplayed);
super.onSaveInstanceState(savedInstanceState);
}
public void closeFragment(){
// Get the FragmentManager.
FragmentManager fragmentManager = getSupportFragmentManager();
// Check to see if the fragment is already showing.
AddNewTimerFragment simpleFragment = (AddNewTimerFragment) fragmentManager
.findFragmentById(R.id.FragmentContainer_AddNewAlarm);
if (simpleFragment != null) {
// Create and commit the transaction to remove the fragment.
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.remove(simpleFragment).commit();
}
// Set boolean flag to indicate fragment is closed.
isFragmentAddNewAlarmDisplayed = false;
}
public void displayFragment(){
AddNewTimerFragment simpleFragment = AddNewTimerFragment.newInstance();
// Get the FragmentManager and start a transaction.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
// Add the SimpleFragment.
fragmentTransaction.add(R.id.FragmentContainer_AddNewAlarm,
simpleFragment).addToBackStack(null).commit();
// Set boolean flag to indicate fragment is open.
isFragmentAddNewAlarmDisplayed = true;
}
}
AddNewTimerFragment.java
package com.mobprog.ius.dwasu;
import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TimePicker;
import android.widget.Toast;
import org.apache.http.entity.mime.content.StringBody;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import static android.content.Context.MODE_PRIVATE;
public class AddNewTimerFragment extends Fragment {
Button startTime;
Button endTime;
Button meditConfirm_button;
int startHour;
int startMinute;
int endHour;
int endMinute;
int position = 1;
long totalSize = 0;
String value;
ProgressDialog progDailog;
View rootview;
private SharedPreferences mPreferences;
private String sharedPrefFile =
"com.mobprog.ius.dwasu";
public AddNewTimerFragment() {
// Required empty public constructor
}
public static AddNewTimerFragment newInstance() {
return new AddNewTimerFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_add_new_alarm,
container, false);
rootview = rootView;
/*Shared Pref*/
mPreferences = this.getActivity().getSharedPreferences(sharedPrefFile, MODE_PRIVATE);
SharedPreferences.Editor mPreferencesEditor = mPreferences.edit();
ImageButton mbtnCloseFragment = rootView.findViewById(R.id.btnCloseFragment);
mbtnCloseFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity) getActivity()).closeFragment();
}
});
// initiate the edit text
startTime = rootView.findViewById(R.id.startTimePick);
startTime.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
// perform click event listener on edit text
startTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
startHour = mcurrentTime.get(Calendar.HOUR);
startMinute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mStartTimePicker;
mStartTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int selectedStartHour, int selectedStartMinute) {
if (selectedStartMinute == 0) {
startTime.setText(selectedStartHour + ":00");
} else if (selectedStartMinute < 10) {
if (selectedStartHour < 10) {
startTime.setText("0" + selectedStartHour + ":0" + selectedStartMinute);
}
} else {
startTime.setText(selectedStartHour + ":" + selectedStartMinute);
}
startHour = selectedStartHour;
}
}, startHour, startMinute, true);//Yes 24 hour time
mStartTimePicker.show();
}
});
endTime = rootView.findViewById(R.id.endTimePick);
endTime.setText(Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + ":" + Calendar.getInstance().get(Calendar.MINUTE));
// perform click event listener on edit text
endTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
endHour = mcurrentTime.get(Calendar.HOUR);
endMinute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mEndTimePicker;
mEndTimePicker = new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker timePicker, int selectedEndHour, int selectedEndMinute) {
if (selectedEndMinute == 0) {
endTime.setText(selectedEndHour + ":00");
} else if (selectedEndMinute < 10) {
if (selectedEndHour < 10) {
endTime.setText("0" + selectedEndHour + ":0" + selectedEndMinute);
}
} else {
endTime.setText(selectedEndHour + ":" + selectedEndMinute);
}
endHour = selectedEndHour;
}
}, endHour, endMinute, true);//Yes 24 hour time
mEndTimePicker.show();
}
});
Spinner spinner = (Spinner) rootView.findViewById(R.id.timeIntervalPick);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.listtimer, R.layout.spinner_support);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(R.layout.spinner_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
// your code here
String[] valueListTimer = getResources().getStringArray(R.array.valueListTimer);
value = valueListTimer[position];
Log.e("Value of Spinner", value);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
meditConfirm_button = rootView.findViewById(R.id.editConfirm_button);
meditConfirm_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String.valueOf(startHour);
String.valueOf(endHour);
String.valueOf(value);
new MyListDataTimer(String.valueOf(startHour),String.valueOf(endHour),String.valueOf(value),String.valueOf(position));
new UploadAlarmDataToServer().execute();
position++;
}
});
// Inflate the layout for this fragment
return rootView;
}
private class UploadAlarmDataToServer extends AsyncTask<Void, Integer, String> {
#Override
protected void onPreExecute() {
progDailog = new ProgressDialog(getContext());
progDailog.setMessage("Menyimpan...");
progDailog.setIndeterminate(false);
progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDailog.setCancelable(false);
progDailog.setCanceledOnTouchOutside(false);
progDailog.show();
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
String data = null;
try {
data = sendDataTimer();
} catch (Exception e) {
e.printStackTrace();
data = "Gagal";
}
return data;
}
public String sendDataTimer() throws Exception {
URL url = new URL("https://ius.mobile.indoserver.web.id/alarmData.php");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
new AndroidMultiPartEntity.ProgressListener() {
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
entity.addPart("startHour", new StringBody(startHour + ""));
entity.addPart("endHour", new StringBody(endHour + ""));
entity.addPart("intervalWaktu", new StringBody(value + ""));
totalSize = entity.getContentLength();
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.addRequestProperty("Content-length", totalSize + "");
con.addRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
OutputStream os = con.getOutputStream();
entity.writeTo(con.getOutputStream());
os.close();
con.connect();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
#Override
protected void onPostExecute(String result) {
progDailog.dismiss();
if (result != null) {
Log.e("UPLOAD", result);
if (result.equalsIgnoreCase("OK")) {
Toast.makeText(getContext(), "Data Alarm tersimpan", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getContext(), MainActivity.class));
}
}
super.onPostExecute(result);
}
}
}
alarmListAdapter.java
package com.mobprog.ius.dwasu;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.LinkedList;
public class alarmListAdapter extends RecyclerView.Adapter<alarmListAdapter.alarmListHolder>{
private final ArrayList<MyListDataTimer> mintervalTimeList;
private LayoutInflater mInflater;
public alarmListAdapter(Context context, ArrayList<MyListDataTimer> mintervalTimeList) {
mInflater = LayoutInflater.from(context);
this.mintervalTimeList = mintervalTimeList;
}
#Override
public alarmListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mItemView = mInflater.inflate(R.layout.alarm_item,
parent, false);
return new alarmListHolder(mItemView, this);
}
#Override
public void onBindViewHolder(alarmListAdapter.alarmListHolder holder, int position) {
final MyListDataTimer myListData = mintervalTimeList.get(position);
holder.mintervalTime.setText(myListData.getIntervalWaktu());
holder.mtimeWork.setText(myListData.getStartHour() +":00 - " + myListData.getEndHour() +":00");
}
#Override
public int getItemCount() {
return mintervalTimeList.size();
}
public class alarmListHolder extends RecyclerView.ViewHolder {
public TextView mintervalTime;
public TextView mtimeWork;
final alarmListAdapter mAdapter;
public alarmListHolder(View itemView, alarmListAdapter adapter) {
super(itemView);
mintervalTime = itemView.findViewById(R.id.intervalTime);
mtimeWork = itemView.findViewById(R.id.timeWork);
this.mAdapter = adapter;
}
}
}
**MyListDataTimer.java**
package com.mobprog.ius.dwasu;
public class MyListDataTimer {
private String startHour;
private String endHour;
private String intervalWaktu;
private String position;
public MyListDataTimer(String startHour, String endHour, String intervalWaktu, String position) {
this.startHour = startHour;
this.endHour = endHour;
this.intervalWaktu = intervalWaktu;
this.position = position;
}
public String getStartHour() {
return startHour;
}
public void setStartHour(String startHour) {
this.startHour = startHour;
}
public String getEndHour() {
return endHour;
}
public void setEndHour(String endHour) {
this.endHour = endHour;
}
public String getIntervalWaktu() {
return intervalWaktu;
}
public void setIntervalWaktu(String intervalWaktu) {
this.intervalWaktu = intervalWaktu;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}

get Variable in doInBackground Get out of AsyncTask

How to get Variable in doInBackground Get out of AsyncTask
Request Api url set new like and get new like and like mode
Now how to get new like and like mode out of AsyncTask for use setText
get like this from GetDataLike AsyncTask:
new GetDataLike().execute(textViewQuoteId.getText().toString());
String newLike = GetDataLike().newLike; // get like this from GetDataLike
String modeLike = GetDataLike().modeLike; // get like this from GetDataLike
textViewQuoteLike.setText("پسندیدم ("+newLike+")");
Toast.makeText(rootView.getContext(), "لایک شما برای سخن "+textViewProfileName.getText().toString()+" ثبت شد.",
Toast.LENGTH_LONG).show();
Json result example:
{"Like":{"quote_like":"27","quote_like_mode":"1"}}
QuoteArrayAdapter.java
package com.example.adapter;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.R;
import com.example.model.QuoteDataModel;
import com.example.parser.JSONParser;
import com.example.utils.Keys;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Transformation;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import static android.content.Context.CLIPBOARD_SERVICE;
public class QuoteArrayAdapter extends ArrayAdapter<QuoteDataModel> {
List<QuoteDataModel> modelList;
Context context;
private LayoutInflater mInflater;
// Constructors
public QuoteArrayAdapter(Context context, List<QuoteDataModel> objects) {
super(context, 0, objects);
this.context = context;
this.mInflater = LayoutInflater.from(context);
modelList = objects;
}
#Override
public QuoteDataModel getItem(int position) {
return modelList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder vh;
if (convertView == null) {
View view = mInflater.inflate(R.layout.quote_row, parent, false);
vh = ViewHolder.create((RelativeLayout) view);
view.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
QuoteDataModel item = getItem(position);
vh.textViewQuoteContent.setText(item.getQuoteContent());
vh.textViewProfileName.setText(item.getProfileName());
vh.textViewQuoteLike.setText("پسندیدم ("+item.getQuoteLike()+")");
vh.textViewQuoteCopy.setText("کپی");
vh.textViewQuoteShare.setText("اشتراک");
vh.textViewQuoteId.setText(item.getQuoteId());
Picasso.with(context).load(item.getProfilePhoto()).placeholder(R.drawable.empty_profile_photo).error(R.drawable.empty_profile_photo).transform(new CircleTransform()).into(vh.imageViewProfilePhoto);
return vh.rootView;
}
private static class ViewHolder {
public final RelativeLayout rootView;
public final ImageView imageViewProfilePhoto;
public final TextView textViewQuoteContent;
public final TextView textViewProfileName;
public final TextView textViewQuoteLike;
public final TextView textViewQuoteCopy;
public final TextView textViewQuoteShare;
public final TextView textViewQuoteId;
public final TextView textViewQuoteLikeIcon;
public final TextView textViewQuoteShareIcon;
public final TextView textViewQuoteCopyIcon;
private ViewHolder(RelativeLayout rootView, ImageView imageViewProfilePhoto, TextView textViewQuoteContent, TextView textViewProfileName, TextView textViewQuoteLike, TextView textViewQuoteCopy, TextView textViewQuoteShare, TextView textViewQuoteId, TextView textViewQuoteLikeIcon, TextView textViewQuoteShareIcon, TextView textViewQuoteCopyIcon) {
this.rootView = rootView;
this.imageViewProfilePhoto = imageViewProfilePhoto;
this.textViewQuoteContent = textViewQuoteContent;
this.textViewProfileName = textViewProfileName;
this.textViewQuoteLike = textViewQuoteLike;
this.textViewQuoteCopy = textViewQuoteCopy;
this.textViewQuoteShare = textViewQuoteShare;
this.textViewQuoteId = textViewQuoteId;
this.textViewQuoteLikeIcon = textViewQuoteLikeIcon;
this.textViewQuoteShareIcon = textViewQuoteShareIcon;
this.textViewQuoteCopyIcon = textViewQuoteCopyIcon;
}
public static ViewHolder create(final RelativeLayout rootView) {
ImageView imageViewProfilePhoto = (ImageView) rootView.findViewById(R.id.imageViewProfilePhoto);
final TextView textViewQuoteContent = (TextView) rootView.findViewById(R.id.textViewQuoteContent);
final TextView textViewProfileName = (TextView) rootView.findViewById(R.id.textViewProfileName);
final TextView textViewQuoteLike = (TextView) rootView.findViewById(R.id.textViewQuoteLike);
TextView textViewQuoteCopy = (TextView) rootView.findViewById(R.id.textViewQuoteCopy);
TextView textViewQuoteShare = (TextView) rootView.findViewById(R.id.textViewQuoteShare);
final TextView textViewQuoteId = (TextView) rootView.findViewById(R.id.textViewQuoteId);
final TextView textViewQuoteLikeIcon = (TextView) rootView.findViewById(R.id.textViewQuoteLikeIcon);
final TextView textViewQuoteShareIcon = (TextView) rootView.findViewById(R.id.textViewQuoteShareIcon);
final TextView textViewQuoteCopyIcon = (TextView) rootView.findViewById(R.id.textViewQuoteCopyIcon);
textViewQuoteLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new GetDataLike().execute(textViewQuoteId.getText().toString());
String currentLike = textViewQuoteLike.getText().toString();
currentLike = currentLike.replace("پسندیدم (","");
currentLike = currentLike.replace(")","");
int newLike = Integer.valueOf(currentLike.toString()) + 1;
textViewQuoteLike.setText("پسندیدم ("+newLike+")");
Toast.makeText(rootView.getContext(), "لایک شما برای سخن "+textViewProfileName.getText().toString()+" ثبت شد.",
Toast.LENGTH_LONG).show();
}
});
textViewQuoteLikeIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new GetDataLike().execute(textViewQuoteId.getText().toString());
String currentLike = textViewQuoteLike.getText().toString();
currentLike = currentLike.replace("پسندیدم (","");
currentLike = currentLike.replace(")","");
int newLike = Integer.valueOf(currentLike.toString()) + 1;
textViewQuoteLike.setText("پسندیدم ("+newLike+")");
Toast.makeText(rootView.getContext(), "لایک شما برای سخن "+textViewProfileName.getText().toString()+" ثبت شد.",
Toast.LENGTH_LONG).show();
}
});
Typeface font = Typeface.createFromAsset( rootView.getContext().getAssets(), "fontawesome-webfont.ttf" );
textViewQuoteLikeIcon.setTypeface(font);
textViewQuoteLikeIcon.setText(String.valueOf((char) 0xf164));
return new ViewHolder(rootView, imageViewProfilePhoto, textViewQuoteContent, textViewProfileName, textViewQuoteLike, textViewQuoteCopy, textViewQuoteShare, textViewQuoteId, textViewQuoteLikeIcon, textViewQuoteShareIcon, textViewQuoteCopyIcon);
}
}
static class GetDataLike extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Nullable
#Override
protected String doInBackground(String... params) {
String quoteId = params[0];
JSONObject jsonObject = JSONParser.getDataFromWeb("http://example.com/api-service/v1/platform_quote_like/?id="+quoteId);
try {
if (jsonObject != null) {
if(jsonObject.length() > 0) {
JSONArray array = jsonObject.getJSONArray(Keys.KEY_LIKE);
int lenArray = array.length();
if(lenArray > 0) {
for(int jIndex = 0; jIndex < lenArray; jIndex++) {
JSONObject innerObject = array.getJSONObject(jIndex);
String quote_like = innerObject.getString(Keys.KEY_QUOTE_LIKE);
String quote_like_mode = innerObject.getString(Keys.KEY_QUOTE_LIKE_Mode);
}
}
}
} else {
}
} catch (JSONException je) {
Log.i(JSONParser.TAG, "" + je.getLocalizedMessage());
}
return null;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
}
}
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap,
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
}
you just have to return string from doInBackground method and in onPostExecute method you can setText.for more than one values which is in your case you should do like this
public class CollectValues{
public String quote_like;
public String quote_like_mode;}
and now in doInBackground method you should do like this
CollectValue cv = new CollectValue();
cv.quote_like=//your response;
cv.quote_like=//your response;
return cv;
and finally in onPostExecute method you should do like this
#Override
protected void onPostExecute(CollectValues cv) {
//your textview here
textview1.setText(cv.quote_like);
textview2.setText(cv.quote_like_mode);
}
this will solve your problem..

pagination in recyclerview in android

I'm trying to implement pagination in recyclerview.
Following are my java classes:
MyAdapter.java
package com.example.opinion;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by manish on 7/18/2016.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<String> movieName = new ArrayList();
public MyAdapter(ArrayList film)
{
this.movieName = film;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_items, null);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.movieText.setText(movieName.get(position));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount()
{
System.out.print(movieName.size());
return movieName.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView movieText;
public ViewHolder(View v) {
super(v);
movieText = (TextView) v.findViewById(R.id.movieName);
}
}
}
viewfragment.java : here i'm fetching the data on my local network. In this file the loadMore(current_page) function only fetches 3 values at time. The first time when it is called, those three values are only visible in the cardview inside recyclerview. I don't know where the problem is!
package com.example.opinion;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Text;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.content.Intent;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Path;
public class ViewFragment extends Fragment {
private static final String PREFS_NAME = "Prefname";
public int j =0;
static String quesText;
//public static final String BASE_URL = "http://192.168.0.104/";
public interface PostquesApi{
#GET("ques/{i}")
Call<quesGetResponse> quesget(#Path("i") String i);
}
static class quesGetResponse {
String ques1;
String ques2;
String ques3;
String quid1;
String quid2;
String quid3;
public quesGetResponse(String ques1, String ques2, String ques3, String u1, String u2,String u3){
this.ques1 = ques1;
this.ques2 = ques2;
this.ques3 = ques3;
this.quid1 = u1;
this.quid2 = u2;
this.quid3 = u3;
}
}
//View rootView;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private ArrayList movieList = new ArrayList();
private static int current_page = 1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_view, container, false);
for(int k=0; k<2; k++) {
loadData(current_page);
}
System.out.println("contents of movie list: "+ movieList);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
LinearLayoutManager feedLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new MyAdapter(movieList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(feedLayoutManager);
// specify an adapter (see also next example)
mRecyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(
feedLayoutManager) {
#Override
public void onLoadMore(int current_page) {
// do somthing...
loadMoreData(current_page);
}
});
/*qt2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent comm = new Intent(getActivity(), Comments.class);
quesText = qt2.getText().toString();
//comm.putExtra(quesText, Text );
startActivity(comm);
}
});
qt3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent comm = new Intent(getActivity(), Comments.class);
quesText = qt3.getText().toString();
//comm.putExtra(quesText, Text );
startActivity(comm);
}
});*/
return rootView;
}
public void loadData(int page) {
// Send an API request to retrieve appropriate data using the offset value as a parameter.
// --> Deserialize API response and then construct new objects to append to the adapter
// --> Notify the adapter of the changes
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Login.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
PostquesApi apiService = retrofit.create(PostquesApi.class);
Call<quesGetResponse> call = apiService.quesget(Integer.toString(j));
call.enqueue(new Callback<quesGetResponse>() {
#Override
public void onResponse(Call<quesGetResponse> call, Response<quesGetResponse> response) {
quesGetResponse decodedResponse = response.body();
if (decodedResponse != null) {
if (decodedResponse.ques1 != null && decodedResponse.quid1.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques1);
}
if (decodedResponse.ques2 != null && decodedResponse.quid2.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques2);
}
if (decodedResponse.ques3 != null && decodedResponse.quid3.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques3);
}
}
if (decodedResponse.ques1 == null || decodedResponse.ques2 == null || decodedResponse.ques3 == null) {
Context context = getActivity().getApplicationContext();
CharSequence text = "Sorry!! no more questions in the database...";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
j = j + 3;
}
#Override
public void onFailure(Call<quesGetResponse> call, Throwable t) {
}
});
}
private void loadMoreData(int current_page) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Login.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
PostquesApi apiService = retrofit.create(PostquesApi.class);
Call<quesGetResponse> call = apiService.quesget(Integer.toString(j));
call.enqueue(new Callback<quesGetResponse>() {
#Override
public void onResponse(Call<quesGetResponse> call, Response<quesGetResponse> response) {
quesGetResponse decodedResponse = response.body();
if (decodedResponse != null) {
if (decodedResponse.ques1 != null && decodedResponse.quid1.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques1);
}
if (decodedResponse.ques2 != null && decodedResponse.quid2.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques2);
}
if (decodedResponse.ques3 != null && decodedResponse.quid3.compareTo(Login.user_id) != 0)
{
movieList.add(decodedResponse.ques3);
}
}
if (decodedResponse.ques1 == null || decodedResponse.ques2 == null || decodedResponse.ques3 == null) {
Context context = getActivity().getApplicationContext();
CharSequence text = "Sorry!! no more questions in the database...";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
j = j + 3;
}
#Override
public void onFailure(Call<quesGetResponse> call, Throwable t) {
}
});
mAdapter.notifyDataSetChanged();
}
}
EndlessRecyclerOnScrollListener.java: The file that implements the logic for pagination.
package com.example.opinion;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
/**
* Created by manish on 7/20/2016.
*/
public abstract class EndlessRecyclerOnScrollListener extends
RecyclerView.OnScrollListener {
public static String TAG = EndlessRecyclerOnScrollListener.class
.getSimpleName();
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 3;
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 1;
private LinearLayoutManager mLinearLayoutManager;
public EndlessRecyclerOnScrollListener(
LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading
&& (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
current_page++;
onLoadMore(current_page);
loading = true;
}
}
public abstract void onLoadMore(int current_page);
}
If someone can review it and tell me the corrections needed in the above files or can direct me to some resource, it will be really appreciated.
I would suggest instead of using EndlessRecyclerOnScrollListener class and listening to the Recyclerview's scroll event you should watch inside MyAdapter class.
1. First add one interface
public interface GetNewDataEvents {
void getNewAdapterData();
}
2. Initialize that interface in MyAdapter class from where you are adding your data by implementing it.
3. you can easily find which item is being loading currently in bindViewHolder
using
if(position==(movieName.size()-1)
and in it you can easily call that interface method and load new data in it.
This thing denotes that second last item is being currently loading and you should add new data if any.
If you get new data you can easily load it into your adapter and call notifyItemRangeChanged with it to get performance and implementing best practices by not loading whole adapter with only few items changed.
if you want to take reference for it you can go here

RecyclerView lags on scrolling

I'm having an issue where when the RecyclerView has a big amount of items (say 2000) the scrolling is really laggy.
I would be really really thankful if someone helps me improving it. Thanks in advance.
EDIT: The lag may be caused when using this FastScroll library. If someone is able to do some pull requests to improve it, I'm sure the dev will be really thankful. https://github.com/plusCubed/recycler-fast-scroll
Here's the Fragment code:
package jahirfiquitiva.apps.iconshowcase.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.pluscubed.recyclerfastscroll.RecyclerFastScroller;
import java.util.ArrayList;
import java.util.Locale;
import jahirfiquitiva.apps.iconshowcase.R;
import jahirfiquitiva.apps.iconshowcase.adapters.IconsAdapter;
import jahirfiquitiva.apps.iconshowcase.utilities.Preferences;
import jp.wasabeef.recyclerview.adapters.AlphaInAnimationAdapter;
import jp.wasabeef.recyclerview.adapters.ScaleInAnimationAdapter;
public class IconsFragment extends Fragment {
private IconsAdapter mAdapter;
private Preferences mPrefs;
private ArrayList<String> iconsNames, filteredIconsList;
private ArrayList<Integer> iconsInts, filteredIconsInts;
private ViewGroup layout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mPrefs = new Preferences(getActivity());
if (layout != null) {
ViewGroup parent = (ViewGroup) layout.getParent();
if (parent != null) {
parent.removeView(layout);
}
}
try {
layout = (ViewGroup) inflater.inflate(R.layout.icons_grid, container, false);
} catch (InflateException e) {
}
RecyclerFastScroller fastScroller =
(RecyclerFastScroller) layout.findViewById(R.id.rvFastScroller);
fastScroller.setVisibility(View.GONE);
RecyclerView iconsGrid = (RecyclerView) layout.findViewById(R.id.iconsGrid);
iconsGrid.setHasFixedSize(true);
iconsGrid.setLayoutManager(new GridLayoutManager(getActivity(),
getResources().getInteger(R.integer.icon_grid_width)));
mAdapter = new IconsAdapter(getActivity(), new ArrayList<String>(), new ArrayList<Integer>());
if (getArguments() != null) {
iconsNames = getArguments().getStringArrayList("iconsNamesList");
iconsInts = getArguments().getIntegerArrayList("iconsArray");
mAdapter.setIcons(iconsNames, iconsInts);
}
iconsGrid.setAdapter(mPrefs.getAnimationsEnabled() ? animAdapter(mAdapter) : mAdapter);
fastScroller.setRecyclerView(iconsGrid);
fastScroller.setHideDelay(500);
fastScroller.setVisibility(View.VISIBLE);
return layout;
}
public static IconsFragment newInstance(ArrayList<String> iconsNames, ArrayList<Integer> iconsArray) {
IconsFragment fragment = new IconsFragment();
Bundle args = new Bundle();
args.putStringArrayList("iconsNamesList", iconsNames);
args.putIntegerArrayList("iconsArray", iconsArray);
fragment.setArguments(args);
return fragment;
}
public void performSearch(String query) {
filter(query, mAdapter);
}
private synchronized void filter(CharSequence s, IconsAdapter adapter) {
if (s == null || s.toString().trim().isEmpty()) {
if (filteredIconsList != null) {
filteredIconsList = null;
}
if (filteredIconsInts != null) {
filteredIconsList = null;
}
adapter.clearIconsList();
adapter.setIcons(iconsNames, iconsInts);
adapter.notifyDataSetChanged();
} else {
if (filteredIconsList != null) {
filteredIconsList.clear();
}
if (filteredIconsInts != null) {
filteredIconsList = null;
}
filteredIconsList = new ArrayList<String>();
filteredIconsInts = new ArrayList<Integer>();
for (int i = 0; i < iconsNames.size(); i++) {
String name = iconsNames.get(i);
if (name.toLowerCase(Locale.getDefault())
.startsWith(s.toString().toLowerCase(Locale.getDefault()))) {
filteredIconsList.add(iconsNames.get(i));
filteredIconsInts.add(iconsInts.get(i));
}
}
adapter.clearIconsList();
adapter.setIcons(filteredIconsList, filteredIconsInts);
adapter.notifyDataSetChanged();
}
}
private ScaleInAnimationAdapter animAdapter(IconsAdapter iconsAdapter) {
AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(iconsAdapter);
ScaleInAnimationAdapter scaleAdapter = new ScaleInAnimationAdapter(alphaAdapter);
scaleAdapter.setFirstOnly(true);
return scaleAdapter;
}
}
And RecyclerView adapter:
package jahirfiquitiva.apps.iconshowcase.adapters;
import android.content.Context;
import android.content.res.Resources;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.afollestad.materialdialogs.MaterialDialog;
import java.util.ArrayList;
import java.util.Locale;
import jahirfiquitiva.apps.iconshowcase.R;
import jahirfiquitiva.apps.iconshowcase.utilities.Util;
public class IconsAdapter extends RecyclerView.Adapter<IconsAdapter.IconsHolder> implements View.OnClickListener {
private final Context context;
private ArrayList<String> iconsList = new ArrayList<>();
private ArrayList<Integer> iconsArray = new ArrayList<>();
public IconsAdapter(Context context, ArrayList<String> iconsList, ArrayList<Integer> iconsArray) {
this.context = context;
this.iconsList = iconsList;
this.iconsArray = iconsArray;
}
public void setIcons(ArrayList<String> iconsList, ArrayList<Integer> iconsArray) {
this.iconsList.addAll(iconsList);
this.iconsArray.addAll(iconsArray);
this.notifyItemRangeInserted(0, iconsList.size() - 1);
}
public void clearIconsList() {
this.iconsList.clear();
this.iconsArray.clear();
}
#Override
public IconsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new IconsHolder(inflater.inflate(R.layout.item_icon, parent, false));
}
#Override
public void onBindViewHolder(IconsHolder holder, int position) {
if (iconsArray.size() > 0) {
holder.icon.setImageResource(iconsArray.get(position));
}
holder.view.setTag(position);
holder.view.setOnClickListener(this);
setAnimation(holder.icon, position);
}
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
viewToAnimate.setHasTransientState(true);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return iconsList == null ? 0 : iconsList.size();
}
#Override
public void onClick(View v) {
int position = (Integer) v.getTag();
int resId = iconsArray.get(position);
String name = iconsList.get(position).toLowerCase(Locale.getDefault());
MaterialDialog dialog = new MaterialDialog.Builder(context)
.customView(R.layout.dialog_icon, false)
.title(Util.makeTextReadable(name))
.positiveText(R.string.close)
.show();
if (dialog.getCustomView() != null) {
ImageView dialogIcon = (ImageView) dialog.getCustomView().findViewById(R.id.dialogicon);
dialogIcon.setImageResource(resId);
}
}
class IconsHolder extends RecyclerView.ViewHolder {
final View view;
final ImageView icon;
IconsHolder(View v) {
super(v);
view = v;
icon = (ImageView) v.findViewById(R.id.icon_img);
}
}
}
From your comment you have mentioned that, you are not using any library for loading images, that's might be the issue, since libraries like Picasso ,glide... Use an asynctask to load images load on the main that is refused. You can do the same by writing it yourself but you will end up re-inventing the wheel again
How big are the images? Try to downscale them (for example resize through Picasso)

Categories