I have Quote List class QuoteListFragment. where I am loading data in adapter from server like this
private ArrayList<Quote> quotes;
quotes = response.body();
NewQuoteAdapter adapter = new NewQuoteAdapter(getContext(), response.body());
mQuoteList.setAdapter(adapter);
and RecyclerView Adapter called NewQuoteAdapter
I am displaying Item in details with QuoteViewFragment. I have implemented a button called "delete" in this fragment and I want to give the user a chance to delete that quote from fragment so When the user goes back to the list, it disappears from the list.
I have no idea how to achieve this. Let me know if someone can give me a solution for this. Thanks
well you have a list, and adapter, and a recyclerview
ArrayList<String> myQuoteList = new ArrayList<String>();
MyCustomAdapter adapter = new MyCustomAdapter(myQuoteList);
rcvQuotes.setAdapter(adapter);
Then in your delete you can just do
private void deleteAtIndex(int index){
myQuoteList.remove(index);
adapter.notifyDataSetChanged();
}
//make a interface.
public interface fragmentCallback{
boolean onQuoteDeleted(Quote deleteQuote);
}
have your activity implement the interface:
myActivity implements fragmentCallback{
public boolean onQuoteDeleted(Quote deletedQuote){
if(myQuotelist.contains(deleteQuote){
myQuoteList.remove(deleteQuote);
adapter.notifyDataSetChanged();
}
}
}
then in fragment simpley
myFragment.setQuote(selectedQuote);
inside of fragment just do:
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
mFragmentCallback = (IFragmentCallback) context;
}catch (Exception ex){
A35Log.e(TAG, "Parent Context does not implement fragmentCallback");
}
}
public void setQuote(Quote showQuote){
mSelectedQuote = showQuote;
}
btnDelete_onClick(){
if(mFragmentCallback != null){
mFragmentCallback.onDeleteQuote(mSelectedQuote);
}
}
you can handle it by selected index of the row, or by last index, or first index, or you can add a long touch listener or trash can to the row item. how you get the index is up to you.
That's it, that is all there is to it.
Arraylist.remove(index)
recycleradapter.notifydatasetchanged()
Get the index of clicked item
e.g index = 4
list of quote e.g quotesList.
quotesList.remove(index);
adapter.notifyDataSetChanged();
Related
I am calling the filter data function from the fragment search view , it is working fine and the data are getting filtered but the images are getting reloaded.How can this be prevented
public menuadapter(ArrayList<GridItem> mGridDat, Context context, OnItemClickListener listener) {
this.mGridData=new ArrayList<GridItem>();
this.orignallist=new ArrayList<GridItem>();
mGridData.addAll(mGridDat);
orignallist.addAll(mGridDat);
this.context = context;
this.listener = listener;
this.Session=new session(context);
}
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final Activity activity = (Activity)context;
String capital=mGridData.get(position).getTitle().substring(0,1).toUpperCase()+mGridData.get(position).getTitle().substring(1).toLowerCase();
holder.txtview.setText(capital);
Picasso.with(context).load(mGridData.get(position).getImage()).fit().centerCrop().skipMemoryCache().into(holder.imageView);
}
Filter Data function
public void filterData(String query){
query=query.toLowerCase();
//Log.v("check1",String.valueOf(orignallist.size()));
mGridData.clear();
if(query.isEmpty()){
mGridData.addAll(orignallist);
// Log.v("check2",String.valueOf(orignallist.size()));
}
else {
//Log.v("check0",String.valueOf(orignallist.size()));
ArrayList<GridItem> newlist = new ArrayList<>();
for(GridItem gd: orignallist) {
if ((gd.getTitle().toLowerCase().contains(query)) ) {
newlist.add(gd);
}
}
if(newlist.size()> 0){
mGridData.addAll(newlist);
}
}
notifyDataSetChanged();
}
Try this
Picasso.with(context).load(mGridData.get(position).getImage()).fit().centerCrop().networkPolicy(NetworkPolicy.OFFLINE).into(holder.imageView);
You need to use below property and not skipMemoryCache()
OFFLINE
public static final NetworkPolicy OFFLINE
Forces the request through the disk cache only, skipping network.
https://square.github.io/picasso/2.x/picasso/com/squareup/picasso/NetworkPolicy.html
To avoid reloding of images, solutions I think of are
one is to remove the images which are not matching the query and keeping others. Something like -
if(!(gd.getTitle().toLowerCase().contains(query)))
{
// get it from holder.getAdapterPosition();
contentsArrayList.remove(position);
notifyItemRemoved(position);
}
// out of for loop
notifyItemRangeChanged(firstRemovedPostion,contentsArrayList.size());
You can hide the element which is not matching the query and then show if it's matching another
itemView.setVisibility(View.GONE);
I'm trying to perform a search on my recycler adapter when onQueryTextChange
as shown below.
newText = newText.toLowerCase();
List<HymnDataModel> search_list = new ArrayList<>();
for(HymnDataModel hymnDataModel : hymnDataList){
String hymn_title = hymnDataModel.getHymnTitle().toLowerCase();
String hymn_subTitle = hymnDataModel.getHymnSubTitle().toLowerCase();
if (hymn_title.contains(newText) || hymn_subTitle.contains(newText)){
search_list.add(hymnDataModel);
}
}
And i filter the Adapter using the setFilter.
adapterRV.setFilter(search_list);
This is the setFilter function in my Adapter
public void setFilter(List<HymnDataModel> search_list) {
mHymnsList = new ArrayList<>();
mHymnsList.addAll(search_list);
//notify to reload
notifyDataSetChanged();
}
The search works just fine, onQueryTextChange
, but after filtering the Adapter and displaying on the RecyclerView, when i click on the filtered/searched item on my recyclerview, it doesn't open that particular item, instead, it opens another item that's not on the filtered list.
Try this instead.Assign search_list to the existing array List.
public void setFilter(List<HymnDataModel> search_list) {
mHymnsList = search_list;
//notify to reload
notifyDataSetChanged();
}
You are appending Filtered data item's in your Arraylist that's why your adapter display item that's not on the filtered list. try this clear your Arraylist before adding Filtered item in your Arraylist
Try this
public void setFilter(List<HymnDataModel> search_list) {
mHymnsList.clear();
mHymnsList.addAll(search_list);
or
mHymnsList = search_list;
//notify to reload
notifyDataSetChanged();
}
I'm using ParseQueryAdapter to display a ListView including the set of elements given by the Parse query:
ParseQueryAdapter.QueryFactory<AlertObject> factory =
new ParseQueryAdapter.QueryFactory<AlertObject>() {
public ParseQuery<AlertObject> create() {
ParseQuery<AlertObject> query = AlertObject.getQuery();
query.orderByDescending(AlertObject.TIMESTAMP_KEY);
query.fromLocalDatastore();
return query;
}
};
alertsListAdapter = new AlertListItemAdapter(activity, factory, thisFragment);
ListView alertsListView = (ListView) rootView.findViewById(R.id.alerts_list_view);
alertsListView.setAdapter(alertsListAdapter);
Now, I'd like to know the number of items in the ListView, but if I call alertsListView.getCount(), it returns 0. What am I doing wrong?
EDIT: someone gave this post a negative vote, but without leaving a comment or a request for clarification. So, I ask for some explanation about the reason of that in order to improve the readability of my question.
UPDATE: below my adapter
public class AlertListItemAdapter extends ParseQueryAdapter<AlertObject> {
private Context context;
private Fragment listAlertsFragment;
public AlertListItemAdapter(Context context,
ParseQueryAdapter.QueryFactory<AlertObject> queryFactory,
Fragment fragment) {
super(context, queryFactory);
this.context = context;
this.listAlertsFragment = fragment;
}
#Override
public View getItemView(final AlertObject alertObject, View view, final ViewGroup parent) {
[...]
}
#Override
public int getCount() {
return super.getCount();
}
}
I suspect (cannot be sure without seeing the Parse code/docs) that the adapter is not immediately populated with items, and when the query is executed, it'll call notifyDataSetChanged() on itself so that the ListView requeries it for item Views.
This would explain why your getCount() returns 0 immediately after setAdapter(ListAdapter) but why you can also see 33 items.
You can verify this logging adapter.getCount() as you do, and in addition, overriding notifyDataSetChanged to then observe the order of statements:
public class AlertListItemAdapter extends ParseQueryAdapter<AlertObject> {
public AlertListItemAdapter(
Context context,
ParseQueryAdapter.QueryFactory<AlertObject> queryFactory,
Fragment fragment) {
super(context, queryFactory);
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
Log.d("FOO", "item count: " + getCount());
}
#Override
public View getItemView(AlertObject alertObject, View view, ViewGroup parent) {
Log.d("FOO", "getItemView()");
...
}
...
}
If you need to know when the data changes, you can register a dataset changed listener on the adapter:
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
Log.d("Foo", adapter.getCount());
}
});
Are you sure you populated your ListView with parse AlertObjects?
I think you should add something like this to your query:
query.findInBackground(new FindCallback<AlertObject>() {
#Override
public void done(List<AlertObject> alerts, ParseException e) {
if (e == null) {
// Success
mAlerts = alerts;
String[] alertObjects = new String[mAlerts.size()];
Log.v(TAG, "There are " + mAlerts.size() + “ on the parse");
}
} else {
Log.e(TAG, e.getMessage());
}
}
});
Log can tell you how many objects you have on Parse.
In this Callback you can populate your ListView and then use
.getCount();
on your alertListAdapter.
Make sure you pass, store, and override the getCount() method correctly.
Please provide the code of adapter class if possible
Simply write following line to get number of items in the list view:
int count = alertsListView.alertsListAdapter().getCount();
After:
alertsListView.setAdapter(alertsListAdapter);
So your code will look like:
alertsListAdapter = new AlertListItemAdapter(activity, factory, thisFragment);
ListView alertsListView = (ListView) rootView.findViewById(R.id.alerts_list_view);
alertsListView.setAdapter(alertsListAdapter);
int count = alertsListView.alertsListAdapter().getCount();
I have an android activity with 4 fragments.
In Each fragment, there exists a text box, On the 4th fragment, a button exists.
on clicking the button, all the values(numbers) present in the text-boxes in the different fragment is added together and displayed as a Toast.
Note: Fragments must not communicate with each other.(without use of static variables or public in fragments and access it in the 4th fragment.)
Now, I have fragments but i need to know What communication technique should i have to use in this case?
You could store the Data in the MainActivity and read it from any Fragment like:
//MainActivity
private String mItem = "";
public void getItem(){
return this.mItem;
}
public void addItem(String searchItem){
this.mItem += searchItem;
}
//FRAGMENT 1
public void onButtonClick(){
//adding a string to your item in the MainActivity
((MainActivity)getActivity()).addItem("String from Frag1");
}
//FRAGMENT 4
private void onButtonClick{
//reading the string
String toastMessage = ((MainActivity)getActivity()).getItem();
}
One way i think you could do this is by communicating through the activity by using getActivity() from each fragment since they all share the same activity
public interface IAddItem{ public void addItem(int fragID, String value) };
Create this interface and implement it to your MainActivity:
Public class MainActivity extends Activity implements IAddItem{
private String mValue;
public void addItem(int fragID, String value){
switch(fragID){
case R.id.frag_1:
mValue = value;
break;
case //Do your other code here
}
}
}
In using it in other fragments using this: private IAddItem mCallback;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (IAddItem) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement IAddItem");
}
}
And call it like this: mCallback.addItem(R.id.frag_1, text.getText().toString());
Before calling another fragment just put code below:
Bundle bundle=new Bundle();
bundle.putString("MY_DATA", mStringData);
mFragment.setArguments(bundle);
After commit() mFragment. In second fragment where you want to get this data use:
String data = getArguments().getStringExtra("MY_DATA");
Another way for this in your case, you can use SharedPreference
Save data in preference like:
SharedPreference mPreference=PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
mPreferences.edit().putString("MY_DATA", mStringData).commit();
to get this data in another fragment use:
String data = mPrefrences().getStringExtra("MY_DATA");
I am trying to update my Activity's ListView from within the onLocationChanged function of a Location Listener using notifyDatasetChanged() but it doesnt work. I can however use setListAdapter from the same point in my code and this will work.
Here is my code:
public class TestListeners extends ListActivity {
ArrayAdapter adapter;
private final LocationListener networkLocationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.AVAILABLE:
break;
case LocationProvider.OUT_OF_SERVICE:
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
break;
}
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onLocationChanged(Location location) {
checkProximity(location.getLatitude(), location.getLongitude(), cx);
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//get a list here venueNamesArray
//etc
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1,
venueNamesArray);
setListAdapter(adapter);
}
private void checkProximity(double curLat, double curLon, Context cx) {
//get a different list here venueNamesArray
//etc
adapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1, android.R.id.text1,
venueNamesArray);
adapter.notifyDataSetChanged();//this doesnt work and no error is thrown
setListAdapter(adapter);//this works
}
}
The reason I want to use notifyDatasetChanged() instead of setListAdapter is because the listview scrolls back to the top upon setting it. No error is throw when I use notifyDatasetChanged() so it is hard for me to see why this isnt working.
I have tried using a normal ListView for this instead of extending ListActivity and ran into the same problem.
because you are creating a new adapter every time. you are not only changing the data in same adapter that is currently linked to list ........
As you are creating the new adapter and new adter will not linked with list untill you call setAdpter So it is not worth to call adapter.notifyDataSetChanged(); for adtper that is not linked with the list...
Solution
There is no need to create the adapter each time . jsut create and set in once in On-create and only change the ArrayList (add/remove not create new) and call adapter.notifyDataSetChanged();
When you create a new object of the Adapter in the call back, the one set as list adapter does not get affected. So notifyDataSetChanged is invoked on the new instance, and the one associated with the List is unaware of the method call.
Change the code to following:
private void checkProximity(double curLat, double curLon, Context cx) {
//update the original venueNamesArray, don't create a new instance
adapter.notifyDataSetChanged();
}
You are recreating adapter in checkProximity thats why notifyDataSetChanged is not working.
Change your code to following.
private void checkProximity(double curLat, double curLon, Context cx) {
//get values that are to be added into venueNamesArray.
venueNamesArray.add(value1); //This is just sample you will put your values
venueNamesArray.add(value2);
adapter.notifyDataSetChanged();
}