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.
Related
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.
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 can't figure out what is wrong with this code. I had been using if fine for days and haven't changed it, i even copied and pasted code from github when it was definitely working. I have now stripped back all my code and just made a simply click on the list view. first I was only getting it to respond to with a position of 0 in the list view now i am getting no response
Please tell me its something stupid that I a missing
Here is the relevant code
public class AdminActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
ArrayList<String> optionList = new ArrayList<String>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin);
//set the context sp we can use firebase
// Firebase.setAndroidContext(this);
optionList.add("VIEW DRIVERS");
optionList.add("DESIGNATE A DRIVER");
optionList.add("LOG OUT");
listView1 = (ListView) findViewById(R.id.lv);
ArrayAdapter adapter = new ArrayAdapter(AdminActivity.this, android.R.layout.simple_list_item_1, optionList);
listView1.setAdapter(adapter);
listView1.setOnItemClickListener(this);
}
and the onclick
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Driver d = driverList.get(position);
Toast.makeText(this,"Getting in here",Toast.LENGTH_SHORT).show();
System.out.println("Getting in here");
if(position == 0) {
Toast.makeText(this,"0",Toast.LENGTH_SHORT).show();
}
else if(position == 1) {
Toast.makeText(this,"DESIGNATE A DRIVER ACTIVITY 1",Toast.LENGTH_SHORT).show();
}
else if(position == 2) {
Toast.makeText(this,"GOODBYE 2",Toast.LENGTH_SHORT).show();
System.exit(0);
}
}
The Driver object created in the ListView was trying to retrieve from a list that previously had multiple objects in it. Because this list was coming from firebase it had not been throwing up an obvious error. That is why the same code was working previously.
I try to fill a listView with the following code:
private void getPhoneComments(View rootView) {
String phoneNumber = ((EditText) rootView.findViewById(R.id.phone_editText)).getText().toString();
Phone phone = phoneDal.getItem(phoneNumber);
if (phone != null) {
List<String> comments = commentDal.getAllItems(phone.id);
ListView lv = ((ListView) rootView.findViewById(R.id.comments_list));
// This is the array adapter, it takes the context of the activity as a
// first parameter, the type of list view as a second parameter and your
// array as a third parameter.
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
getActivity(),
android.R.layout.simple_list_item_1,
comments);
lv.setAdapter(arrayAdapter);
}
}
but the list still isn't displayed to the screen.
1) When do I need to add invalidate data
or what else I need to change in order to code to work?
2) how can i disply an option popup when there was a long push on each list item?
Edit:
phone != null
comments != empty
lv is set OK:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);
setCommentsVisibility(rootView, false);
lv = ((ListView) rootView.findViewById(R.id.comments_list));
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();
}