in my adapter items can be selectable for show popup such as copy, cut or etc, now how can i get selected part of text on recyclerView item and position? i read more document about found this solution but i dont know how can i do that
this is my adapter which i would like to get selected part of text and postion:
public class ShowBookContentsAdapter extends RecyclerView.Adapter<ShowBookContentsAdapter.ShowBookContentsViewHolder> {
private List<Contents> list;
private Context context;
...
private fontFace setFontFace = fontFace.SHABNAM;
public ShowBookContentsAdapter(List<Contents> items, Context mContext, IonChangeBottomViewVisibility mOnChangeBottomViewVisibility, IonSelectText mIonSelectText) {
list = items;
context = mContext;
ionChangeBottomViewvisibility = mOnChangeBottomViewVisibility;
ionSelectText = mIonSelectText;
}
#Override
public ShowBookContentsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layout = -1;
switch (viewType) {
case 0:
layout = R.layout.item_book_content_paragraph;
break;
}
view = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
holder = new ShowBookContentsViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(ShowBookContentsViewHolder holder, final int position) {
switch (list.get(position).getContentType()) {
case 0:
makeSelectable(holder.book_content_paragraph);
implementingParagraphView(holder, position);
break;
}
}
private void implementingParagraphView(final ShowBookContentsViewHolder mHolder, final int position) {
holder = mHolder;
String content = list.get(position).getContent();
mHolder.book_content_paragraph.removeAllViews();
try {
Reader reader = new StringReader(content);
KetabkhanView ketabkhan = new KetabkhanView(context);
KetabkhanTagProcessor ketabkhanTagProcessor = new KetabkhanTagProcessor();
ketabkhanTagProcessor.parse(reader, ketabkhan);
mHolder.book_content_paragraph.addView(ketabkhan);
} catch (Exception e) {
e.printStackTrace();
Log.e("E ", e.getMessage());
throw new RuntimeException(e);
}
makeSelectable(mHolder.book_content_paragraph);
if (setFontFace == fontFace.SHABNAM)
Utils.overrideFonts(context, mHolder.book_content_paragraph, PersianFontType.SHABNAM);
else if (setFontFace == fontFace.SAHEL)
Utils.overrideFonts(context, mHolder.book_content_paragraph, PersianFontType.SAHEL);
//for show and hide bottom view
mHolder.book_content_paragraph.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ionChangeBottomViewvisibility != null) {
ionChangeBottomViewvisibility.onChange();
}
}
});
}
...
private void makeSelectable(ViewGroup viewGroup) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof ViewGroup) {
makeSelectable((ViewGroup) child);
} else if (child instanceof TextView) {
((TextView) child).setTextIsSelectable(true);
((TextView) child).setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize == 0 ? 14 : textSize);
}
}
}
#Override
public int getItemViewType(int position) {
return list.get(position).getContentType();
}
#Override
public int getItemCount() {
return list.size();
}
public int getItemPosition(int itemId) {
return itemPositions.get(itemId);
}
public void setData(List<Contents> mContents) {
list.clear();
list.addAll(mContents);
}
public class ShowBookContentsViewHolder extends RecyclerView.ViewHolder {
#Nullable
#BindView(R.id.book_content_paragraph)
LinearLayout book_content_paragraph;
...
public ShowBookContentsViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
i make selectable text on items by this method: makeSelectable()
I have implemented the same using custom ActionMode Callback. We can set the custom Action Mode callback to a particular textview of recycler view item by setting textView.customSelectionActionModeCallback in the onBindViewHolder of recyclerView Adapter. In the custom Callback we can use the current position and selected text.
onBindViewHolder will look like this.
public void onBindViewHolder(myViewHolder holder, int position) {
//code
holder.textview. setCustomSelectionActionModeCallback(new CustomSelectionCallback(holder.taskName, position, mContext));
}
In the custom Callback we can send anything along with the position of the item.
Custom Selection Callback can be implemented as follows.
public class CustomSelectionCallback implements ActionMode.Callback {
private TextView mTextView;
private int position;
private Context mContext;
public CustomSelectionCallback(TextView text, int pos, Context context) {
this.mTextView = text;
this.position = pos;
this.mContext = context;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int start = mTextView.getSelectionStart();
int end = mTextView.getSelectionEnd();
Spannable wordtoSpan = (Spannable) mTextView.getText();
wordtoSpan.setSpan(new BackgroundColorSpan(Color.TRANSPARENT), start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//copy the text when Copy Action Mode is clicked
if (item.getItemId() == android.R.id.copy) {
copyText(start, end);
mode.finish();
return true;
} else if (item.getItemId() == android.R.id.shareText) {
shareText(start, end);
mode.finish();
return true;
} else if (item.getItemId() == android.R.id.selectAll) {
selectAllText();
return true;
}
return true;
}
/**
* implement select all functionality id ActionMOde Menu
*/
private void selectAllText() {
Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.length());
}
private void shareText(int start, int end) {
CharSequence selectedTxt = mTextView.getText().subSequence(start, end);
String shareBody = selectedTxt.toString();
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
mContext.startActivity(Intent.createChooser(sharingIntent, "SHARE"));
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
/**
* copy the selected text with start and end param to clipboard
*
* #param start start point of selection of the text view
* #param end end point of selection of the text view
*/
private void copyText(int start, int end) {
ClipboardManager clipboardManager = (ClipboardManager) mContext.
getSystemService(Context.CLIPBOARD_SERVICE);
CharSequence selectedTxt = mTextView.getText().subSequence(start, end);
ClipData clipData = ClipData.newPlainText("selected text label", selectedTxt);
assert clipboardManager != null;
clipboardManager.setPrimaryClip(clipData);
Toast.makeText(mContext, selectedTxt.toString() + " position " + position, Toast.LENGTH_LONG).show();
}
}
Related
I am trying to get position of the clicked item in RecyclerView. In adapter class, I am trying to create intent and send clicked item's contents. Also I created popup menu for two option. It is in adapter class too. onBindViewHolder position is works for puting contents in the rows of RecyclerView. However I couldn't reach that position from outside of method.
This is adapter class.
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements PopupMenu.OnMenuItemClickListener {
public ArrayList<MovieModel.Results> resultList;
public Context context;
public RecyclerViewAdapter(ArrayList<MovieModel.Results> list, Context context) {
this.resultList = list;
this.context = context;
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView posterImage;
ImageView addIcon;
TextView movieName;
TextView date;
TextView overview;
public ViewHolder(#NonNull View itemView) {
super(itemView);
posterImage = itemView.findViewById(R.id.movie_poster);
addIcon = itemView.findViewById(R.id.addImage);
movieName = itemView.findViewById(R.id.movieNameText);
date = itemView.findViewById(R.id.dateText);
overview = itemView.findViewById(R.id.overviewText);
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_2, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if (position < getItemCount()) {
String title = resultList.get(position).getTitle();
String date = resultList.get(position).getRelease_date();
String overview = resultList.get(position).getOverview();
String posterPath = resultList.get(position).getPoster_path();
holder.movieName.setText(title);
holder.date.setText(date);
holder.overview.setText(overview);
if (posterPath == null) {
holder.posterImage.setImageDrawable(context.getDrawable(R.drawable.no_poster));
} else {
Glide.with(context).load(FeedActivity.BASE_PHOTO_URL + posterPath).into(holder.posterImage);
}
int finalPosition = position;
holder.addIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(context, "You clicked : " + finalPosition, Toast.LENGTH_SHORT).show();
showPopup(v);
}
});
}
position++;
}
private void showPopup(View v) {
PopupMenu popup = new PopupMenu(context,v);
popup.setOnMenuItemClickListener(this);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu, popup.getMenu());
popup.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
// Here I need to position of clicked item in Recyclerview, and I will get title, date etc.
int pos;
if(item.getItemId() == R.id.menuAdd){
// Find here to get position of clicked movie.
String title = resultList.get(pos).getTitle();
String date = resultList.get(pos).getRelease_date();
String overview = resultList.get(pos).getOverview();
String posterpath = resultList.get(pos).getPoster_path();
Intent intent1 = new Intent(context,ListActivity.class);
intent1.putExtra("title",title);
intent1.putExtra("date",date);
intent1.putExtra("overview",overview);
intent1.putExtra("posterpath",posterpath);
context.startActivity(intent1);
return true;
}
else if(item.getItemId() == R.id.menuShowDetails){
int movieId = resultList.get(pos).getMovieId();
Intent intent1 = new Intent(context, MovieDetails.class);
intent1.putExtra("movie_id",movieId);
context.startActivity(intent1);
return true;
}
return false;
}
#Override
public int getItemCount() {
return resultList.size();
}
}
You can use the ViewHolder's getAdapterPosition() to retrieve the item's position within an interface method. Then store the clicked position in a member variable.
Additionally, there shouldn't be a need to call position++ from within your onBindViewHolder.
// Create a member variable to store the clicked position
public int clickedPos = -1;
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// ...
holder.addIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// When you're inside the click listener interface,
// you can access the position using the ViewHolder.
// We'll store the position in the member variable in this case.
clickedPos = holder.getAdapterPosition();
}
});
// Remove the 'position++' call as the position should already be handled without explicitly updating it.
}
#Override
public boolean onMenuItemClick(MenuItem item) {
// You can use clickedPos here to perform whatever tasks you need.
// ...
}
I am trying to make an application with a ListView that include a Country Flag and name. This is so that the user can click on them and be shown images of the country that they wouldve taken before. However for about 3 seconds when the listview loads if i try to scroll it will sort of glitch and send me back to top. This is the code..
public class CountriesListAdapter extends ArrayAdapter {
private int resource;
private LayoutInflater inflater;
private List<CountryModel> countryModels;
private WeakReference<TextView> selectedCountryIdtxt;
private boolean useFilter;
private WeakReference<ProgressBar> progressBarWeakReference;
public int getSelectedCountryId() {
return selectedCountryId;
}
public void setSelectedCountryId(int selectedCountryId) {
this.selectedCountryId = selectedCountryId;
}
private int selectedCountryId;
public CountriesListAdapter(#NonNull WeakReference<Context> context, int resourceId, WeakReference<TextView> textView, #NonNull List<CountryModel> countryModelList, boolean useFilter, WeakReference<ProgressBar> progressBarWeakReference){
super(context.get(), resourceId, countryModelList);
selectedCountryIdtxt = textView;
resource = resourceId; //the id of the template file
inflater = LayoutInflater.from(context.get());
this.countryModels = countryModelList;
selectedCountryId = -1;
this.useFilter = useFilter;
this.progressBarWeakReference = progressBarWeakReference;
}
public int getCount() {
if (countryModels != null)
return countryModels.size();
return 0;
}
public CountryModel getItem(int position) {
if (countryModels != null)
return countryModels.get(position);
return null;
}
public long getItemId(int position) {
if (countryModels != null)
return countryModels.get(position).hashCode();
return 0;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
// this method is automatically called for every object in our list
//basically it's called for every single row before it is generated
// this method is called per row
convertView = (ConstraintLayout) inflater.inflate(resource, null);
//the variable countryModel is fiiled with current object that is being processed
final CountryModel countryModel = countryModels.get(position);
TextView countryName = convertView.findViewById(R.id.countryNamelbl);
final ImageView countryFlag = convertView.findViewById(R.id.countryFlagimg);
final ImageView checked = convertView.findViewById(R.id.countryCheckedimg);
//this is done for every object in the list
assert countryModel != null;
countryName.setText(countryModel.getName());
Picasso.get().load(countryModel.getImage()).fit().into(countryFlag);
if(!useFilter) {
if (selectedCountryId == countryModel.getId()) {
checked.setVisibility(View.VISIBLE);
} else {
checked.setVisibility(View.INVISIBLE);
}
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!useFilter) {
if (checked.getVisibility() == View.VISIBLE) {
checked.setVisibility(View.INVISIBLE);
selectedCountryId = -1;
selectedCountryIdtxt.get().setText(String.valueOf(selectedCountryId));
} else {
if (selectedCountryId == -1) {
checked.setVisibility(View.VISIBLE);
selectedCountryId = countryModel.getId();
} else {
selectedCountryId = countryModel.getId();
notifyDataSetChanged();
}
selectedCountryIdtxt.get().setText(String.valueOf(selectedCountryId));
}
} else {
Intent i = new Intent(getContext(), PicturesActivity.class);
i.putExtra("countryId",countryModel.getId());
i.putExtra("countryName", countryModel.getName());
getContext().startActivity(i);
}
}
});
progressBarWeakReference.get().setVisibility(View.INVISIBLE);
return convertView;
}
public List<CountryModel> getCountryModels() {
return countryModels;
}
public void setCountryModels(List<CountryModel> countryModels) {
this.countryModels = countryModels;
}
}
The problem was actually in another class, i was calling the adapter for every list item instead of just once... oops.
Thanks for the replies though!
In my app, I want to delete the images, which i have done, but every time I delete image, it doesn't refresh the recyclerView. But when I again open the folder then Recyclerview is refreshed..
I want to refresh Recyclerview when image is deleted
Here is my code for Deleting an image
#Override
protected void onExternalStoragePermissionGranted() {
super.onExternalStoragePermissionGranted();
storage = SimpleStorage.getExternalStorage();
checkForGalleryDirectories();
File galleryFiles = new File(path);
pathContainerView.removeAllViews();
pathContainerView.addView(createTitleView("Location: " + galleryFiles.getAbsolutePath()));
File[] files = galleryFiles.listFiles();
List<GalleryItem> galleryItems = new ArrayList<>();
String lastModifiedDate = "UNDEFINED";
SimpleDateFormat formatter = new SimpleDateFormat("E-MMM-yyyy");
if (files != null) {
this.adapter.clearGallery();
for (File file : files) {
if (file.isDirectory()) {
}
String formattedPicDate = formatter.format(lastMod);
if (lastModifiedDate != null && !lastModifiedDate.equals(formattedPicDate)) {
lastModifiedDate = formattedPicDate;
galleryItems.add(new Header(lastModifiedDate));
countgridsize++;
}
galleryItems.add(new Picture(file.getPath(), file.getName()));
}
}
}
this.adapter.setGalleryList(galleryItems);
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
final List<String> list = GalleryAdapter.list;
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked
Toast.makeText(GalleryBrowserActivity.this, "Delete Successfully..", Toast.LENGTH_SHORT).show();
for (String fileNameStr : list) {
String[] parts = fileNameStr.split("/");
String part1 = parts[5]; // 004
String part2 = parts[6]; // 034556
storage.deleteFile(".AliRehman/" + part1, part2);
}
break;
case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(GalleryBrowserActivity.this);
builder.setMessage("Are you sure?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
return true;
My adapter Class
public class GalleryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context context;
private final LayoutInflater layoutInflater;
private List<GalleryItem> galleryList = new ArrayList<>();
private OnItemClickListener mItemClickListener;
public static List<String> list;
public GalleryAdapter(Context context, LayoutInflater layoutInflater) {
this.context = context;
this.layoutInflater = layoutInflater;
}
public void setItemClickListener(OnItemClickListener listener) {
mItemClickListener = listener;
}
public void setGalleryList(List<GalleryItem> galleryList) {
this.galleryList = galleryList;
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return this.galleryList.get(position).getItemType();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == GalleryItem.HEADER_TYPE) {
return new HeaderHolder(layoutInflater.inflate(R.layout.item_header, parent, false));
} else {
return new PictureHolder(layoutInflater.inflate(R.layout.item_picture, parent, false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
GalleryItem item = galleryList.get(position);
if(getItemViewType(position) == GalleryItem.HEADER_TYPE) {
bindHeaderHolder((HeaderHolder) holder, (Header) item);
}
else {
bindPictureHolder((PictureHolder) holder, (Picture) item);
}
}
private void bindPictureHolder(final PictureHolder holder, Picture picture) {
Glide.with(context).load(Uri.fromFile(new File(picture.getPath()))).into(holder.pictureThumbnail);
boolean itemselected=picture.getSelected();
if(itemselected)
{
Log.d("ViewVisiblePicture", String.valueOf(picture.getPath()));
holder.overlayView.setVisibility(View.VISIBLE);
}
else
holder.overlayView.setVisibility(View.GONE);
}
private void bindHeaderHolder(HeaderHolder holder, Header header) {
holder.headerTxt.setText(header.getName());
}
#Override
public int getItemCount() {
return this.galleryList.size();
}
public void clearGallery() {
this.galleryList.clear();
notifyDataSetChanged();
}
public class HeaderHolder extends RecyclerView.ViewHolder {
private TextView headerTxt;
public HeaderHolder(View itemView) {
super(itemView);
this.headerTxt = (TextView) itemView.findViewById(R.id.headerTxt);
}
}
public class PictureHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public ImageView pictureThumbnail;
public FrameLayout overlayView;
public PictureHolder pictureHolder;
private boolean[] thumbnailsselection;
public PictureHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
this.pictureThumbnail = (ImageView) itemView.findViewById(R.id.pictureThumbnail);
this.overlayView = (FrameLayout) itemView.findViewById(R.id.overlayView);
}
#Override
public boolean onLongClick(View view) {
list=new ArrayList<>();
if (mItemClickListener != null) {
mItemClickListener.onItemLongClick(getAdapterPosition());
this.overlayView.setVisibility(View.VISIBLE);
Picture model=(Picture) galleryList.get(getAdapterPosition());
//galleryList.get(getAdapterPosition());
model.setSelected(true);
list.add(model.getPath());
Log.d("Path1", model.getPath());
final int len = GalleryBrowserActivity.countgridsize;
int count = 0;
/* String selectImages = "";
for (int i = 0; i < len; i++) {
*//*if (pictureHolder..get(i).selection) {
count++;
selectImages = selectImages
+ pictureHolder.images.get(i).id + ",";
}*//*
this.overlayView.setVisibility(View.VISIBLE);
}
Log.d("Length", len+"");
if (count == 0) {
Toast.makeText(context,
"Please select at least one image",
Toast.LENGTH_LONG).show();
}*/
return true;
}
Log.d("hi","hello Image");
notifyDataSetChanged();
return false;
}
#Override
public void onClick(View v)
{
int position = getAdapterPosition();
Picture picture = (Picture) galleryList.get(position);
if(GalleryBrowserActivity.mActionMode!=null)
{
Log.d("Visiblilty","visible");
Picture model=(Picture) galleryList.get(getAdapterPosition());
if(model.getSelected()){
this.overlayView.setVisibility(View.GONE);
model.setSelected(false);
list.remove(model.getPath());
}else {
mItemClickListener.onItemClick(position, v, picture.getPath());
Toast.makeText(context, "visible" + picture.getPath(), Toast.LENGTH_LONG).show();
this.overlayView.setVisibility(View.VISIBLE);
model.setSelected(true);
list.add(model.getPath());
Log.d("Path2", model.getPath());
}
notifyDataSetChanged();
}
if (GalleryBrowserActivity.mActionMode==null) {
Log.d("Visible","invisible");
Toast.makeText(context,"invisible",Toast.LENGTH_LONG).show();
mItemClickListener.onItemClick(position, v, picture.getPath());
}
}
}
public interface OnItemClickListener
{
void onItemClick(int position, View v, String picturePath);
void onItemLongClick(int position);
}
}
I would suggest you to make below changes:
In GalleryAdapter :
From:
public static List<String> list;
To:
public static List< GalleryItem > list;
And add a function in your GalleryAdapter to remove items from your galleryList:
public void removeItem(GalleryItem item){
this.galleryList.remove(item);
notifyDataSetChanged();
}
And In PictureHolder:
#Override
public boolean onLongClick(View view) {
list=new ArrayList<>();
if (mItemClickListener != null) {
mItemClickListener.onItemLongClick(getAdapterPosition());
this.overlayView.setVisibility(View.VISIBLE);
GalleryItem model=(GalleryItem) galleryList.get(getAdapterPosition());
//galleryList.get(getAdapterPosition());
((Picture)model).setSelected(true);
list.add(model);
Log.d("Path1", ((Picture)model).getPath());
final int len = GalleryBrowserActivity.countgridsize;
int count = 0;
return true;
}
Log.d("hi","hello Image");
notifyDataSetChanged();
return false;
}
#Override
public void onClick(View v)
{
int position = getAdapterPosition();
GalleryItem picture = (GalleryItem) galleryList.get(position);
if(GalleryBrowserActivity.mActionMode!=null)
{
Log.d("Visiblilty","visible");
GalleryItem model=(GalleryItem) galleryList.get(getAdapterPosition());
if(model.getSelected()){
this.overlayView.setVisibility(View.GONE);
((Picture)model).setSelected(false);
list.remove(model);
}else {
mItemClickListener.onItemClick(position, v, picture.getPath());
Toast.makeText(context, "visible" + picture.getPath(), Toast.LENGTH_LONG).show();
this.overlayView.setVisibility(View.VISIBLE);
((Picture)model).setSelected(true);
list.add(model);
Log.d("Path2", model.getPath());
}
notifyDataSetChanged();
}
if (GalleryBrowserActivity.mActionMode==null) {
Log.d("Visible","invisible");
Toast.makeText(context,"invisible",Toast.LENGTH_LONG).show();
mItemClickListener.onItemClick(position, v, picture.getPath());
}
}
In the above code I am trying to update the list with selected GallryItem objects.
And While deleting item after the DialogInterface.BUTTON_POSITIVE is clicked, update the code like below:
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked
Toast.makeText(GalleryBrowserActivity.this, "Delete Successfully..", Toast.LENGTH_SHORT).show();
for (GalleryItem item : list) {
this.adapter.removeItem(item);
String fileNameStr = ((Picture)item).getPath();
String[] parts = fileNameStr.split("/");
String part1 = parts[5]; // 004
String part2 = parts[6]; // 034556
storage.deleteFile(".AliRehman/" + part1, part2);
}
break;
The above code will also update the galleryList inside adapter and notify the dataset change. Please let me know if you face any issue while implementing it.
you have to notify your adapter after you delete your image. like below.
arrayAdapter.notifyDataSetChanged();
in your example you have to write above line after you click Yes in your AlertDialog.
All you need to do is call notifyDataSetChanged() which will notify the RecyclerView to re-bin the views again, thereby deleting any item as necessary.
Just add a method in your adapter class,
mAdapter.notifyDataSetChanged();
If you know the position of the particular item which is getting deleted, then it is RECOMMENDED to use,
mAdapter.notifyItemChanged(position);
This will give you a nice animation effect while deleting the item.
This is my ExpandableRecyclerAdapter adapter
public class MyAdapter extends ExpandableRecyclerAdapter<MyAdapter.ProductParentViewHolder, MyAdapter.ProductChildViewHolder> {
private LayoutInflater mInflater;
private Context context;
private List<? extends ParentListItem> mParentItemList;
public MyAdapter(Context context, List<ParentListItem> itemList) {
super(itemList);
mInflater = LayoutInflater.from(context);
this.context = context;
this.mParentItemList = itemList;
}
#Override
public ProductParentViewHolder onCreateParentViewHolder(ViewGroup viewGroup) {
View view = mInflater.inflate(R.layout.list_item_crime_parent, viewGroup, false);
return new ProductParentViewHolder(view);
}
#Override
public ProductChildViewHolder onCreateChildViewHolder(ViewGroup viewGroup) {
View view = mInflater.inflate(R.layout.list_item_crime_child, viewGroup, false);
return new ProductChildViewHolder(view);
}
#Override
public void onBindParentViewHolder(ProductParentViewHolder crimeParentViewHolder, int i, ParentListItem parentListItem) {
Product product = (Product) parentListItem;
crimeParentViewHolder.productName.setText(product.getBrandName() + " " + product.getProductName());
Glide.with(context)
.load(product.getProductImagePath())
.placeholder(R.drawable.placeholder)
.error(R.drawable.placeholder)
.into(crimeParentViewHolder.thumbnail);
}
#Override
public void onBindChildViewHolder(ProductChildViewHolder productChildViewHolder, int i, Object childListItem) {
final ProductVariant productVariant = (ProductVariant) childListItem;
productChildViewHolder.mCrimeDateText.setText(productVariant.getVariantName());
productChildViewHolder.variantMrp.setText(context.getString(R.string.positive_amount, productVariant.getMRP()));
productChildViewHolder.variantMrp.setPaintFlags(productChildViewHolder.variantMrp.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
productChildViewHolder.variantSellPrice.setText(context.getString(R.string.positive_amount, productVariant.getSellPrice()));
//productChildViewHolder.variantMrp.setText(productVariant.getMRP().toString());
//productChildViewHolder.variantSellPrice.setText(productVariant.getSellPrice().toString());
if (productVariant.getInCart() == 0) {
productChildViewHolder.btnProductDetailAddToCart.setVisibility(View.VISIBLE);
productChildViewHolder.btnProductDetailMinus.setVisibility(View.GONE);
productChildViewHolder.btnProductDetailQty.setVisibility(View.GONE);
productChildViewHolder.btnProductDetailPlus.setVisibility(View.GONE);
} else {
productChildViewHolder.btnProductDetailAddToCart.setVisibility(View.GONE);
productChildViewHolder.btnProductDetailMinus.setVisibility(View.VISIBLE);
productChildViewHolder.btnProductDetailQty.setVisibility(View.VISIBLE);
productChildViewHolder.btnProductDetailPlus.setVisibility(View.VISIBLE);
}
int quantity = productVariant.getInCart();
productChildViewHolder.btnProductDetailQty.setText(Integer.toString(quantity));
productChildViewHolder.btnProductDetailAddToCart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
productVariant.setInCart(1);
//Utility.loadShoppingCartItems();
notifyDataSetChanged();
invalidateOptionsMenu();
//holder.db.addItem(new CartItem(1, productVariant.getProductID(), productVariant.getVariantID(), 1));
}
});
productChildViewHolder.btnProductDetailPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
productVariant.setInCart(1 + productVariant.getInCart());
notifyDataSetChanged();
invalidateOptionsMenu();
//if (productVariant.getInCart() > 0) {
//int count = holder.db.updateSingleRow(productVariant.getProductID(), productVariant.getVariantID(), productVariant.getInCart());
//}
}
});
productChildViewHolder.btnProductDetailMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
productVariant.setInCart(productVariant.getInCart() - 1);
notifyDataSetChanged();
invalidateOptionsMenu();
if (productVariant.getInCart() == 0) {
//int count = holder.db.deleteSingleRow(productVariant.getProductID(), productVariant.getVariantID());
} else if (productVariant.getInCart() > 0) {
//int count = holder.db.updateSingleRow(productVariant.getProductID(), productVariant.getVariantID(), productVariant.getInCart());
}
//Utility.displayToast(holder.db.getItemsCount() + "");
}
});
//crimeChildViewHolder.mCrimeSolvedCheckBox.setChecked(productVariant.isSolved());
}
public class ProductParentViewHolder extends ParentViewHolder {
private static final float INITIAL_POSITION = 0.0f;
private static final float ROTATED_POSITION = 180f;
private final boolean HONEYCOMB_AND_ABOVE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
public TextView productName;
public ImageView thumbnail;
public ImageButton mParentDropDownArrow;
public ProductParentViewHolder(View itemView) {
super(itemView);
productName = (TextView) itemView.findViewById(R.id.productName);
thumbnail = (ImageView) itemView.findViewById(R.id.thumbnail);
// mParentDropDownArrow = (ImageButton) itemView.findViewById(R.id.parent_list_item_expand_arrow);
}
#SuppressLint("NewApi")
#Override
public void setExpanded(boolean expanded) {
super.setExpanded(expanded);
if (!HONEYCOMB_AND_ABOVE) {
return;
}
if (expanded) {
// mParentDropDownArrow.setRotation(ROTATED_POSITION);
} else {
// mParentDropDownArrow.setRotation(INITIAL_POSITION);
}
}
}
public class ProductChildViewHolder extends ChildViewHolder {
public TextView mCrimeDateText;
public TextView variantMrp;
public TextView variantSellPrice;
public Button btnProductDetailAddToCart, btnProductDetailPlus, btnProductDetailMinus;
public TextView btnProductDetailQty;
public ProductChildViewHolder(View itemView) {
super(itemView);
mCrimeDateText = (TextView) itemView.findViewById(R.id.variantName);
variantMrp = (TextView) itemView.findViewById(R.id.productVariantMrp);
variantSellPrice = (TextView) itemView.findViewById(R.id.productVariantSellPrice);
btnProductDetailAddToCart = (Button) itemView.findViewById(R.id.btnProductDetailAddToCart);
btnProductDetailPlus = (Button) itemView.findViewById(R.id.btnProductDetailPlus);
btnProductDetailMinus = (Button) itemView.findViewById(R.id.btnProductDetailMinus);
btnProductDetailQty = (TextView) itemView.findViewById(R.id.btnProductDetailQty);
}
}
}
When i am bottom of the page and click on item it expands, but exapnded child item doesn't shows to user because it is bottom in the screen.
I want to move that item up in the screen and show expanded items to user.
How can i do that?
You can simply use the method setSelectedGroup()
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
expandableListView.setSelectedGroup(groupPosition);
return true;
}
});
This will move the selected group to the top
EDIT
Finally I came out with a solution for your ExpandableRecyclerAdapter also. Simply put this method inside your adapter implementation. Also you will require the reference of the recyclerView inside the adapter which you can pass to the adapter at the time of initialization.
int lastPos = -1;
#Override
public void onParentListItemExpanded(int position) {
List<? extends ParentListItem> parentItemList = this.getParentItemList();
collapseAllParents();
int finalPos = position;
if (lastPos != -1 && lastPos < position) {
finalPos = position - parentItemList.get(lastPos).getChildItemList().size();
}
expandParent(finalPos);
mRecyclerView.smoothScrollToPosition(finalPos);
lastPos = position;
}
I found this issue at https://github.com/bignerdranch/expandable-recycler-view/issues/156 . Although the solution given there didn't work. Slight tweaking to that make it work.
Use this following code in your expandable listview click listener. Do something liket his
yourExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public boolean onGroupClick(final ExpandableListView parent, View v, final int groupPosition, long id) {
....
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
parent.smoothScrollToPositionFromTop(groupPosition + 1, 0);
}
},100);
....
return true;
}
});
Use AnimatedExpandableListView
I have a very strange problem while using my ListView.
Only a part of my adapter items are renderd in the listview on screen but when I interact with the listview (ie tries to scroll it) all items are renderd properly.
This fenonemon only occurs if i have less items than the screen can show. Take a look at these screenshots below.
Before interaction:
After interaction:
Source code of activity where adding items:
String[] jRests = getResources().getStringArray(R.array.j_restaurants);
String[] lRests = getResources().getStringArray(R.array.l_restaurants);
items = new ArrayList<Object>();
items.add(getString(R.string.campus_j));
for(String item : jRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
items.add(getString(R.string.campus_l));
for(String item : lRests){
String[] val = item.split(",,,");
items.add(new FoodSectionListItem(new Restaurant(val[0], val[1], val[2], "")));
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new BaseSectionAdapter(this, R.layout.list_item_fragment_header);
if(!isTabletView()){
adapter.setSelectedItem(-1);
}
adapter.setItems(items);
Code of adapter:
public class BaseSectionAdapter extends AmazingAdapter {
private LayoutInflater inflater;
private int selectedItem = 0;
private List<Object> items;
private List<SectionItem> sections = new ArrayList<SectionItem>(10);
private List<Class> itemTypes = new ArrayList<Class>();
private List<Integer> sectionPositions = new ArrayList<Integer>();
private int listHeaderLayoutId;
private View headerView;
public static interface ISectionListItem {
public void setProps(View convertView, int position, int selectedItem);
public View getLayout(LayoutInflater inflater);
}
private class SectionItem implements Serializable {
private static final long serialVersionUID = -8930010937740160935L;
String text;
int position;
public SectionItem(String text, int position) {
this.text = text;
this.position = position;
}
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
}
public BaseSectionAdapter(Context context, int listHeaderLayoutId, List<Object> listItems) {
this.listHeaderLayoutId = listHeaderLayoutId;
init(context);
initListItems(listItems);
}
private void init(Context context) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setSelectedItem(int position) {
selectedItem = position;
}
// public List<ListItem> getItems() {
// return items;
// }
private void initListItems(List<Object> itemList) {
int curSection = -1;
//int curPosition = 0;
//curSection = 0;
this.items = itemList;
itemTypes.clear();
sections.clear();
sectionPositions.clear();
int listSize = itemList.size();
for(int i = 0; i < listSize; i++){
Object currentItem = items.get(i);
if(currentItem instanceof String){
sections.add(new SectionItem((String) currentItem,i));
curSection++;
}
if(!itemTypes.contains(currentItem.getClass())){
itemTypes.add(currentItem.getClass());
}
sectionPositions.add(curSection);
}
Log.d("test", "No of items = "+items.size());
Log.d("test", "No of itemtypes = "+itemTypes.size());
Log.d("test", "View type count = "+getViewTypeCount());
}
public void setItems(List<Object> itemList) {
initListItems(itemList);
}
public int getCount() {
return items==null?0:items.size();
}
#Override
public int getViewTypeCount(){
return (itemTypes.size() == 0)?1:itemTypes.size();
}
#Override
public int getItemViewType(int position){
return itemTypes.indexOf(items.get(position).getClass());
}
#Override
public boolean isEnabled(int position){
return !(items.get(position) instanceof String || items.get(position) instanceof EmptySectionListItem);
}
#Override
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
protected void onNextPageRequested(int page) {
// TODO Auto-generated method stub
}
#Override
protected void bindSectionHeader(View view, int position,
boolean displaySectionHeader) {
// TextView lSectionTitle = (TextView) view
// .findViewById(R.id.txt_list_header);
// if (displaySectionHeader) {
// lSectionTitle.setVisibility(View.VISIBLE);
// lSectionTitle
// .setText(getSections()[getSectionForPosition(position)]);
// } else {
// lSectionTitle.setVisibility(View.GONE);
// }
}
#Override
public View getAmazingView(int position, View convertView, ViewGroup parent) {
Object curItemObject = items.get(position);
boolean isHeader = (curItemObject instanceof String);
if(convertView == null){
if(isHeader && headerView != null){
convertView = headerView;
}else if(isHeader){
convertView = inflater.inflate(listHeaderLayoutId, null);
headerView = convertView;
}else{
convertView = ((ISectionListItem) curItemObject).getLayout(inflater);
}
}
if(isHeader){
TextView header = ((TextView)convertView.findViewById(R.id.txt_list_header));
header.setText((String)curItemObject);
}else{
((ISectionListItem)curItemObject).setProps(convertView, position, selectedItem);
}
return convertView;
}
#Override
public void configurePinnedHeader(View header, int position, int alpha) {
TextView textView = ((TextView)header.findViewById(R.id.txt_list_header));
textView.setText(getSections()[getSectionForPosition(position)]);
}
#Override
public int getPositionForSection(int section) {
if(section >= sections.size()){
return 0;
}
return sections.get(section).position;
}
#Override
public int getSectionForPosition(int position) {
return sectionPositions.get(position);
}
#Override
public String[] getSections() {
String[] res = new String[sections.size()];
for (int i = 0; i < res.length; i++) {
res[i] = sections.get(i).text;
}
return res;
}
}
Code of layout:
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
FrameLayout listLayout = new FrameLayout(this);
LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
listParams.weight = 1;
listLayout.setId(LIST_FRAGMENT_VIEW_ID);
FrameLayout detailLayout = new FrameLayout(this);
LinearLayout.LayoutParams detailParams = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT);
detailParams.weight = 2;
detailLayout.setId(DETAIL_FRAGMENT_VIEW_ID);
layout.addView(listLayout, listParams);
layout.addView(detailLayout, detailParams);
if(savedInstanceState == null){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(listLayout.getId(), (Fragment) listFragment, TWO_PANEL_LIST_FRAGMENT_TAG);
ft.add(detailLayout.getId(), detailFragment);
ft.commit();
}
setContentView(layout);
try calling notifyDataSetChanged() in runOnUIThread() method like I have shown below and it will work like a charm. :)
runOnUiThread(new Runnable() {
#Override
public void run() {
messageAdapter.notifyDataSetChanged();
}
});
i dont know what causes the problem, but if you don't find a logical solution to it you could try something like this:
trigger an onTouchEvent() programmatically whenever you launch the ListView.
scroll down and back up programmatically as soon as the ListView is launched.
etc..
Add ListView widget to layout.xml and add content of list to that. Do not use FrameLayout as it probably is the cause of the problem. It is updating content after touch so the Layout it is on is no implementing the correct onCreate() setup as the ListView widget has.
Are you calling the method notifyDataSetChanged() on your adapter after adding new items? This causes the listview to refresh its view when the underlying dataset is changed.
If it still doesn't work, try notifyDataSetInvalidated() that causes the listview to redraw completely.
Solved it!!!
Problem was with the adapter trying to reuse the same section item. Not good!!!
Changed it to inflate the section item each time we hit a section!