I have a filter panel and I get a data from it and from my Firebase Realtime Database using a callback. I have an if/else block. If answer.size() == 0 is true (answer is a list of filters' values), I fill my adapter with a list. If false, I want to clear an adapter and have an empty ListView.
Here is my code:
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
verifyStoragePermissions(getActivity());
ArrayList<PlayerRating> finalRatingList = new ArrayList<PlayerRating>();
View view = inflater.inflate(R.layout.rating_fragment, container, false);
button = view.findViewById(R.id.convertButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
alertSingleChoiceItems(); ;
}});
Database base = new Database();
base.readTournaments(new Database.TournamentsCallback() { //reading data from Firebase using callback
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onCallback(ArrayList<TournamentParameters> tournamentsList,
ArrayList<String> tournamentsNames, ArrayList<String> answer) {
ArrayList<PlayerRating>ratingList = new ArrayList<PlayerRating>();
ArrayList<TournamentParameters> editableTournamentsList = new ArrayList<TournamentParameters>(tournamentsList);
PlayerRatingAdapter adapter = new PlayerRatingAdapter(getActivity(), R.layout.rating_adapter_item,
new ArrayList<PlayerRating>());
ListView listview = (ListView) view.findViewById(R.id.ratingListView);
if (answer.size() == 0) { // answer.size() is a size of an ArrayList with filters' values
ratingList.clear();
finalRatingList.clear();
HashMap<String, Integer> rating = new HashMap<String, Integer>();
//tournamentsList filling
...
//ratingList filling
...
//ratingList sorting
...
adapter = new PlayerRatingAdapter(getActivity(), R.layout.rating_adapter_item, ratingList);
adapter.notifyDataSetChanged();
ViewGroup header = (ViewGroup) inflater.inflate(R.layout.rating_listview_header,
listview, false);
listview.addHeaderView(header);
listview.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
else {
ratingList.clear();
finalRatingList.clear();
adapter.clear();
adapter.notifyDataSetChanged();
Log.d("okey", "cleared!");
}
Button filtersTV = getActivity().findViewById(R.id.filtersTV);
filtersTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showFragment();
}
});
}
});
return view;
}
showFragment method:
private void showFragment() {
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
if (!fragment.isAdded()) {
transaction.add(R.id.frame, fragment, "filter");
}
transaction.addToBackStack(null);
transaction.commit();
}
Also when I set the filters method dismissFragment() works (it is responsible for going back from my filter panel fragment to my fragment with ListView):
public void dismissFragment() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (!fragment.isAdded()) {
transaction.add(R.id.frame, fragment, "filter");
}
transaction.replace(R.id.frame, new RatingFragment());
transaction.addToBackStack(null);
transaction.commit();
//FragmentManager fm = getSupportFragmentManager();
//fm.popBackStackImmediate();
}
The problem is the fact that my adapter is not cleared. When code goes to else block and
ratingList.clear();
finalRatingList.clear();
adapter.clear();
adapter.notifyDataSetChanged();
Log.d("okey", "cleared!");
works (I even have an expected message in my LogCat), nothing is changed - my ListView remains the same, nothing is cleared.
What should I change in the code?
You have two different instances of adapter in your code. One outside if/else and one in 'if block'.
That's why when you clear it in 'else block' it's not the same adapter. And nothing happens.
Instrad of initializing adapter again in 'if block' just update it and your cide will work.
Related
I am working on an android application where I have three fragments I want to show the back button on the toolbar of the fragments to go back to the previous fragments now how can I achieve that?? I am new to android please guide me.
public class SecondFragment extends Fragment {
Button button2;
private PageViewModel viewModel;
EditText editTextName, editTextEmail, editTextDesc;
public SecondFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_second, container, false);
button2 = view.findViewById(R.id.next2);
editTextName = view.findViewById(R.id.edittextName);
editTextEmail = view.findViewById(R.id.edditextEmail);
editTextDesc = view.findViewById(R.id.edittexDesc);
viewModel = new ViewModelProvider(requireActivity()).get(PageViewModel.class);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (editTextName.getText().toString().isEmpty() || editTextEmail.getText().toString().isEmpty() || editTextDesc.getText().toString().isEmpty())
{
editTextName.setError("Enter name");
editTextEmail.setError("Enter Email");
editTextDesc.setError("Enter Description");
}else {
// viewModel.setName(editTextName.getText().toString());
enterName(editTextName.getText().toString());
enterEmail(editTextEmail.getText().toString());
enterDesc(editTextDesc.getText().toString());
// viewModel.setEmail(editTextEmail.getText().toString());
// viewModel.setDescription(editTextDesc.getText().toString());
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
Fragment NAME = new LastFragment();
fragmentTransaction.replace(R.id.container, NAME);
fragmentTransaction.commit();
}
}
});
return view;
}
this is the code of my fragment borther i have three fragments like this i need to add the back button on the toolbar of there three fragemtns
You can add a toolbar to your activity, which is the container for these fragments.
Then in your fragments you can do something like this:
private void setupToolbar() {
YourActivity yourActivity = (YourActivity) getActivity()
if(yourActivity != null) {
yourActivity.toolbar.setSkipVisibility(View.GONE) // Or View.VISIBLE
yourActivity.toolbar.setText() // Set some text
yourActivity.toolbar.setOnBackButtonClickListener{ yourActivity.onBackPressed() }
}
}
Follow the steps down below.
fragmentTransaction.replace(R.id.container, NAME);
fragmentTransaction.addToBackStack(null); //Add this line
fragmentTransaction.commit();
This will solve your issue. Thank you.
I have an array list which is responsible for storing a collection of exercises names as 'Workouts'. The array list, situated in Fragment A, gets its data from an argument sent through a Bundle in Fragment B.
When a user wants to pick an exercise they press an option of 2 buttons on Fragment A which populates different exercises names on Fragment B. When an exercise is picked in Fragment B then the exercise name is sent back to Fragment A.
The argument taken from Fragment B is meant to be appended to the array list in Fragment A, however every time the Fragment A is reloaded the array list is refreshed therefore removing the previous exercise that was saved. I know this is because new ArrayList<String>() is defined in the onCreateView of Fragment A but is there a way that it can only be created once? (on Fragment A's initial creation rather than every transition between Fragment B & A).
OnCreateView of Fragment A:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view =inflater.inflate(R.layout.fragment_editor, container, false);
//BUTTON SETUP
final Button addUpButton = (Button) view.findViewById(R.id.btnAddUpper);
addUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
newExe(addUpButton);
}
});
final Button addLowButton = (Button) view.findViewById(R.id.btnAddLower);
addLowButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
newExe(addLowButton);
}
});
ListView listView = (ListView) view.findViewById(R.id.lstWorkout);
//CREATE AN ARRAY LIST TO AMMEND WITH EXERCISES
workoutSave = new ArrayList<String>();
if (getArguments() == null) {
return view;
}
else{
getValue= getArguments().getString("Movement");
workoutSave.add(getValue);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), R.layout.item_list, R.id.txtWorkout, workoutSave);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
}
return view;
}
How Fragment A is reloaded from Fragment B when list item is pressed:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String exercise = lstExe.get(position);
Fragment myFragment = new EditorFragment();
Bundle args = new Bundle();
args.putString("Movement", exercise);
myFragment.setArguments(args);
getFragmentManager().beginTransaction().add(R.id.frame_layout,myFragment).commit();
}
});
public class AlarmsFragment extends Fragment {
FloatingActionButton floatingActionButton;
RecyclerView recyclerView;
TextView checkText;
ArrayList<AlarmObjects> alarmObjects;
public AlarmsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_alarms, container, false);
floatingActionButton = v.findViewById(R.id.fab_button);
recyclerView = v.findViewById(R.id.rv_alarms);
alarmObjects = new ArrayList<>();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RecyclerView.LayoutManager rvLayoutManager = linearLayoutManager;
recyclerView.setLayoutManager(rvLayoutManager);
AlarmAdapter alarmAdapter = new AlarmAdapter(getContext(),alarmObjects);
recyclerView.setAdapter(alarmAdapter);
Bundle arguments = getArguments();
if (arguments != null){
String newTime = getArguments().getString("newTimm");
String newNotes = getArguments().getString("newNott");
checkText.setText(newTime + newNotes);
alarmObjects.add(new AlarmObjects(newNotes,newTime));
}
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)getActivity()).showPopupmeth();
}
});
return v;
}
}
it keeps updating same object it created but doesnt create new one can you help i am new to this.
public void setFragment(Fragment fragment, int id) {
changeTitle(id);
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_frame, fragment);
fragmentTransaction.commit();
}
using this method i come back to my alarmsFragment. When i come back to it from dialog fragment it creates new ArrayList every time as i understood. How can i make it show existing objects and add new ones using getArguments
Your is only part in and not clear enough, So I am assuming that you want create Immutable ArrayList,You can implement it as follows by using unmodifiableList method of Collections framework Java 8
i.e Collections unmodifiableList(list);
Example :
List<String> list = new ArrayList<String>(Arrays.asList("one", "two", "three"));
List<String> unmodifiableList = Collections.unmodifiableList(list);
unmodifiableList.add("four");
This is only a part of the code. I assume the code above is being called for every new arguments. If so, then the following is what is happening:
On the first line you are doing new ArrayList() which always creates a new (and empty) array list.
On the last line you are adding a new AlarmObjects to the list.
So, when you try to retrieve the element from the list you get the most recently added element. This is why you are thinking it is modifying the existing element.
In reality, you are adding a new element. But you are also recreating the list every time. So you are not seeing the previous element
Instead of creating a new arraylist every time, create one in the parent method and pass the reference to this method.
public void parentMethod(){
List<AlarmObjects> alarmObjects = new ArrayList<>();
childMethod(alarmObjects);
}
public void childMethod(List<AlarmObjects> alarmObjects){
//all of your code except the new ArrayList<>() goes here
}
Sorry but I cannot get what you want to do.
You initialize an ArrayList here:
alarmObjects = new ArrayList<>();
And put the first object into the array here:
alarmObjects.add(new AlarmObjects(newNotes,newTime)); }
What behaviour do you expect?
EDIT:
try this:
FloatingActionButton floatingActionButton;
RecyclerView recyclerView;
TextView checkText;
ArrayList<AlarmObjects> alarmObjects = new ArrayList<>();
public AlarmsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_alarms, container, false);
floatingActionButton = v.findViewById(R.id.fab_button);
recyclerView = v.findViewById(R.id.rv_alarms);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
RecyclerView.LayoutManager rvLayoutManager = linearLayoutManager;
recyclerView.setLayoutManager(rvLayoutManager);
AlarmAdapter alarmAdapter = new AlarmAdapter(getContext(),alarmObjects);
recyclerView.setAdapter(alarmAdapter);
Bundle arguments = getArguments();
if (arguments != null){
String newTime = getArguments().getString("newTimm");
String newNotes = getArguments().getString("newNott");
checkText.setText(newTime + newNotes);
alarmObjects.add(new AlarmObjects(newNotes,newTime));
}
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)getActivity()).showPopupmeth();
}
});
return v;
enter code here
}
}
I have a listview that shows up when a fragment is opened being updated by a saved list. Initially that list is empty so it spits out an error java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0. So i want to show show something like a text saying something like empty so that when there is something in the list it will display. I have tried using the getEmptyView but to no avail. Can i please get some help on how to accomplish this thank you.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View customView = inflater.inflate(R.layout.fragment_reading_monday, container, false);
addNewButton = (Button) customView.findViewById(R.id.btnAddNewReadingMonday);
relativeLayoutMonday = (RelativeLayout) customView.findViewById(R.id.frameLayoutMonday);
listViewMonday = (ListView)customView.findViewById(R.id.listViewMonday);
listContainerMonday = (RelativeLayout)customView.findViewById(R.id.listContainerMonday);
tinyDB = new TinyDB(getContext());
addNewSubject = (Button)customView.findViewById(R.id.btnAddNewSubjectMonday);
dataModels = new ArrayList<>();
arrayListSubjectsRead = new ArrayList<>();
timeOne = new ArrayList<>();
timeTwo = new ArrayList<>();
adapter = new CustomListAdapterReading(getContext(), dataModels);
TextView empty = (TextView) customView.findViewById(R.id.emptyTextView);
listViewMonday.setEmptyView(empty);
arrayListSubjectsRead = tinyDB.getListString("ArrayForSubjects");
timeOne = tinyDB.getListString("ArrayForTimeOne");
timeTwo = tinyDB.getListString("ArrayForTimeTwo");
dataModels.add(new DataModelReading(arrayListSubjectsRead, timeOne, timeTwo));
adapter = new CustomListAdapterReading(getContext(), dataModels);
listViewMonday.setAdapter(adapter);
adapter.notifyDataSetChanged();
System.out.println(" subjects: "+arrayListSubjectsRead);
System.out.println("timeone: "+ timeOne);
System.out.println("timetwo: "+timeTwo);
addNewButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
relativeLayoutMonday.removeView(noEventTextView);
Intent intent = new Intent(getActivity(),ReadMain.class);
startActivity(intent);
}
});
addNewSubject.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
return customView;
}
I want you to check this post setEmptyView on ListView not showing its view in a android app, it should solve your empty view issue.
And if you want to prevent the app from throwing an IndexOutOfBoundsException, you can simply check the size of your dataModels array before setting up your adapter.
if (dataModels.size() > 0)
{
//Setup our adapter here
}
Hope this helps :)
Something like this ?
ImageListAdapter imageListAdapter= new ImageListAdapter();
listviewObject.setAdapter(imageListAdapter);
if (imageListAdapter!= null)
if (imageListAdapter.getCount() > 0){
// implement your work
}else {
// do whatever you want on empty list adapter
}
I am using this way in my application
ListView listView = (ListView)findViewById(android.R.id.listView);
TextView noData = (TextView)findViewById(android.R.id.noData);
listView.setEmptyView(noData);
Listview will automatically set no data text when adapter is empty.
So I'm trying to load different contents in a ListView when I press on specific buttons but it only loads the first that I tried to load (and only after I have pressed it twice). I can't find what I've done wrong.
Here's the code that creates the view in witch I show the content:
public class ContentQuery extends Fragment {
private List<String> contents_list = new ArrayList<String>();
public static final String TAG = contentQuery.class.getSimpleName();
private String uri = "";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View lv = inflater.inflate(R.layout.contents_list, container, false);
super.onActivityCreated(savedInstanceState);
getContent(); // Sets contents_list
((ListView) lv).setAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, contents_list));
return lv;
}
}
I think it might be because I should in some way destroy it but I'm pretty new to android dev.
tag = ContentQuery.TAG;
ContentQuery contentqueryfragment = null;
final Fragment foundFragment = fm.findFragmentByTag(tag);
if (foundFragment != null && uri != old_uri) {
fragment = foundFragment;
contentqueryfragment = (ContentQuery) fragment;
old_uri = uri;
} else {
contentqueryfragment = new ContentQuery();
contentqueryfragment.setUri(uri.toString());
fragment = contentqueryfragment;
}
And after:
if (fragment.isAdded())
{
tr.show(fragment);
} else
{
tr.remove(fragment);
tr.add(R.id.content, fragment, tag);
tr.show(fragment);
}
tr.commit();
currentUri = uri;
currentContentFragmentTag = tag;
If you need to update the content within the List a good approach would be to separate the List, ListAdapter and ListView. When data needs to be updated, update the contents of the list and notify the Adapter that the list contents changed.
eg.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, contents_list);
((ListView) lv).setAdapter(adapter);
...
button.onClickListener(...) {
contents_list.clear();
... populate list with new data ...
adapter.notifyDataSetChanged();
}