I have a BottomSheetDialogFragment and inside onCreateView i am inflating 2 different views based on a condition. Now my 1st view contains a recyclerView and the condition on which i want to switch my views is that if the list is empty then inflate view 1 else inflate view 2. Now my problem is when my list data count becomes 0 i want to call the onCreateView again so that based on the condition my 2nd view would be inflated. But i don't know how am i supposed to do it or rather is this the right way to do it.
My Code -
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
if (this.documentCount > 0) {
View v = inflater.inflate(R.layout.bottom_sheet_layout_document_attachments_added, container, false);
documentArrayList = dataToRender.get(fieldPosition).getAttachments();
Button attachMore = (Button) v.findViewById(R.id.btn_attachMore);
if(documentCount == 5){
attachMore.getBackground().setAlpha(128);
}else{
attachMore.getBackground().setAlpha(255);
}
attachMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try{
if(documentCount == 5){
PageLoader.showToast(getResources().getString(R.string.document_limit_message));
}else{
pickDocuments();
}
}
catch (Exception e){
Sentry.captureException(e);
}
}
});
Button btnCloseDrawer = (Button) v.findViewById(R.id.btn_closeDrawer);
btnCloseDrawer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
}
});
recyclerview_documents = v.findViewById(R.id.recyclerview_documents);
adapter_documents = new DocumentAdapter(this, documentArrayList, fieldPosition);
recyclerview_documents.setAdapter(adapter_documents);
recyclerview_documents.setLayoutManager(new LinearLayoutManager(mContext));
return v;
} else {
View v = inflater.inflate(R.layout.bottom_sheet_layout_document, container, false);
TextView txtview_attach = (TextView) v.findViewById(R.id.txtview_attach);
txtview_attach.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try{
permissionManager.checkPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE, new PermissionManager.PermissionAskListener() {
#Override
public void onNeedPermission() {
ActivityCompat.requestPermissions(getActivity(), new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE
}, REQUEST_EXTERNAL_STORAGE);
}
#Override
public void onPermissionPreviouslyDenied() {
showDocumentRational();
}
#Override
public void onPermissionPreviouslyDeniedWithNeverAskAgain() {
dialogForSettings(getResources().getString(R.string.permission_denied), getResources().getString(R.string.permission_denied_document_access_message));
}
#Override
public void onPermissionGranted() {
pickDocuments();
}
});
}
catch (Exception e){
Sentry.captureException(e);
}
}
});
return v;
}
}```
Can't use more then one views for one fragment, but you can create a fragment wrapper that depends on the conditions, will show or create the fragment you need with the view you need.
for example WrapperFragment checking list size and creating Fragment1, when list size changed Wrapper fragment removung from fragment manager Fragment1 and add Fragment2
Related
The app is for Attendance with barcode.
The scan function work fine until i change to other fragment / activity and back to it. If that happen then the camera will scan but it will not return anything and on back press it wont show any toast (even thought it should).
If i close the app then reopen it, open this fragment and scan, it back to normal again until i change to other fragment / activity.
There isnt any error message. So i dont know where the error is.
This is parts of my code that i believe have something to do with this bug:
onCreateView:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_attendance, container, false);
fetch();
return v;
}
fetch:
private void fetch() {
FirebaseRecyclerOptions <ModelEvent> options = new FirebaseRecyclerOptions.Builder<ModelEvent>()
.setQuery(query, snapshot -> new ModelEvent(
Objects.requireNonNull(snapshot.child("eventID").getValue()).toString(),
Objects.requireNonNull(snapshot.child("eventStatus").getValue()).toString()))
.build();
adapter = new FirebaseRecyclerAdapter<ModelEvent, ViewHolderEvent>(options) {
#NonNull
#Override
public ViewHolderEvent onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_attendance, parent, false);
return new ViewHolderEvent(view);
}
//Set data on each list
#Override
protected void onBindViewHolder(#NonNull ViewHolderEvent viewHolderEvent, int i, #NonNull ModelEvent modelEvent) {
viewHolderEvent.setStringStatus(modelEvent.getEventStatus());
viewHolderEvent.buttonScan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stringEventID = modelEvent.getEventID();
ScanOptions options = new ScanOptions();
options.setDesiredBarcodeFormats(ScanOptions.ALL_CODE_TYPES);
options.setPrompt("Scan something");
options.setOrientationLocked(true);
options.setBeepEnabled(true);
fragmentLauncher.launch(options);
}
});
}
};
recyclerViewAttendance.setAdapter(adapter);
}
for scanner:
private final ActivityResultLauncher<ScanOptions> fragmentLauncher = registerForActivityResult(new ScanContract(),
result -> {
//On Backpress
if(result.getContents() == null) {
Toast.makeText(getContext(), "Cancelled", Toast.LENGTH_LONG).show();
}
else {
//Get data from QRCode
stringQR = result.getContents();
getUserData();
setUserAttendance();
//Notification
Toast.makeText(getContext(), "Name: " + stringName, Toast.LENGTH_LONG).show();
}
});
onStart:
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
This is the full code: https://pastebin.com/e7XZN08i
So i just do many thing and ended up find what i should do.
switch (item.getItemId()) {
case R.id.nav_event:
fragmentEvent = new FragmentEvent(); //i just need to add this on all case for some reason, the tutorial i use dont do this
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragmentEvent).commit();
return true;
I also ask this on github:https://github.com/journeyapps/zxing-android-embedded/issues/695
I tried many options and solutions but I am still not able to get on Click event on ViewHolder. i.e. viewHolder.mView.setOnClickListener is not working in fragment. I have used same code in activity and its working perfectly but not in Fragment.
gradle dependecy:
implementation 'com.android.support:recyclerview-v7:26.1.0' <br>
implementation 'com.firebaseui:firebase-ui-database:2.3.0'
Code:
public class OffersFragment extends Fragment {
private View mMainView;
private RecyclerView mBusinessOffersList;
private RecyclerView.LayoutManager mLayoutManager;
public OffersFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mMainView = inflater.inflate(R.layout.fragment_offers, container, false);
//------Recyclerview to show Business Gallery ------------//
mBusinessOffersList = mMainView.findViewById(R.id.businessOffersList);
mBusinessOffersList.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mBusinessOffersList.setLayoutManager(mLayoutManager);
.
.
.
if(currentUser!=null && mBusinessUserID != null){
mdatabaseOffers = FirebaseDatabase.getInstance().getReference().child("Offers")
.child(BusinessCity).child(mBusinessUserID);
}
return mMainView;
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter <EshopOffers, BusinessOffersViewHolder> mfirebaseRecycleAdapter = new FirebaseRecyclerAdapter<EshopOffers, BusinessOffersViewHolder>
( EshopOffers.class,
R.layout.shop_offerslist_layout,
BusinessOffersViewHolder.class,
mdatabaseOffers) {
#Override
protected void populateViewHolder(final BusinessOffersViewHolder viewHolder, EshopOffers model, int position) {
//---tried--Method 1: Open new Activity on CLick----but no luck--------//
viewHolder.mView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "Item Clicked", Toast.LENGTH_LONG).show();
}
});
}
};mBusinessOffersList.setAdapter(mfirebaseRecycleAdapter);
}
public static class BusinessOffersViewHolder extends RecyclerView.ViewHolder {
View mView;
public LinearLayout offerLayout;
ImageView offerImage1;
LinearLayout offerLayout2;
// public RelativeLayout offerRLlayout;
public BusinessOffersViewHolder(View itemView) {
super(itemView);
mView = itemView;
//---tried--Method 2: Open new Activity on CLick----but no luck--------//
itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Log.i("View Clicked", "View Clicked");
}
});
}
}
}
I have tried most of the solutions from: RecyclerView onClick and how to implement a SetOnItemClickListener FirebaseRecyclerViewAdapter but no luck. :(
I have scratched my head for almost 2 days 3 nights but still going nowhere ...:( so now need your help..!
I have a Activity with TabLayout and ViewPager. I have two fixed buttons floating on top of the activity at bottom right corner. These two buttons are Plus and Minus buttons for increasing/decreasing the font sizes of the text inside the fragment. I created an Interface inside Activity and implemented it inside the fragment where I am changing the textsize of TextView.
Problem is that it does not work at the time when I click the button. When I swipe the fragment then it shows with updated textsize. Am I missing something? Is this the correct way?
Inside Activity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.post_single);
//....
onCoachMark();
//....
}
public void onCoachMark() {
final FrameLayout overlayFramelayout = new FrameLayout(getApplicationContext());
setContentView(overlayFramelayout);
View view = getLayoutInflater().inflate(R.layout.post_single, overlayFramelayout, false);
final View overlay_view = getLayoutInflater().inflate(R.layout.zoom_overlay, overlayFramelayout, false);
final ImageView ivPlus = (ImageView) overlay_view.findViewById(R.id.ivPlus);
final ImageView ivMinus = (ImageView) overlay_view.findViewById(R.id.ivMinus);
overlayFramelayout.addView(view);
overlayFramelayout.addView(overlay_view);
ivPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommonFunctions.FONT_SIZE += 3;
CommonFunctions.putMySharedPreferences(getApplicationContext(), "fontSize", String.valueOf(CommonFunctions.FONT_SIZE));
iCoachMark.onTextSizeChange();
}
});
ivMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommonFunctions.FONT_SIZE -= 3;
CommonFunctions.putMySharedPreferences(getApplicationContext(), "fontSize", String.valueOf(CommonFunctions.FONT_SIZE));
iCoachMark.onTextSizeChange();
}
});
}
public interface ICoachMark {
void onTextSizeChange();
}
public void setOnCoachMark(ICoachMark iCoachMark) {
this.iCoachMark = iCoachMark;
}
Inside Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.post_content, container, false);
tvTitle = (TextView) rootView.findViewById(R.id.tvTitle);
tvDescription = (TextView) rootView.findViewById(R.id.tvDescription);
svPost = (NestedScrollView) rootView.findViewById(R.id.svPost);
String fs = CommonFunctions.getMySharedPreferences(getActivity().getApplicationContext(), "fontSize");
if (fs.matches("")) {
CommonFunctions.putMySharedPreferences(getActivity().getApplicationContext(), "fontSize", String.valueOf(CommonFunctions.FONT_SIZE));
} else {
CommonFunctions.FONT_SIZE = Integer.valueOf(fs);
tvTitle.setTextSize(CommonFunctions.FONT_SIZE);
tvDescription.setTextSize(CommonFunctions.FONT_SIZE);
}
((PostActivity) getActivity()).onTextSizeChange(new PostActivity.ICoachMark() {
#Override
public void onTextSizeChange() {
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, CommonFunctions.FONT_SIZE);
tvDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, CommonFunctions.FONT_SIZE);
}
});
}
I have a popupWindow that modifies a SQLight table that loads a spinner in the parent window. I would like to have the spinner in the parent window refreshed with the new values when I dismiss the PopupWindow. The code below shows my progress creating a listener that would detect the PopupWindow's dismissal. The listener that I have so far does not work. I think that I have missed something in structuring the listener. I've included the ShowPopup class as well as the fragment (Tab3Fragment) that is the parent to this window.
showPopup.java
public class showPopup extends PopupWindow{
Context m_context;
Button btnDismiss;
PopupWindow popup;
Tab3Fragment Tab3Fragment;
OnDismissListener listener;
public showPopup(Context context){
super(context);
m_context = context;//was commented out
setContentView(LayoutInflater.from(context).inflate(R.layout.popup_layout, null));
setHeight(LayoutParams.WRAP_CONTENT);
setWidth(LayoutParams.WRAP_CONTENT);
}
public void init(View v){
LayoutInflater inflater = (LayoutInflater)m_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View popUpView = inflater.inflate(R.layout.popup_layout, null, false);
final PopupWindow popup = new PopupWindow(popUpView, 600, 400, true);
popup.setContentView(popUpView);
popup.showAtLocation(v, Gravity.CENTER_HORIZONTAL, 0, 0);
btnDismiss = (Button) popUpView.findViewById(R.id.btndismissxml);
btnDismiss.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View anchor) {
popup.dismiss();
}
});
}
#Override
public void setOnDismissListener(OnDismissListener listener){
this.listener = listener;
}
}
Tab3Fragment.java
public class Tab3Fragment extends Fragment implements OnClickListener{
Context context;
Button btnPopup, btnSpinnerRefresh;
Spinner spinnerSpecies;
public static int iSpeciesPosition;
showPopup showPopup;
ArrayAdapter<String> arrayAdapterSpecies;
OnDismissListener dismissListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup containerGroup, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab3_fragment, containerGroup, false);
btnPopup = (Button)v.findViewById(R.id.btnPopupxml);
btnPopup.setOnClickListener(this);
btnSpinnerRefresh = (Button)v.findViewById(R.id.btnSpinnerRefreshxml);
btnSpinnerRefresh.setOnClickListener(this);
spinnerSpecies = (Spinner) v.findViewById(R.id.spinnerSpeciesxml);
spinnerSpecies.setAdapter(arrayAdapterSpecies);
if(savedInstanceState != null){
iSpeciesPosition = savedInstanceState.getInt("speciesPosition_key");
populateTab3Fragment(v);
}else if(savedInstanceState == null){
populateTab3Fragment(v);
}
return v;
}
//#Override
public void onViewCreated(View v) {
populateTab3Fragment(v);
/******************************************************************************************************
Can setOnDismissListener be used outside of showPopup class to indicate that showPopup has dismissed?
******************************************************************************************************/
showPopup popup = new showPopup(context);
popup.setOnDismissListener(new OnDismissListener(){
#Override
public void onDismiss(){
Toast.makeText(getActivity().getApplicationContext(), "onDismiss() works.", Toast.LENGTH_LONG).show();
loadSpinnerData();
}
});
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnPopupxml:
new showPopup(getActivity().getApplicationContext()).init(v);
break;
case R.id.btnSpinnerRefreshxml:
loadSpinnerData();//temporary workaround to refresh spinner...
break;
}
}
/**
* Function to load the spinner data from SQLite database
* */
public void loadSpinnerData() {
//omitted
}
public void populateTab3Fragment(View v){
loadSpinnerData();
}
}
Never got to the point where I could refresh the parent window directly on the child PopupWindow dismiss. The final solution (workaround) was to use fragmentmanager replace() after an onTouch event from the spinner only when a static flag (iSpeciesRefresh) had been set that indicated a modified SQL spinner lookup table.
public class dataCapture extends Fragment implements OnClickListener {
String szSpecies;
static public int iSpeciesRefresh = 1;
Spinner spinnerSpecies;
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.data_capture, container, false);
...
spinnerSpecies = (Spinner) v.findViewById(R.id.spinnerSpeciesxml);
spinnerSpecies.setOnTouchListener(new View.OnTouchListener() {//refreshes fragment as needed...
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (iSpeciesRefresh == 1) {//this is application default
//do nothing
} else if (iSpeciesRefresh == 0) {//value is reset to "0" at SAVE, UPDATE, or DELETE in speciesPopupWindow.
refreshDataCapture();
iSpeciesRefresh = 1;
}
return false;
}
});
...
}
public void refreshDataCapture() {
Fragment currentFragment = (dataCapture) getFragmentManager().findFragmentByTag("data_capture");
if (currentFragment == null) {
currentFragment = new dataCapture();
} else if (currentFragment != null) {
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getFragmentManager().beginTransaction().replace(R.id.fragment_placeholder, new dataCapture(), "data_capture").addToBackStack(null).commit();
}
}
In your onCreateView and onViewCreated methods, you do btnPopup.setOnClickListener(this);, but then in your showPopup class' init() method, you overwrite your fragment as the listener and instead assign a new anonymous listener. My guess is that you need to rework how you assign your listener and make sure you don't overwrite it like that.
P.S. For maintainability's sake (and the sanity of other developers who look at your code), it's convention to name classes with upper camel case and they should not contain verbs. Something like MyCustomPopup would be better.
I have a list fragment on the left of another fragment and is essentially the standard click an item and update the right fragment pattern. When they click an item in the list fragment they are choosing the news article category and I need to keep whatever one is selected when they rotate the device. How do I do that? My current code doesn't work.
My code is as follows:
public class SideMenuFragment extends ListFragment {
ArrayList<SideItem> sideItems;
SideAdapter sideAdapter;
public SideMenuFragment() {
this.setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.list, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sideItems = new ArrayList<SideItem>();
...add bunch of items
sideAdapter = new SideAdapter(getActivity(), sideItems);
getListView().setVerticalScrollBarEnabled(false);
setListAdapter(sideAdapter);
if (savedInstanceState != null) {
sideAdapter.setSelectedItem(savedInstanceState.getInt("sidePosition"));
sideAdapter.notifyDataSetChanged();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("sidePosition", sideAdapter.getSelectedItem());
}
#Override
public void onListItemClick(ListView lv, View v, int position, long id) {
if (sideAdapter.getSelectedItem() != position) {
sideAdapter.setSelectedItem(position);
sideAdapter.notifyDataSetChanged();
}
switch (position) {
...switch the fragment depending on position.
}
}
// the meat of switching the above fragment
private void switchFragment(Fragment fragment, String title) {
if (getActivity() == null)
return;
if (getActivity() instanceof HomeActivity) {
HomeActivity a = (HomeActivity) getActivity();
a.switchContent(fragment, title);
}
}
}
First, add your Fragment in xml if the Activity layout.
In Activity onCreate
getFragmentManager().findFragmentById(R.id.youtfragmentid).setRetainInstance(true)
This means that the fragment will not be recreated on activity recreate.
Don't change your ListView in onActivityCreated - because it will be rebuilt every time orientation changes. If you set a new adapter - the states of children will be reseted.
Add checking for null or a boolean flag that the view already was created.
Next time onActivityCreated gets called, your list adapter should not change
if (sideAdapter == null) {
sideAdapter = new SideAdapter(getActivity(), sideItems);
getListView().setVerticalScrollBarEnabled(false);
setListAdapter(sideAdapter);
}
Also, don't create new view in onCreateView instead use previously created one.
private View v;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (v == null) {
v = inflater.inflate(R.layout.list, null);
} else {
// detatch from container and return the same view
((ViewGroup) getListView().getParent()).removeAllViews();
}
return v;
}