Info:
I have a RecyclerView, and I populate it with the ArrayList dataList inside the ListAdapter class. I get the data for dataList from the SQLiteDatabase table: TABLE_USERdETAIL in the DbHelper class. I'm trying to implement drag and drop re-organisation into the RecyclerView by using the SimpleItemTouchHelperCallback class; however, although I am now able to move the RecyclerView elements, the list doesn't re-sort or move; I'm only able to temporarily drag the list elements over each other, as shown in the image below, but it's meant to be permanently slotting the list elements into whichever position it's held:
I expect the problem to be within the ListAdapter class, inside the method onItemMove, but I don't know how to solve my issue.
Question: How do I make this drag and drop feature actually re-organise the RecyclerView data list?
Update 5: I have updated my current code for further assistance.
ListAdapter Class
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> {
Context context;
List<UserData> dataList = new ArrayList<>();
LayoutInflater inflater;
Listener listener;
DbHelper dbHelper;
public interface Listener {
void nameToChnge(String name);
}
public ListAdapter(Context context, List<UserData> dataList1) {
this.context = context;
this.dataList = dataList1;
//this.listener= (Listener) context;
inflater = LayoutInflater.from(context);
}
#Override
public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View convertView = inflater.inflate(R.layout.recylerview_one, parent, false);
ListViewHolder viewHolder = new ListViewHolder(convertView);
return viewHolder;
}
#Override
public void onBindViewHolder(ListViewHolder holder, final int position) {
holder.tv_name.setText(dataList.get(position).name);
holder.tv_quantity.setText(dataList.get(position).quantity);
holder.tv_description.setText(dataList.get(position).description + " ");
if(dataList.get(position).description.isEmpty()) {
holder.tv_description.setVisibility(View.GONE);
}
holder.relLayout.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
String s = dataList.get(position).id;
Integer stringo = Integer.parseInt(s);
Intent intent = new Intent(context, ItemEditActivity.class);
intent.putExtra("ItemNumber", stringo);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return dataList.size();
}
class ListViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
TextView tv_name, tv_quantity, tv_description;
RelativeLayout relLayout;
public ListViewHolder(View itemView) {
super(itemView);
tv_name = (TextView) itemView.findViewById(R.id.nameDisplay);
tv_quantity = (TextView) itemView.findViewById(R.id.quantityDisplay);
tv_description = (TextView) itemView.findViewById(R.id.descriptionDisplay);
relLayout = (RelativeLayout) itemView.findViewById(R.id.relLayout);
}
#Override
public void onItemSelected() {
Log.d("ListViewHolder", "item selected");
}
#Override
public void onItemClear() {
Log.d("ListViewHolder", "item clear");
for (int count = 0; count < dataList.size(); count++) {
UserData u = dataList.get(count);
u.setSort(count);
dbHelper.updateUserData(u);
}
notifyDataSetChanged();
}
}
public void onItemDismiss(int position) {
dataList.remove(position);
//dbHelper = DbHelper.getInstance(context);
//dbHelper.deleteRowItem(position + 1);
notifyItemRemoved(position);
}
//Collections.swap(dataList, fromPosition, toPosition);
//notifyItemMoved(fromPosition, toPosition);
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(dataList, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(dataList, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
}
SimpleItemTouchHelperCallback Class
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ListAdapter mAdapter;
public SimpleItemTouchHelperCallback(ListAdapter adapter) {
mAdapter = adapter;
}
#Override
public boolean isLongPressDragEnabled() {return true; }
#Override
public boolean isItemViewSwipeEnabled() { return false; }
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
#Override
public boolean onMove(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
Log.i("ADAPTER", "----DRAGGING----");
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
}
DbHelper Class
public class DbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "UserDatabase";
private static final int DATABASE_VERSION = 2;
private static DbHelper mDbHelper;
public static String TABLE_USERdETAIL = "userdetail";
private static final String _ID = "_id";
private static final String SORT_ID = "sort_id";
private static final String NAME = "name";
private static final String QUANTITY = "quantity";
private static final String WEIGHT = "weight";
private static final String WEIGHTTOTAL = "weighttotal";
private static final String VALUE = "value";
private static final String VALUETOTAL = "valuetotal";
private static final String DESCRIPTION = "description";
public static synchronized DbHelper getInstance(Context context) {
if (mDbHelper == null) {
mDbHelper = new DbHelper(context.getApplicationContext());
}
return mDbHelper;
}
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_USERDETAIL_TABLE = "CREATE TABLE " + TABLE_USERdETAIL +
"(" +
_ID + " INTEGER PRIMARY KEY , " +
SORT_ID + " INTEGER," +
NAME + " TEXT," +
QUANTITY + " INTEGER," +
WEIGHT + " INTEGER," +
WEIGHTTOTAL + " INTEGER," +
VALUE + " INTEGER," +
VALUETOTAL + " INTEGER," +
DESCRIPTION + " TEXT" +
")";
db.execSQL(CREATE_USERDETAIL_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHT + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHTTOTAL + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUE + " INTEGER DEFAULT 0");
db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUETOTAL + " INTEGER DEFAULT 0");
}
}
/**
Insert a user detail into database
*/
public void insertUserDetail(UserData userData) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(SORT_ID, userData.sort_id);
values.put(NAME, userData.name);
values.put(QUANTITY, userData.quantity);
values.put(WEIGHT, userData.weight);
values.put(WEIGHTTOTAL, userData.weighttotal);
values.put(VALUE, userData.value);
values.put(VALUETOTAL, userData.valuetotal);
values.put(DESCRIPTION, userData.description);
db.insertOrThrow(TABLE_USERdETAIL, null, values);
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
public void updateUserDetail(int id, String v1, String v2, String v3, String v4, String v5, String v6, String v7){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(NAME, v1);
values.put(QUANTITY, v2);
values.put(DESCRIPTION, v3);
values.put(WEIGHT, v4);
values.put(WEIGHTTOTAL, v5);
values.put(VALUE, v6);
values.put(VALUETOTAL, v7);
db.update(TABLE_USERdETAIL, values, "_id="+id, null);
}
/**
fetch all data from UserTable
*/
public List<UserData> getAllUser() {
List<UserData> usersdetail = new ArrayList<>();
String USER_DETAIL_SELECT_QUERY = "SELECT * FROM " + TABLE_USERdETAIL + " ORDER BY " + SORT_ID + " COLLATE NOCASE;";
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(USER_DETAIL_SELECT_QUERY, null);
try {
if (cursor.moveToFirst()) {
do {
UserData userData = new UserData();
userData.id = cursor.getString(cursor.getColumnIndex(_ID));
userData.sort_id = cursor.getInt(cursor.getColumnIndex(SORT_ID));
userData.name = cursor.getString(cursor.getColumnIndex(NAME));
userData.quantity = "Quantity: " + cursor.getString(cursor.getColumnIndex(QUANTITY));
userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
usersdetail.add(userData);
} while (cursor.moveToNext());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
return usersdetail;
}
/**
Delete single row from UserTable
*/
void deleteRow(String name) {
SQLiteDatabase db = getWritableDatabase();
try {
db.beginTransaction();
db.execSQL("delete from " + TABLE_USERdETAIL + " where name ='" + name + "'");
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
void deleteRowItem(int id) {
SQLiteDatabase db = getWritableDatabase();
try {
db.beginTransaction();
db.execSQL("delete from " + TABLE_USERdETAIL + " where _id ='" + id + "'");
db.setTransactionSuccessful();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
public UserData getSingleUserDetail(String userId) {
SQLiteDatabase db = this.getWritableDatabase();
UserData userData = null;
//Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL, null);
// this is the code to order the RecyclerView by _ID:
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL + " WHERE " + _ID + "= ?", new String[]{userId});
try {
while (cursor.moveToNext()) {
userData = new UserData();
userData.name = cursor.getString(cursor.getColumnIndex(NAME));
userData.quantity = cursor.getString(cursor.getColumnIndex(QUANTITY));
userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
}
cursor.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
return userData;
}
public int getTotalWeight() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(WEIGHTTOTAL) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalWeight();
}
public int getTotalQuantity() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(QUANTITY) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalQuantity();
}
public int getTotalValue() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor cur = db.rawQuery("SELECT SUM(VALUETOTAL) FROM userdetail", null);
if(cur.moveToFirst())
{
return cur.getInt(0);
}
cur.close();
return getTotalValue();
}
public int getMaxColumnData() {
SQLiteDatabase db = this.getWritableDatabase();
final SQLiteStatement stmt = db
.compileStatement("SELECT MAX(SORT_ID) FROM " + TABLE_USERdETAIL);
return (int) stmt.simpleQueryForLong();
}
public void updateUserData(UserData userData) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(NAME, userData.getName());
values.put(QUANTITY, userData.getQuantity());
values.put(DESCRIPTION, userData.getDescription());
values.put(WEIGHT, userData.getWeight());
values.put(WEIGHTTOTAL, userData.getWeighttotal());
values.put(VALUE, userData.getValue());
values.put(VALUETOTAL, userData.getValuetotal());
values.put(SORT_ID, userData.getSort());
Log.i("DBhelper", "USER UPDATED = " + userData.getName());
db.update(TABLE_USERdETAIL, values, _ID + "=?", new String[]{String.valueOf(userData.getId())});
}
}
UserData
import java.io.Serializable;
public class UserData implements Serializable {
String id, name, quantity, weight, weighttotal, value, valuetotal, description;
int sort_id;
public UserData() {
super();
}
public void setId(String id){
this.id= id;
}
public String getId(){
return id;
}
public void setSort(int sort){
this.sort_id= sort;
}
public int getSort(){
return sort_id;
}
public void setName(String name){
this.name= name;
}
public String getName(){
return name;
}
public void setDescription(String description){
this.description= description;
}
public String getDescription(){
return description;
}
public void setQuantity(String quantity){
this.quantity= quantity;
}
public String getQuantity(){
return quantity;
}
public void setWeight(String weight){
this.weight= weight;
}
public String getWeight(){
return weight;
}
public void setWeighttotal(String weighttotal){
this.weighttotal= weighttotal;
}
public String getWeighttotal(){
return weighttotal;
}
public void setValue(String value){
this.value= value;
}
public String getValue(){
return value;
}
public void setValuetotal(String valuetotal){
this.quantity= valuetotal;
}
public String getValuetotal(){
return quantity;
}
}
ItemTouchHelperViewHolder Class
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
MainActivity
public class MainActivity extends AppCompatActivity implements ListAdapter.Listener {
RecyclerView recyclerView;
DbHelper dbHelper;
ListAdapter adapter;
private ItemTouchHelper mItemTouchHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = DbHelper.getInstance(getApplicationContext());
recyclerView = (RecyclerView) findViewById(R.id.rv_contactlist);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ItemTouchHelper.Callback callback =
new SimpleItemTouchHelperCallback(adapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.about_task:
Intent intentChangeActivity2 = new Intent(MainActivity.this, AboutActivity.class);
startActivity(intentChangeActivity2);
return true;
case R.id.encumbrance_task:
Intent intentChangeActivity = new Intent(MainActivity.this, EncumbranceActivity.class);
startActivity(intentChangeActivity);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onResume() {
super.onResume();
dbHelper = DbHelper.getInstance(getApplicationContext());
recyclerView = (RecyclerView) findViewById(R.id.rv_contactlist);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
#Override
public void nameToChnge(String name) {
dbHelper.deleteRow(name);
adapter = new ListAdapter(this, dbHelper.getAllUser());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
Error log:
8-26 11:20:49.443 23533-23533/name.appE/AndroidRuntime: FATAL EXCEPTION: main
Process: name.app, PID: 23533
java.lang.NullPointerException: Attempt to invoke virtual method 'void name.app.DbHelper.updateUserData(name.app.UserData)' on a null object reference
at name.app.ListAdapter$ListViewHolder.onItemClear(ListAdapter.java:95)
at name.app.SimpleItemTouchHelperCallback.clearView(SimpleItemTouchHelperCallback.java:63)
at android.support.v7.widget.helper.ItemTouchHelper$3.onAnimationEnd(ItemTouchHelper.java:619)
at android.support.v4.animation.HoneycombMr1AnimatorCompatProvider$AnimatorListenerCompatWrapper.onAnimationEnd(HoneycombMr1AnimatorCompatProvider.java:115)
at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1149)
at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1309)
at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
at android.animation.AnimationHandler.-wrap2(AnimationHandler.java)
at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:869)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:616)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
I'm not sure that catching your problem but what i noticed (hope this helps):
in your onItemMove you are refactoring dataList by swapping items but adapter notifies only about general change.
guess the simplest way to move the item (and save animation) is to remove it and add again:
UserData item = dataList.remove(fromPosition);
dataList.add(i, toPossition);
notifyItemMoved(fromPosition, toPosition);
EDITED: Look at the complete example here
I tested your code and your OnItemMove method is working as expected.
Probably, you have problems to store the order in your database?
Here you have an example:
1- Create ItemTouchHelperViewHolder interface:
public interface ItemTouchHelperViewHolder {
void onItemSelected();
void onItemClear();
}
Now implement it in your ViewHolder class.
2- Go to SimpleItemTouchHelperCallback class and add this two methods:
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
ItemTouchHelperViewHolder itemViewHolder =
(ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
#Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
3- In OnItemClear (ViewHolder class) store the new order:
#Override
public void onItemClear() {
for (int count = 0; count < dataList.size(); count++) {
UserData u = dataList.get(count);
u.setOrder(count);
mDbHelper.updateOrder(u);
}
adapter.notifyDataSetChanged();
}
I am not sure about getting your problem. But I have implemented the same using the given code. This code doesn't use SQLite but it does perform drag and drop in recycler view with some textviews. You can have a look at my code:
MovieTouchHelper.java
public class MovieTouchHelper extends ItemTouchHelper.SimpleCallback {
private MovieAdapter mMovieAdapter;
public MovieTouchHelper(MovieAdapter movieAdapter){
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
this.mMovieAdapter = movieAdapter;
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mMovieAdapter.remove(viewHolder.getAdapterPosition());
}
}
MovieAdapter.java
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
private Context mContext;
private List<Movie> mMovies;
public MovieAdapter(Context context, List<Movie> movies){
this.mContext = context;
this.mMovies = movies;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item_movie, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindMovie(mMovies.get(position));
}
#Override
public int getItemCount() {
return mMovies.size();
}
public void remove(int position) {
mMovies.remove(position);
notifyItemRemoved(position);
}
public void swap(int firstPosition, int secondPosition){
Collections.swap(mMovies, firstPosition, secondPosition);
notifyItemMoved(firstPosition, secondPosition);
}
public class ViewHolder extends RecyclerView.ViewHolder{
public final TextView movieNameTextView;
public ViewHolder(View view){
super(view);
movieNameTextView = (TextView) view.findViewById(R.id.movie_name);
}
public void bindMovie(Movie movie){
this.movieNameTextView.setText(movie.getName());
}
}
}
You can edit the code according to your need.
Hope this helps!
In onItemMove you don't need to make all the swap because the method will be called every time the selected item change its position with the item next to it. So every iteration in the for will be taking care on each call to the method.
you should move the item from the old position (dragged.getAdapterPosition()) to new position (target.getAdapterPosition()) in your adapter and also call RecyclerView.Adapter.notifyItemMoved(int, int).
Your onItemMove should look something like this:
#Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
Related
How can I get the first adapter position inside another adapter to set value in SQLite Database
I want to select a value from the radio button onClick of the item and save it to SQLite database
it's working fine but it takes onClick last position of the item
So I need First Adapter position in the inside adapter to save a proper value of radio button in SQLite Database
Globally Declare
int pos = 0;
Here is my first adapter code
public class CartCustomAdapter extends RecyclerView.Adapter<CartCustomAdapter.MyViewHolder> {
private List<Cart> moviesList;
public CartCustomAdapter(List<Cart> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_cart_details, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final List<Cart> datum = moviesList;
pos = holder.getAdapterPosition();
Log.e("POSI1", pos + "");
if (loginModel != null) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("option_name", TextUtils.join(",", Collections.singleton(datum.get(position).getShippingOption() + "")));
hashMap.put("weight", datum.get(position).getWeight() + "");
hashMap.put("zip", loginModel.getResultLogin().getZip() + "");
Log.e("Parms", hashMap + "");
showProgressDialog();
Call<CheckOutShippingInfoModel> checkOutShippingInfoModelCall = RetrofitHelper.createService(RetrofitHelper.Service.class).CheckOutShippingInfoModel(hashMap);
checkOutShippingInfoModelCall.enqueue(new Callback<CheckOutShippingInfoModel>() {
#Override
public void onResponse(#NonNull Call<CheckOutShippingInfoModel> call, #NonNull Response<CheckOutShippingInfoModel> response) {
CheckOutShippingInfoModel object = response.body();
hideProgressDialog();
if (object != null && object.getError() == false) {
Log.e("TAG", "Shipping_Response : " + new Gson().toJson(response.body()));
holder.resultCheckoutShippingInfo = object.getResultCheckoutShippingInfo();
holder.resultCheckoutShippingInfo = object.getResultCheckoutShippingInfo();
holder.shippingCustomAdapter = new ShippingCustomAdapter(holder.resultCheckoutShippingInfo,
new ResultCallback() {
#Override
public void onItemClick(int position) {
//Do, what you need...
pos = holder.getAdapterPosition();
Log.e("postion", pos + "");
}
});
holder.recyclerViewShippingInfo.setAdapter(holder.shippingCustomAdapter);
} else {
}
}
#Override
public void onFailure(#NonNull Call<CheckOutShippingInfoModel> call, #NonNull Throwable t) {
hideProgressDialog();
t.printStackTrace();
Log.e("Shipping_Response", t.getMessage() + "");
}
});
} else {
Toast.makeText(getContext(), "Please Login", Toast.LENGTH_SHORT).show();
}
}
private int grandTotal() {
int totalPrice = 0;
for (int i = 0; i < moviesList.size(); i++) {
totalPrice += moviesList.get(i).getSubtotal();
// notifyDataSetChanged();
}
return totalPrice;
}
#Override
public int getItemCount() {
return moviesList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
RecyclerView recyclerViewShippingInfo;
private ShippingCustomAdapter shippingCustomAdapter;
private List<ResultCheckoutShippingInfo> resultCheckoutShippingInfo;
public MyViewHolder(View view) {
super(view);
recyclerViewShippingInfo = view.findViewById(R.id.recyclerViewShippingInfo);
recyclerViewShippingInfo.setLayoutManager(new GridLayoutManager(getContext(), 1));
recyclerViewShippingInfo.setHasFixedSize(true);
recyclerViewShippingInfo.setNestedScrollingEnabled(false);
}
}
}
Here is Another Adapter Code which inside the first adapter
public class ShippingCustomAdapter extends RecyclerView.Adapter<ShippingCustomAdapter.MyViewHolder> {
private List<ResultCheckoutShippingInfo> moviesList;
private RadioGroup lastCheckedRadioGroup = null;
private int lastSelectedPosition = 0;
boolean isSelected = false;
int previousSelectedPosition = -1;
ResultCallback callback;
public ShippingCustomAdapter(List<ResultCheckoutShippingInfo> moviesList, ResultCallback callback) {
this.moviesList = moviesList;
this.callback = callback;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_shipping_info, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final List<ResultCheckoutShippingInfo> datum = moviesList;
Log.e("POSI", pos + "--" + position + "");
holder.shipping_name.setText(datum.get(position).getType() + "");
RadioButton rb = new RadioButton(getContext());
holder.radio.addView(rb);
if (cartId.equals("Standard")) {
rb.setChecked(true);
}
if (cartId.equals("Economy")) {
rb.setChecked(true);
}
if (cartId.equals("Free")) {
rb.setChecked(true);
}
}
#Override
public int getItemCount() {
return moviesList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView shipping_name, shipping_price;
RadioGroup radio;
RadioButton radioShipping;
public MyViewHolder(View view) {
super(view);
shipping_name = view.findViewById(R.id.shipping_name);
shipping_price = view.findViewById(R.id.shipping_price);
radio = view.findViewById(R.id.price_grp);
radio.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (lastCheckedRadioGroup != null
&& lastCheckedRadioGroup.getCheckedRadioButtonId()
!= radioGroup.getCheckedRadioButtonId()
&& lastCheckedRadioGroup.getCheckedRadioButtonId() != -1) {
lastCheckedRadioGroup.clearCheck();
databaseHelper.updateShippingInfo(cartModel.get(pos).getId(), shipping_price.getText().toString() + "", ShippingCustomAdapter.this.moviesList.get(i).getTypeId() + "");
label_subTotal.setText("Shipping : " + shipping_value + "\n" + "Total Amount : " + mSubTotal);
}
lastCheckedRadioGroup = radioGroup;
callback.onItemClick(i);
}
});
}
}
}
Here is a database Query for updating value after radio button change
public void updateShippingInfo(String id, String shipping, String current_option) {
SQLiteDatabase db = this.getWritableDatabase();
String sql = "UPDATE " + TABLE_NAME + " SET " + " shipping" + " = " + "'" + shipping + "'" + ", current_option" + " = " + "'" + current_option + "'" + " WHERE " + "id" + " = '" + id + "'";
Log.e("QUERY", sql);
db.execSQL(sql);
}
Here is ResultCheckoutShippingInfo
public class ResultCheckoutShippingInfo {
#SerializedName("type")
#Expose
private String type;
#SerializedName("type_id")
#Expose
private String typeId;
#SerializedName("days")
#Expose
private String days;
#SerializedName("price")
#Expose
private String price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTypeId() {
return typeId;
}
public void setTypeId(String typeId) {
this.typeId = typeId;
}
public String getDays() {
return days;
}
public void setDays(String days) {
this.days = days;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
Here I want to update database value
shipping charges = price
current_option = TypeId
using its position
You need to create: one RecyclerView.Adapter with item, that contains: photo, price, + | - buttons, delete button and radioGroup, which have dynamic radioButtons count, created using cycle by List<ResultCheckoutShippingInfo>.
public class CartCustomAdapter extends RecyclerView.Adapter<CartCustomAdapter.MyViewHolder> {
private List<Cart> moviesList;
public CartCustomAdapter(List<Cart> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_cart_details, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
final List<Cart> datum = moviesList;
pos = holder.getAdapterPosition();
Log.e("POSI1", pos + "");
if (loginModel != null) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("option_name", TextUtils.join(",", Collections.singleton(datum.get(position).getShippingOption() + "")));
hashMap.put("weight", datum.get(position).getWeight() + "");
hashMap.put("zip", loginModel.getResultLogin().getZip() + "");
Log.e("Parms", hashMap + "");
showProgressDialog();
Call<CheckOutShippingInfoModel> checkOutShippingInfoModelCall = RetrofitHelper.createService(RetrofitHelper.Service.class).CheckOutShippingInfoModel(hashMap);
checkOutShippingInfoModelCall.enqueue(new Callback<CheckOutShippingInfoModel>() {
#Override
public void onResponse(#NonNull Call<CheckOutShippingInfoModel> call, #NonNull Response<CheckOutShippingInfoModel> response) {
CheckOutShippingInfoModel object = response.body();
hideProgressDialog();
if (object != null && object.getError() == false) {
Log.e("TAG", "Shipping_Response : " + new Gson().toJson(response.body()));
holder.resultCheckoutShippingInfo = object.getResultCheckoutShippingInfo();
//List<String> resultCheckoutShippingInfo = new ArrayList<>();
//resultCheckoutShippingInfo.add("Standard");
//resultCheckoutShippingInfo.add("Big cost");
for (ResultCheckoutShippingInfo info : holder.resultCheckoutShippingInfo){
RadioButton radioButton = new RadioButton(this);
radioButton.setText(info.name);
holder.radioShippingGroup.addView(radioButton);
//Check, if this element of radioGroup was checked in database and set checked it in radioGroup
if (info.isChecked()){
radioButton.setChecked(true);
}
}
holder.radioShippingGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
View radioButton = holder.radioShippingGroup.findViewById(checkedId);
int idx = holder.radioShippingGroup.indexOfChild(radioButton);
Log.i("TEST", "checkedId = " + Integer.toString(idx) + "; cartPosition = " + Integer.toString(position) + "; arraySize = " + Integer.toString(holder.resultCheckoutShippingInfo.size()));
databaseHelper.updateShippingInfo(
datum.get(position).getCartID,
holder.resultCheckoutShippingInfo.get(idx).getPrice() + "",
holder.resultCheckoutShippingInfo.get(idx).getTypeId() + "");
}
});
} else {
}
}
#Override
public void onFailure(#NonNull Call<CheckOutShippingInfoModel> call, #NonNull Throwable t) {
hideProgressDialog();
t.printStackTrace();
Log.e("Shipping_Response", t.getMessage() + "");
}
});
} else {
Toast.makeText(getContext(), "Please Login", Toast.LENGTH_SHORT).show();
}
}
private int grandTotal() {
int totalPrice = 0;
for (int i = 0; i < moviesList.size(); i++) {
totalPrice += moviesList.get(i).getSubtotal();
// notifyDataSetChanged();
}
return totalPrice;
}
#Override
public int getItemCount() {
return moviesList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
//RecyclerView recyclerViewShippingInfo;
//private ShippingCustomAdapter shippingCustomAdapter;
//private List<ResultCheckoutShippingInfo> resultCheckoutShippingInfo;
RadioGroup radioShippingGroup;
public MyViewHolder(View view) {
super(view);
radioShippingGroup = view.findViewById(R.id.radioShippingGroup);
//recyclerViewShippingInfo = view.findViewById(R.id.recyclerViewShippingInfo);
//recyclerViewShippingInfo.setLayoutManager(new GridLayoutManager(getContext(), 1));
//recyclerViewShippingInfo.setHasFixedSize(true);
//recyclerViewShippingInfo.setNestedScrollingEnabled(false);
}
}
}
I would suggest to use Listener pattern with few onChange callbacks. And pass it to one adapter to another. This would be cleaner solution.
I have a Fragment with a RecyclerView. users input data and they will store in a SQLite DataBase. i am trying to Search in the items of this RecyclerView but it does not work,
here is my Fragment :
public class FragmentOne extends Fragment {
private RecyclerView mDetailRecyclerView;
private DetailAdapter mAdapter;
private boolean mNumberVisible;
private SearchView sv;
private ArrayList<Detail> mDetails=new ArrayList<>();
private View view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_one_layout,
container, false);
mDetailRecyclerView = (RecyclerView) view.findViewById(R.id.detail_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setReverseLayout(true); //This will reverse the data order but not scroll the RecyclerView to the last item
layoutManager.setStackFromEnd(true); //For keeping data order same and simply scrolling the RecyclerView to the last item
mDetailRecyclerView.setLayoutManager(layoutManager);
if (savedInstanceState != null) {
mNumberVisible =
savedInstanceState.getBoolean(SAVED_NUMBER_VISIBLE);
}
sv = (SearchView) view.findViewById(R.id.sv);
mAdapter = new DetailAdapter(mDetails);
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit (String query) {
return false;
}
#Override
public boolean onQueryTextChange(String query) {
getDetailsSearch(query);
return false;
}
});
initViews();
updateUI();
return view;
}
#Override
public void onResume() {
super.onResume();
updateUI();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_NUMBER_VISIBLE, mNumberVisible);
}
..
..
private class DetailHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
private TextView mTitleTextView;
// private TextView mDateTextView;
private Detail mDetail;
private RatingBar mRatingBar;
public DetailHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.list_item_detail,
parent, false));
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
mTitleTextView = (TextView) itemView.findViewById(R.id.detail_title);
mRatingBar = (RatingBar) itemView.findViewById(R.id.ratingBar);
}
public void bind(Detail detail) {
mDetail = detail;
mTitleTextView.setText(mDetail.getTitle());
mRatingBar.setRating(mDetail.getRate());
}
#Override
public void onClick(View view) {
Intent intent = DetailPagerActivity.newIntent(getActivity(),
mDetail.getId());
startActivity(intent);
}
}
private class DetailAdapter extends RecyclerView.Adapter<DetailHolder> {
private List<Detail> mDetails;
private Detail mDetail;
public DetailAdapter(List<Detail> details) {
mDetails = details;
}
#Override
public DetailHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
return new DetailHolder(layoutInflater, parent);
}
#Override
public void onBindViewHolder(DetailHolder holder, int position) {
Detail detail = mDetails.get(position);
holder.bind(detail);
}
#Override
public int getItemCount() {
return mDetails.size();
}
public void setDetails(final List<Detail> details) {
mDetails = details;
}
..
..
}
public void initViews(){
mDetailRecyclerView.setAdapter(mAdapter);
initSwipe();
}
..
..
private void getDetailsSearch (String searchTerm) {
mDetails.clear();
DBAdapter db = new DBAdapter(getActivity());
db.openDB();
Detail p = null;
Cursor c = db.retrieve(searchTerm);
while (c.moveToNext()) {
String title = c.getString(2);
p = new Detail();
p.setTitle(title);
mDetails.add(p);
}
db.closeDB();
mDetailRecyclerView.setAdapter(mAdapter);
}
}
and this is my Database Adapter:
public class DBAdapter {
Context c;
SQLiteDatabase db;
DetailBaseHelper helper;
public DBAdapter (Context c) {
this.c = c;
helper = new DetailBaseHelper(c);
}
public void openDB() {
try {
db = helper.getWritableDatabase();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void closeDB() {
try {
helper.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public Cursor retrieve (String searchTerm) {
String[] columns = {
"_id",
"uuid",
"title",
"des",
"date",
"rate"
Cursor c = null;
if (searchTerm != null && searchTerm.length()>0) {
String sql ="SELECT * FROM " +DetailDbSchema.DetailTable.NAME+
" WHERE "+DetailDbSchema.DetailTable.Cols.TITLE+
" LIKE '%"+searchTerm+"%'";
c = db.rawQuery(sql, null);
return c;
}
c = db.query(DetailDbSchema.DetailTable.NAME, columns,
null, null, null, null, null);
return c;
}
}
and here is DataBase Helper:
public class DetailBaseHelper extends SQLiteOpenHelper{
private static final int VERSION = 1;
private static final String DATABASE_NAME = "detailBase.db";
public DetailBaseHelper (Context context) {
super(context, DATABASE_NAME, null, VERSION);
}
#Override
public void onCreate (SQLiteDatabase db) {
db.execSQL("create table " + DetailTable.NAME +
"(" +
" _id integer primary key autoincrement," +
DetailTable.Cols.UUID + ", " +
DetailTable.Cols.TITLE + ", " +
DetailTable.Cols.DES + ", " +
DetailTable.Cols.DATE + ", " +
DetailTable.Cols.RATE +
")"
);
}
#Override
public void onUpgrade (SQLiteDatabase db,
int oldVersion, int newVersion) {
}
}
here is the tutorial that i used for this,
I'll be appreciate if u have any idea for helping me.
I think that the main problem is here you're changing the adapter, but the new adapter was never modified by the data of the results, and also you have to notify your recycler that the data set changed. so
private void getDetailsSearch (String searchTerm) {
mDetails.clear();
/// the loop wiith the cursor
/// change the dataset
mAdapter = new DetailAdapter(mDetails);
mDetailRecyclerView.setAdapter(mAdapter);
/// tell the recycler there is a different data to display
mDetailRecyclerView.notifyDataSetChanged();
}
I have a problem with recycler, the problem is: I have AsyncTask which query data from my db, and then updating recycler by CursorLoader, but adapter doesn't fill recycler, Logs says that the data from db is successfully reading and then Adapter constructor successfully takes ArrayList with data, but that's all, logs says that adapter's methods doesn't call.
MainActivity :
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private SQLiteDatabase db;
private SimpleCursorLoader loader;
private MySimpleAdapter adapter;
private RecyclerView recycler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recycler = (RecyclerView) findViewById(R.id.recycler);
new SimpleTask(SimpleTask.OPEN, null).execute();
}
private class SimpleTask extends AsyncTask<Void, Void, Void> {
public static final int INSERT = 0;
public static final int DELETE = 1;
public static final int OPEN = 2;
private int task;
private String name;
public SimpleTask(int task, String name) {
this.task = task;
this.name = name;
}
#Override
protected Void doInBackground(Void... params) {
switch (task) {
case INSERT :
ContentValues values = new ContentValues();
values.put(SimpleHelper.KEY_NAME, name);
db.insert(SimpleHelper.TABLE_NAME, null, values);
break;
case DELETE :
db.delete(SimpleHelper.TABLE_NAME, SimpleHelper.KEY_NAME + " = ? ", new String[]{name});
break;
case OPEN :
if (db == null) {
try {
db = new SimpleHelper(MainActivity.this).getWritableDatabase();
} catch (SQLiteException e) {
e.printStackTrace();
}
}
break;
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
if (loader == null) {
loader = new SimpleCursorLoader(MainActivity.this, db);
loader.setQueryParams(SimpleHelper.TABLE_NAME, new String[]{SimpleHelper.KEY_NAME},
null, null);
getSupportLoaderManager().initLoader(0, null, MainActivity.this);
}
getSupportLoaderManager().getLoader(0).forceLoad();
}
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return loader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Log.i("MyLog", "onLoadFinished cursor size is " + data.getCount());
List<String> items = new ArrayList<>();
data.moveToFirst();
do {
items.add(data.getString(0));
Log.i("MyLog", data.getString(0));
} while (data.moveToNext());
Log.i("MyLog", "onLoadFinished items size is " + items.size());
if (adapter == null) {
adapter = new MySimpleAdapter(items);
recycler.setAdapter(adapter);
} else {
adapter.updateAdapter(items);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
private class MySimpleAdapter extends RecyclerView.Adapter<MySimpleAdapter.MyHolder> {
private List<String> items;
public MySimpleAdapter(List<String> items) {
Log.i("MyLog", "Constructor called with items size " + items.size());
this.items = items;
}
public class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView tvText;
public MyHolder(View itemView) {
super(itemView);
tvText = (TextView) itemView.findViewById(android.R.id.text1);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
new SimpleTask(SimpleTask.DELETE, tvText.getText().toString());
}
}
public void updateAdapter(List<String> items) {
this.items = items;
notifyDataSetChanged();
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i("MyLog", "onCreateViewHolder");
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, null, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.tvText.setText(items.get(position));
Log.i("MyLog", "onBindViewHolder setText : " + items.get(position));
}
#Override
public int getItemCount() {
Log.d("MyLog", "getItemCount called with size : " + items.size());
return items.size();
}
}
SimpleCursorLoader :
public class SimpleCursorLoader extends CursorLoader {
private SQLiteDatabase db;
private String tableName;
private String[] columns;
public SimpleCursorLoader(Context context, SQLiteDatabase db) {
super(context);
this.db = db;
}
public void setQueryParams(String tableName, String[] columns, String selection, String[] selectionArgs) {
this.tableName = tableName;
this.columns = columns;
setSelection(selection);
setSelectionArgs(selectionArgs);
}
#Override
public Cursor loadInBackground() {
Cursor cursor = db.query(tableName, columns, getSelection(), getSelectionArgs(),
null, null, null);
return cursor;
}
DBHelper :
public class SimpleHelper extends SQLiteOpenHelper{
public static final String TABLE_NAME = "users";
public static final String KEY_NAME = "name";
public static final String KEY_ID = "_id";
private static final int DB_VERSION = 1;
private static final String DB_NAME = "SimpleDB";
public SimpleHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + "("
+ KEY_ID + " integer primary key autoincrement, "
+ KEY_NAME + " text)");
for (int i = 0; i < 5; i ++) {
ContentValues values = new ContentValues();
values.put(KEY_NAME, "name" + i+1);
db.insert(TABLE_NAME, null, values);
Log.i("MyLog", "inserted");
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Use this.
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setHasFixedSize(true);
recycler.setNestedScrollingEnabled(false);
i made RecyclerView to display data from Mysql and it work good now i want to make a favourite button when i clicked on it save this item in a favourite and display it in new activity in RecyclerView
I think i should use Sqlite to save data in it then display in favourite activity but i don't know how i can make that please help me
I tried to make Sqlite
public class DB_Sqlit extends SQLiteOpenHelper {
public static final String BDname = "mdata.db";
public DB_Sqlit(Context context) {
super(context, BDname, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table favorite ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, img TEXT, url TEXT, num TEXT, size TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS favorite");
onCreate(db);
}
public Boolean Insert_to_favorite(String name, String img, String url, String num, String size) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("img", img);
contentValues.put("url", url);
contentValues.put("num", num);
contentValues.put("size", size);
long result = db.insert("favorite", null, contentValues);
if (result == -1)
return false;
else
return true;
}
public ArrayList getAllList_Favorite() {
ArrayList<listitem_gib> arraylist = new ArrayList<listitem_gib>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor rs = db.rawQuery("select * from favorite", null);
rs.moveToFirst();
while (!rs.isAfterLast()) {
String id = rs.getString(rs.getColumnIndex("id"));
String name = rs.getString(rs.getColumnIndex("name"));
String img = rs.getString(rs.getColumnIndex("img"));
String url = rs.getString(rs.getColumnIndex("url"));
String num = rs.getString(rs.getColumnIndex("num"));
String size = rs.getString(rs.getColumnIndex("size"));
arraylist.add(new listitem_gib());
rs.moveToNext();
}
return arraylist;
}
public int get_check_List_Favorite(String Title) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor rs = db.rawQuery("select * from favorite Where name like '"+ Title +"'", null);
rs.moveToFirst();
int count = rs.getCount();
return count;
}
public Integer Delete(String id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete("favorite", "id = ?", new String[]{id});
}}
RecyclerView Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_r_arabic);
GetDataAdapter1 = new ArrayList<>();
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
recyclerView.setHasFixedSize(true);
recyclerViewlayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(recyclerViewlayoutManager);
progress_layout = (LinearLayout) findViewById(R.id.progress_layout);
progress_layout.setVisibility(View.VISIBLE);
JSON_DATA_WEB_CALL();
}
public void JSON_DATA_WEB_CALL(){
Intent intent = getIntent();
story_type = intent.getStringExtra("story_type");
String GET_JSON_DATA_HTTP_URL = "http://grassyhat.com/android/" + story_type + ".php";
jsonArrayRequest = new JsonArrayRequest(GET_JSON_DATA_HTTP_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
progress_layout.setVisibility(View.GONE);
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonArrayRequest);
}
public void JSON_PARSE_DATA_AFTER_WEBCALL(JSONArray array){
for(int i = 0; i<array.length(); i++) {
listitem_gib GetDataAdapter2 = new listitem_gib();
JSONObject json = null;
try {
json = array.getJSONObject(i);
GetDataAdapter2.setId(json.getString(id));
GetDataAdapter2.setName(json.getString(name));
GetDataAdapter2.seturl(json.getString(url));
GetDataAdapter2.setimg(json.getString(img));
GetDataAdapter2.setnum(json.getString(num));
GetDataAdapter2.setsize(json.getString(size));
} catch (JSONException e) {
e.printStackTrace();
}
GetDataAdapter1.add(GetDataAdapter2);
}
recyclerViewadapter = new RecyclerViewAdapter(GetDataAdapter1, this);
//RecyclerView needs a layout manager in order to display data so here we create one
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
//Here we set the layout manager and the adapter to the listview
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerViewadapter);
}
RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
List<listitem_gib> getDataAdapter;
public RecyclerViewAdapter(List<listitem_gib> getDataAdapter, Context context){
super();
this.getDataAdapter = getDataAdapter;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(v,context,getDataAdapter);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
listitem_gib getDataAdapter1 = getDataAdapter.get(position);
holder.name.setText(getDataAdapter1.getName());
holder.num.setText(getDataAdapter1.getnum());
Picasso.with(context).load("http://grassyhat.com/android/image/" + getDataAdapter1.getimg()).into(holder.img1);
}
#Override
public int getItemCount() {
return getDataAdapter.size();
}
class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener{
public TextView name;
public TextView num;
public ImageView img1;
Context context;
List<listitem_gib> getDataAdapter;
public ViewHolder(View itemView, Context context ,List<listitem_gib> getDataAdapter ) {
super(itemView);
itemView.setOnClickListener(this);
this.getDataAdapter = getDataAdapter;
this.context = context;
name = (TextView) itemView.findViewById(R.id.Main_Text) ;
num = (TextView) itemView.findViewById(R.id.Second_Text) ;
img1 = (ImageView) itemView.findViewById(R.id.img1) ;
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
listitem_gib getDataAdapter =this.getDataAdapter.get(position);
Intent intent = new Intent(this.context,Rewaya_info.class);
intent.putExtra("name",getDataAdapter.getName());
intent.putExtra("url",getDataAdapter.geturl());
intent.putExtra("img",getDataAdapter.getimg());
intent.putExtra("num",getDataAdapter.getnum());
intent.putExtra("size",getDataAdapter.getsize());
this.context.startActivity(intent);
}
}}
ListItem
public class listitem_gib {
String id;
String name;
String url;
String img;
String num;
String size;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getid() {
return id;
}
public void setId(String id1) {
this.id = id1;
}
public String geturl() {
return url;
}
public void seturl(String url1) {
this.url = url1;
}
public String getimg() {
return img;
}
public void setimg(String img1) {
this.img = img1;
}
public String getnum() {
return num;
}
public void setnum(String num1) {
this.num = num1;
}
public String getsize() {
return size;
}
public void setsize(String size1) {
this.size = size1;
}}
you need to use SQLite database to store fav items data offline
create one table containing all data fields by make a class extends SQLiteOpenHelper and override onCreate() to write your create table command in it, and you don't need to write anything in onUpdate() method in your case
in your Detail activity make a button for fav which will implement insert this item in the SQLite database
to view the data from SQLite in RecyclerView:
make an arraylist from your item type "class"
retrieve each item data from SQLite database using cursor
add item data in the arraylist and send it to the adapter of the RecyclerView
you can use this tutorial to build RecyclerView :
Arabic Version
or English Version
I have one RecyclerView and my method in RecyclerView adapter is working, but only for position i select and for example, when i click image with sign X i'm deleting first item which i positioned in remove method, but i want this to happens when user click image with sign X, to give him ability to select what item from the list he will delete.
Also i would like to delete that item from SQLite, but my method isn't good probably in helper class.
Here is MainActivity:
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
GridAdapter mGridAdapter;
DBHelper dbh;
String firstName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
initAddImage();
dbh = new DBHelper(this);
initRecyclerView();
initDeleteImage();
}
public List<Birthday> getData() {
List<Birthday> birthdays = new ArrayList<>();
Birthday birthday = null;
Cursor c = dbh.getBirthdayData();
if (c != null) {
while (c.moveToNext()) {
int nameIndex = c.getColumnIndex(dbh.BIRTHDAY_NAME);
String nameText = c.getString(nameIndex);
this.firstName = nameText;
int lastNameIndex = c.getColumnIndex(dbh.BIRTHDAY_LAST_NAME);
String lastNameText = c.getString(lastNameIndex);
birthday = new Birthday();
birthday.setNAME(nameText);
birthday.setLAST_NAME(lastNameText);
birthdays.add(birthday);
}
}
return birthdays;
}
private void initRecyclerView(){
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setItemAnimator(new ScaleInAnimator());
// The number of Columns
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new GridLayoutManager(this, 3);
mRecyclerView.setLayoutManager(mLayoutManager);
mGridAdapter = new GridAdapter(getData());
mRecyclerView.setAdapter(mGridAdapter);
}
private void initAddImage(){
ImageView addImage = (ImageView) findViewById(R.id.add_image);
addImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AddBirthday.class);
startActivity(intent);
}
});
}
private void initDeleteImage(){
ImageView deleteImage = (ImageView) findViewById(R.id.delete_image);
deleteImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mGridAdapter.removeItem(0);
}
});
}
#Override
protected void onResume() {
super.onResume();
initRecyclerView();
}
}
Here is my RecyclerView Adapter:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.MyViewHolder> {
private List<Birthday> birthdays;
DBHelper dbh;
public GridAdapter(List<Birthday> birthdays){
this.birthdays = birthdays;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
CustomTextView firstName, lastName;
TextView dateOfBirthday;
public MyViewHolder(View itemView) {
super(itemView);
firstName = (CustomTextView) itemView.findViewById(R.id.first_name);
lastName = (CustomTextView) itemView.findViewById(R.id.last_name);
dateOfBirthday = (TextView) itemView.findViewById(R.id.date_of_birthday);
}
}
public void removeItem(int position) {
birthdays.remove(position);
notifyItemRemoved(position);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
MyViewHolder holder = new MyViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.firstName.setText(birthdays.get(position).getNAME());
holder.lastName.setText(birthdays.get(position).getLAST_NAME());
}
#Override
public int getItemCount() {
return birthdays.size();
}
}
And here is my Database: Method for deleting item is at the bottom of class
public class DBHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "_database";
private static final String BIRTHDAY_TABLE_NAME = "birthday_table";
public static final String BIRTHDAY_ID = "birthday_id";
public static final String BIRTHDAY_NAME = "birthday_name";
public static final String BIRTHDAY_LAST_NAME = "birthday_last_name";
private static final String CREATE_BIRTHDAY_TABLE = "CREATE TABLE " + BIRTHDAY_TABLE_NAME +
" ( " + BIRTHDAY_ID + " INTEGER PRIMARY KEY,"
+ BIRTHDAY_NAME + " TEXT," + BIRTHDAY_LAST_NAME + " TEXT );";
SQLiteDatabase database;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BIRTHDAY_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + BIRTHDAY_TABLE_NAME);
onCreate(db);
}
public void setBirthdayData(String birthdayName, String birthdayLastName) {
database = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(BIRTHDAY_NAME, birthdayName);
cv.put(BIRTHDAY_LAST_NAME, birthdayLastName);
database.insert(BIRTHDAY_TABLE_NAME, null, cv);
}
public Cursor getBirthdayData() {
database = getReadableDatabase();
String[] columns = {BIRTHDAY_ID, BIRTHDAY_NAME, BIRTHDAY_LAST_NAME};
Cursor c = database.query(BIRTHDAY_TABLE_NAME, columns, null, null, null, null, BIRTHDAY_ID + " DESC");
return c;
}
public Cursor getBirthdayName(String[] args) {
database = getReadableDatabase();
String query = "SELECT " + BIRTHDAY_NAME + " FROM " + BIRTHDAY_TABLE_NAME + " WHERE " + BIRTHDAY_NAME + " =?";
Cursor c = database.rawQuery(query, args);
return c;
}
public boolean deleteItem(long rowId) {
SQLiteDatabase db = getWritableDatabase();
return db.delete(BIRTHDAY_TABLE_NAME, BIRTHDAY_ID + "=" + rowId, null) > 0;
}
}
Assume your X sign is an ImageButton
Add the ImageButton in your grid_item.xml
In your MyViewHolder add ImageView as item named deleteItem
In OnBindViewHolder
`holder.deleteItem.setOnclickListener(new OnClickListener(){
#Override
public void onClick(View v){
dbHelper.deleteItem(birthdays.get(position).getItemId); /* you pass birthday id to a method deleteItem() in your DBHelper.java */
birthdays.remove(position);
GridAdapter.this.notifyDataSetChanged();
});`
deleteItem(long birthdayId) method
deleteItem(long birthdayId){
return database.delete(BIRTHDAY_TABLE_NAME, BIRTHDAY_ID + " = '" + birthdayId +"'", null, null, null, null);
}