why setVisibility in fragment doesn't work? - java

the ProgressBar doesn't disappear in the fragment also items aren't loaded in the RecyclerView, When the code was in the body of onCreate of the main activity ,it was working
I am making fragment that contains ProgressBar and RecyclerView with retrieving data from firebase database , I added setVisibility at the end of onDataChange method so that after getting all the data and store it in the array list , the ProgressBar disappear
RecyclerView offersRecycler;
ArrayList<offer> offers;
OffersAdapter offersAdapter;
View fragment_layout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fragment_layout = inflater.inflate(R.layout.fragment_offers, container, false);
// Offers RecyclerView
offersRecycler = fragment_layout.findViewById(R.id.offersRecycler);
offers = new ArrayList();
offers_init();
offersAdapter = new OffersAdapter(offers,getContext());
offersRecycler.setAdapter(offersAdapter);
offersRecycler.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_offers, container, false);
}
private void offers_init() {
DatabaseReference db_offers = db_ref().child("offers");
db_offers.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
ProgressBar loadingOffers = fragment_layout.findViewById(R.id.loadingOffers);
loadingOffers.setProgress(10);
for (DataSnapshot offer_item : dataSnapshot.getChildren()) {
String id = offer_item.getKey();
String title = offer_item.child("title").getValue().toString();
String rating = offer_item.child("rating").getValue().toString();
String orders_number = offer_item.child("orders_number").getValue().toString();
offer offer_object = new offer(id,title, rating, orders_number);
offers.add(offer_object);
offersAdapter.notifyDataSetChanged();
}
Toast.makeText(getContext(),"title",Toast.LENGTH_LONG).show();
loadingOffers.setVisibility(View.GONE);
}catch (Exception ex){
Toast.makeText(getContext(),ex.getMessage(),Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
I expect the ProgressBar to hide and the array loaded into the RecyclerView

#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fragment_layout = inflater.inflate(R.layout.fragment_offers, container, false);
// Offers RecyclerView
offersRecycler = fragment_layout.findViewById(R.id.offersRecycler);
offers = new ArrayList();
offers_init();
offersAdapter = new OffersAdapter(offers,getContext());
offersRecycler.setAdapter(offersAdapter);
offersRecycler.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_offers, container, false);
}
^ This is your code snippet. What you are doing is - inflating a layout fragment_layout = inflater.inflate(R.layout.fragment_offers, container, false) and using fragment_layout to get the instance of RecyclerView. This is fine.
But at the end of the method, you are inflating a new layout and returning that. So the Android framework uses that View instead of fragment_layout to set the Fragment view. All the views in fragment_layout won't be shown since it's never added to the fragment and hence you don't see any changes in the RecyclerView.
At the end of the onCreateView method, you should just return fragment_layout.

in your CreateView, change
return inflater.inflate(R.layout.fragment_offers, container, false);
by
return fragment_layout;
You call the layout, init recyclerview, but recall the "blank" layout
Also, avoid underscore for method or variable name, it's not the java convention

Related

How to show my spinner within one fragment

I am on creating an application and at the moment, I have created two fragments which is going to be a "navigation" sort of thing. On the second of the two fragments, I have put a spinner on which is where the user would be able to select a particular option. All of the spinners have unique ID's but the findViewById method cannot be resolved
All of the strings are in the strings xml file and when I tried this spinner in my testing app, it worked
public class Frag2 extends Fragment implements AdapterView.OnItemSelectedListener{
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.frag2_layout, container, false);
Spinner spinner = findViewById (R.id.spinner1);
ArrayAdapter.createFromResource(getActivity(), R.array.insulin, android.R.layout.simple_spinner_item);
ArrayAdapter<CharSequence> adapter;
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String text = parent.getItemAtPosition(position).toString();
Toast.makeText(parent.getContext(), text, Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
The spinner should work within the one fragment and then I would like to have it another few times
This is fragment you're dealing with, not an activity. Fragment doesn't extend Context or View classes and does not have this findViewById method.
What you should do is to move your code from onCreateView to onViewCreated which gets a reference to the root view as a parameter. Then use the same method but with that view, as below:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
Spinner spinner = view.findViewById(R.id.spinner1);
...
}
Another thing you may do is replacing:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.frag2_layout, container, false);
Spinner spinner = findViewById (R.id.spinner1);
// I'm not sure how you didn't see all errors when writing code after a return statement.
...
}
With:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag2_layout, container, false);
Spinner spinner = view.findViewById(R.id.spinner1);
...
return view; // after finishing all logic.
}
UPDATE:
Didn't see that there is also a problem with the ArrayAdapter.
As mentioned in Csongi77 answer, you need to to instantiate the adapter properly. Again, the fragment cannot use as context, you must use the containing activity for that:
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.insulin, android.R.layout.simple_spinner_item);
ArrayAdapter.createFromResource creates and returns a new adapter and currently you just disposing it immediately by not saving its reference.
I think first you should instantiate adapter like this: ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.insulin, android.R.layout.simple_spinner_item); please let me know if it works. Regards, Csongi

Refreshing fragment in Android

I have a fragment which doesn't contain anything at the application start, but after the data is loaded it should show the loaded data. I do all my data loading in MainActivity in function onDataLoaded which implements DataLoadedListener. After the data is loaded the function sends the data (ArrayList) as a parameter through the function call (initializeAdapter()). Then, the function initializeAdapter() gets it and initialize custom made adapter (adapter is a global object, initialized in initializeAdapter() and used in onCreateView()).
I guess that I should refresh fragment view after the data is loaded and the adapter is initialized, but I don't know how to do it. I tried in a lot of ways but didn't make it.
onDataLoaded function in MainActivity which calls initializeAdapter()
#Override
public void onDataLoaded(List<Grad> gradovi, List<Ponuda> ponude) {
Spinner spinnerGradovi = (Spinner) findViewById(R.id.gradovi_spinner);
ArrayAdapter<String> adapterGradovi;
List<String> listaGradova = new ArrayList<>();
ArrayList<Ponuda> ponudaArrayList = new ArrayList<Ponuda>();
ponudaLista = ponude;
gradLista = gradovi;
for(Grad grad : gradovi ){
listaGradova.add(grad.getNaziv());
}
for(Ponuda ponuda : ponude){
ponudaArrayList.add(ponuda);
}
adapterGradovi = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, listaGradova);
spinnerGradovi.setAdapter(adapterGradovi);
Fragment fragmentGet = svePonudeFragment;
((SvePonudeFragment)fragmentGet).initializeAdapter(ponudaArrayList);
}
and this is a Fragment
public class SvePonudeFragment extends Fragment {
private RecyclerView rv;
RVAdapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.sve_ponude_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
rv.setAdapter(adapter);
return rootView;
}
public void initializeAdapter(List<Ponuda> preuzetePonude){
adapter = new RVAdapter(preuzetePonude);
//this isn't working
/*FragmentManager manager = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = manager.beginTransaction();
ft.detach(this).attach(this).commit();*/
//this is not working, neither
Fragment frg = getFragmentManager().findFragmentByTag("sve_ponude_fragment_tag");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
}
}
I am also interested in how to make an empty adapter which loads if data is not loaded yet? And when the data is loaded to fill out another adapter and use it.
Initialize adapter before you set. If you interested to change you approach I can give suggestions: Create a constructor for you fragment which you can pass the ArrayList. OnCreate or OnCreateView you can initialize the adapter and pass the list into. After setting adapter notifyDataChanges and to check if there is data please use some Logs when you pass the data and before you pass the data. Do not directly blame the adapter or fragment control your data. Besides I suggest you to study more using fragments + RecyclerView. I am posting one example that you can look at but the data load in the fragment.
public class CategoryFragment extends Fragment {
//Class Tag
private static final String TAG = CategoryFragment.class.getSimpleName();
//Fragments base context
private Context mContext;
//RecyclerView widget
private RecyclerView mRecyclerView;
//RecyclerView's Layout Manager
private RecyclerView.LayoutManager mLayourManager;
//RecyclerView's Adapter
private CategoryFragmentAdapter mCategoryFragmentAdapter;
//Category Data List
private ArrayList<Category> mCategoryList;
//Interface object
onCategoryItemClick mCallBackCategory;
#Override
public void onAttach(Context context) {
super.onAttach(context);
//Instantiate base context
mContext = context;
//Instantiate interface
mCallBackCategory = (onCategoryItemClick)getActivity();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Instantiate Category List
mCategoryList = new ArrayList<Category>();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//Custom fragment view instantiating
View view_fragment_category = inflater.inflate(R.layout.fragment_items, container, false);
//Instantiating Fragment's recycler view
mRecyclerView = (RecyclerView) view_fragment_category.findViewById(R.id.recycle_categories);
//Instantiate RecycleView's Layout Manager: LinearLayoutManager is one of the default
mLayourManager = new LinearLayoutManager(mContext);
//Setting layout manager for recycler view
mRecyclerView.setLayoutManager(mLayourManager);
//Retrieve data from server, populate the category data list and set the RecyclerView's adapter
getCategories();
//Instantiate the adapter and push the data
mCategoryFragmentAdapter = new CategoryFragmentAdapter(mContext, mCategoryList);
//RecyclerView item click listener
mCategoryFragmentAdapter.SetOnItemClickListener(new CategoryFragmentAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v , int position) {
//Test display
//Toast.makeText(mContext, mCategoryList.get(position).getId(),Toast.LENGTH_LONG).show();
//Push to Activity method with clicked item ID
mCallBackCategory.proceedToProducts(mCategoryList.get(position).getId());
}
});
return view_fragment_category;
}

Android Studio - Fragment button action

I tried to make an application that shows a fragment at start then you can change that fragment to an other one with a button in the first fragment. But when I put the button action in the fragments java, it won't start and I get the nullpointerexception error. Could you tell me why?
public class Fragment_main extends Fragment {
FragmentManager fm = getFragmentManager();
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Button button_inditas = (Button) getView().findViewById(R.id.button_inditas);
button_inditas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fm.beginTransaction().replace(R.id.content_frame, new Fragment_1()).commit();
}
});
return inflater.inflate(R.layout.fragment_main,container,false);
}
}
But when I put the button action in the fragments java, it won't start and I get the nullpointerexception error. Could you tell me why?
Well I see some errors on your code...
First of all you can't call getView() if you haven't inflated one, it means that you MUST inflate a view as i'll put on my answer and then you can avoid the getView() and use that view itself.
And instead of returning the inflater you have to return your View
This is how your Fragment should look like:
public class Fragment_main extends Fragment {
public Fragment_main() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main,container,false);
Button button_inditas = (Button)rootView.findViewById(R.id.button_inditas);
button_inditas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager ();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction ();
fragmentTransaction.add (R.id.content_frame, new Fragment_1());
fragmentTransaction.commit ();
});
return rootView;
}
}
You have to inflate the view first and use the view returned by that instead of getView ().
View view = inflater.inflate (...);
and then
... = (Button) view.findView(...);
This happens because the view that is returned by getView () hasn't been created yet, so getView() returns null.

FlipView Adapter not Updating

The adapter of a flipview is set onCreate. Everything works fine. The user is meant to select some items on another activity which would update the items on the flipview. I implemented this by changing the adapter of the flipView when onResume is called and the dismiss activity is the selectionActivity. The code is executed but it does not reflect on the flipView items.
What i do on onCreate
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View rootView = inflater.inflate(R.layout.flip_main, container, false);
mFlipView = (FlipView) rootView.findViewById(R.id.flip_view);
mAdapter = new FlipAdapter(getActivity(),getHomeItems(), getFragmentManager());
mAdapter.setCallback(this);
mFlipView.setAdapter(mAdapter);
mFlipView.setOnFlipListener(this);
if (isFirstShown) {
mFlipView.peakNext(false);
isFirstShown = false;
}
mFlipView.setOverFlipMode(OverFlipMode.RUBBER_BAND);
mFlipView.setEmptyView(getActivity().findViewById(R.id.empty_view));
mFlipView.setOnOverFlipListener(this);
return rootView;
}
what is called after the user makes selection
FlipAdapterTest mAdapter = new FlipAdapterTest(getActivity(), getHomeItems(), getFragmentManager());
mFlipView.removeAllViews();
mFlipView.setAdapter(mAdapter);

Fragment content does not show up until I switch it and select it again

I've got a problem with my Android app: my fragment content doesn't show up until I switch it and I select it again. What should load just at the fragment start is a list of Cards.
Here you got the onCreate method of the Fragment that loads everything:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bundle = this.getArguments();
debts = bundle.getParcelableArrayList("list");
adapter = new CardAdapter(getActivity(), android.R.color.holo_blue_dark);
for (int i=0; i<debts.size();++i) {
Debt d = debts.get(i);
Card card = new Card(d.getSecondUser(),d.getSubject());
adapter.add(card);
}
}
And here the onActivityCreated method where i set the adapter for the list:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
CardListView list = (CardListView) getView().findViewById(R.id.newCard);
list.setCardTheme(CardTheme.Light);
list.setAdapter(adapter);
}
It works if I use an ArrayList of Cards already loaded, but not this way.
I tried nearly everything... thank you very much.
UPDATE: Even I tried with the solutions you gave me, it keeps happening, my code now:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bundle = this.getArguments();
debts = bundle.getParcelableArrayList("list");
adapter = new CardAdapter(getActivity(), android.R.color.holo_blue_dark);
for (int i=0; i<debts.size();++i) {
Debt d = debts.get(i);
Card card = new Card(d.getSecondUser(),d.getSubject());
adapter.add(card);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_debts, container,
false);
CardListView list = (CardListView) rootView.findViewById(R.id.newCard);
list.setCardTheme(CardTheme.Light);
list.setAdapter(adapter);
return rootView;
}
You should initialize your cardListView inside the onCreateView() method. onCreateView() gets called before the onActivityCreated() method. onCreateView() should be the point when the view of your fragment is initialized.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//use your layout file instead of R.layout.fragment_main
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
CardListView list = rootView.findViewById(R.id.newCard);
list.setCardTheme(CardTheme.Light);
list.setAdapter(adapter);
}
Please take a look at the lifecycle of Fragments.

Categories