how to settext button in bottom sheet dialog fragment? - java

i have one class for bottomsheetdialog fragment.I looked at many places but I'm confused.i want to change text of button in bottom sheet.i get this error 'android.view.View android.view.View.findViewById(int)' on a null object reference.
here are my codes;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(final Bundle savedInstanceState) {
bottomSheetFragment=new BottomSheetFragment();
View viewDialog=bottomSheetFragment.getView();
assert viewDialog != null;
MaterialButton btn_titresim=viewDialog.findViewById(R.id.btn_titresim);
btn_titresim.setText("text");
}
}
Another class for BottomSheetDialogFragment
public class BottomSheetFragment extends BottomSheetDialogFragment {
public BottomSheetFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Objects.requireNonNull(getDialog()).setOnShowListener(dialog -> {
BottomSheetDialog d = (BottomSheetDialog) dialog;
View bottomSheetInternal =
d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
assert bottomSheetInternal != null;
BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
});
return inflater.inflate(R.layout.layout_popup, container, false);
}
}

You can solve this by having a listener interface in your fragment that returns the BottomSheet fragment's View back to your activity, so you can then access the BottomSheetDialogFragmentunderlying views normally by findViewById() method.
Here I decided to use the Singleton pattern for the BottomSheetDialogFragment to set a listener instance from the activity.
So in your fragment add a listener; it's named below FragmentListener, call the listener callback in onCreateView() or in onViewCreated()
public class BottomSheetFragment extends BottomSheetDialogFragment {
public BottomSheetFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
interface FragmentListener {
void getView(View view);
}
static FragmentListener mFragmentListener;
public static BottomSheetFragment newInstance(FragmentListener listener) {
mFragmentListener = listener;
return new BottomSheetFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Objects.requireNonNull(getDialog()).setOnShowListener(dialog -> {
BottomSheetDialog d = (BottomSheetDialog) dialog;
View bottomSheetInternal =
d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
assert bottomSheetInternal != null;
BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED);
});
View view = inflater.inflate(R.layout.layout_popup, container, false);
// Trigger the listener callback to return the view back to the activity
// mFragmentListener.getView(view); // Not working in all devices
return inflater.inflate(R.layout.layout_popup, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
// Trigger the listener callback to return the view back to the activity
mFragmentListener.getView(view);
}
}
implement the listener by your activity, and change the text in your callback, and instantiate the BottomSheetDialogFragment using the singleton pattern instead.
public class MainActivity extends AppCompatActivity implements BottomSheetFragment.FragmentListener {
#Override
protected void onCreate(final Bundle savedInstanceState) {
bottomSheetFragment = BottomSheetFragment.newInstance(this);
}
#Override
public void getView(View view) {
// Setting the text
((MaterialButton) view.findViewById(R.id.btn_titresim)).setText("text");
}
}
Wish that solves your problem

Related

how to replace the fragment1 from fragment2 from a button click of a dialog[NOT DIALOG FRAGMENT] (which is called by fragment1)

I am facing a problem where I am opening a dialog (Dialog 1) from fragment1 and there is a button (change) on Dialog1 on which if I click then: Dialog1 should be dismissed and on the same fragment1 should be replaced by fragment2(Another fragment)
public class PedigreeAnalysis extends Fragment //My Fragment1
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
showDialog();
}
// SHOW DIALOG FUNCTION IS SHOWN BELOW `
void showDialog() { //Function to show the dialog starts...
Dialog dialog= new Dialog(getActivity());
Button btn = dialog.findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Code for opening new fragment and dismissing the dialog.
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment1, new Fragment2()).commit();
dialog.dismiss();
}
});
}//Function Ends Here....
I have even tried the reverse logic of (dismissing the dialog first and then replacing it with the function but it also doesn't works) as :
dialog.dismiss();//First dismissing the dialog
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment1, new Fragment2()).commit();//Replacing the fragment
Follow this...
Fragment1:
public class Fragment1 extends Fragment {
private ItemClickListener itemClickListener;
private Button addButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// all the views are initialized here...
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
addButton.setOnClickListener(v -> {
if (itemClickListener != null) onItemClicked.onClicked(new Plan());
});
}
public Fragment1 setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
return this;
}
public interface ItemClickListener {
void onItemClicked(Plan plan);
}
}
In parent Activity Class
public class PlanActivity extends AppCompatActivity {
private Fragment1 fragment1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plan);
fragment1 = new Fragment1()
.setOnAddButtonClicked(this::openFragmentEditPlan);
openFragment1();
}
private void openFragment1() {
getSupportFragmentManager().beginTransaction()
//frameLayout_PlanActivity is the container of both fragments
.add(R.id.frameLayout_PlanActivity, fragment1)
.commit();
}
public void openFragmentEditPlan(Plan plan) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frameLayout_PlanActivity, FragmentEditPlan.newInstance(plan))
.addToBackStack("Fragment Edit Plan")
.commit();
}
}

Views of Fragment Layout causing NullPointerException

I'm trying to use View Pager with Fragment State Adapter. But getting a NullPointerException when trying to invoke a Fragment method after creating its instance.
Here is the activity class and Adapter class:
public class AddScheduleActivity extends AppCompatActivity {
private FragmentOverview fragmentOverview;
private FragmentTodo fragmentTodo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_schedule);
ViewPager2 viewPager = findViewById(R.id.viewPager_AddScheduleActivity);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getLifecycle()));
fragmentOverview = new FragmentOverview();
fragmentOverview.setTargetView(); //ERROR IS HERE
My view pager adapter is:
private class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
#NonNull
#Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return fragmentOverview;
case 1:
return fragmentTodo;
default:
return null;
}
}
#Override
public int getItemCount() {
return 2;
}
}
My FragmentOverView class is:
public class FragmentOverview extends Fragment{
private FrameLayout mTargetFrameLayout;
private FrameLayout mDescriptionFrameLayout;
public FragmentOverview() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_overview, container, false);
mDescriptionFrameLayout = rootView.findViewById(R.id.descriptionView_frameLayout_OverviewFragment);
mTargetFrameLayout = rootView.findViewById(R.id.targetView_frameLayout_OverviewFragment);
return rootView;
}
public void setTargetView() {
mTargetFrameLayout.removeAllViews();
if (progress.maxProgress != null) {
//ADD A CHILD VIEW
mTargetFrameLayout.setVisibility(View.VISIBLE);
} else mTargetFrameLayout.setVisibility(View.GONE);
}
}
But when I call the setTargetView() method after creating instance of FragmentOverview, I'm getting a NullPointerException. From log I noticed that the mTargetFrameLayout is null.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.FrameLayout.removeAllViews()' on a null object reference
I think this is because the activity lifecycle methods onCreate(), onStart(), onResume() are called before the fragment lifecycle methods onCreate() & onCreateView(). But how to overcome this problem? Or am I trying to do in a wrong way?
I think your assumption is right. The fragment layout is generated in onViewCreated() of FragmentOverview class. But this method start executing after the Activity lifecycle methods onCreate(), onStart() and onResume() are executed. You can checkout the lifecycle relation of Activity and Fragment by overwriting lifecycle methods and adding logs as mentioned by #Max_Hockeborn.
So you will always get the views i.e mTargetFrameLayout null if you call setTargetView() before executing onCreateView() in FragmentOverview.
To solve this, you can add a callback method that will be executed in parent class after executing the onCreateView() of FragmentOverveiw. And in that callback you can invoke setTargetView().
Here I'm providing a possible solution for your case:
In FragmentOverview add this lines:
public class FragmentOverview extends Fragment{
//all your fields;
private OverviewCallbacks callbacks;
public FragmentOverview(OverviewCallbacks callbacks) {
this.callbacks = callbacks;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//inflate the rootView and find all the childViews;
//I think your codes are okey;
}
//Overwrite this method;
//You can also overwrite onViewCreated() lifecycle method;
//And add call this callback method from here;
#Override
public void onResume() {
super.onResume();
callbacks.onReach();
}
public void setTargetView() {
//Do what you want to do;
}
public interface OverviewCallbacks {
void onReach();
}
}
Thats all for FragmentOverView class.
Now modify your Activity class as follows:
public class AddScheduleActivity extends AppCompatActivity {
private FragmentOverview fragmentOverview;
private FragmentTodo fragmentTodo;
#Override
protected void onCreate(Bundle savedInstanceState) {
//Your codes
fragmentOverview = new FragmentOverview(new FragmentOverview.OverviewCallbacks() {
#Override
public void onReach() {
setTargetView();
}
});
}
}
Hope this will work. Comment if anything gone wrong.
This is just a fast idea that I couldn't test yet.
You could try to change this:
public class AddScheduleActivity extends AppCompatActivity {
private FragmentOverview fragmentOverview;
private FragmentTodo fragmentTodo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_schedule);
ViewPager2 viewPager = findViewById(R.id.viewPager_AddScheduleActivity);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getLifecycle()));
fragmentOverview = new FragmentOverview();
fragmentOverview.setTargetView(); //ERROR IS HERE
to this:
public class AddScheduleActivity extends AppCompatActivity {
private FragmentOverview fragmentOverview = new FragmentOverview();
private FragmentTodo fragmentTodo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_schedule);
ViewPager2 viewPager = findViewById(R.id.viewPager_AddScheduleActivity);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getLifecycle()));
fragmentOverview.setTargetView(); //ERROR IS HERE
To check your assumption that your problem is based on the call order you can add some logs and check the order they are called in with Logcat (given you use android studio)
Something like this:
public class AddScheduleActivity extends AppCompatActivity {
private FragmentOverview fragmentOverview;
private FragmentTodo fragmentTodo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_schedule);
ViewPager2 viewPager = findViewById(R.id.viewPager_AddScheduleActivity);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getLifecycle()));
Log.d("YOUR_TAG","Activity onCreate 1");
fragmentOverview = new FragmentOverview();
fragmentOverview.setTargetView(); //ERROR IS HERE
and
public class FragmentOverview extends Fragment{
private FrameLayout mTargetFrameLayout;
private FrameLayout mDescriptionFrameLayout;
public FragmentOverview() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_overview, container, false);
mDescriptionFrameLayout = rootView.findViewById(R.id.descriptionView_frameLayout_OverviewFragment);
mTargetFrameLayout = rootView.findViewById(R.id.targetView_frameLayout_OverviewFragment);
Log.d("YOUR_TAG","FragmentOverview onCreateView 1");
return rootView;
}
public void setTargetView() {
Log.d("YOUR_TAG","FragmentOverview setTargetView 1");
mTargetFrameLayout.removeAllViews();
if (progress.maxProgress != null) {
//ADD A CHILD VIEW
mTargetFrameLayout.setVisibility(View.VISIBLE);
} else mTargetFrameLayout.setVisibility(View.GONE);
}
}
The last one could be interesting for you to see if onCreateView (and the initiation of the variables that cause your problems) is finished before the setTargetView() function is called.

Passing data through Fragments

My app is simple just i have a FragmentA and FragmentB first one has a single button pass String data ("Hi i'm A") through second fragment who has a text to show this message My question is
Why my "ModifyTxt" method doesn't work ?
public class newFragmentA extends Fragment{
Button button;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.newfragmenta_layout,container,false);
}
newFragmentB newfragmentB;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
button = getActivity().findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
newfragmentB.ModifyTxT("Hi I'm A");
}
});
}
}
And this is my second Fragment(FragmentB)
public class newFragmentB extends Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.newfragmentb_layout,container,false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
textView = getActivity().findViewById(R.id.TV);
}
public void ModifyTxT(String string){
textView.setText(string); }
}
Try this:
public class FragmentB extends Fragment {
// ...
public static FragmentB newInstance() {
return new FragmentB();
}
}
In FragmentA :
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentB newFragment = FragmentB.newInstance();
newFragment.modifyTxT("Hi I'm A");
}
});
Be careful to coding rules : uppercase first letter for class name, lowercase first letter for method...
Prefer using Interface to communicate with Fragments
public class FragmentA extends Fragment{
public interface MyCallback{
void modifyTxT(String text); // method naming convention start with small letter.
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
button = getActivity().findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (newfragmentB instanceof MyCallback) {
((MyCallback)newfragmentB).modifyTxT("Hi I'm A");
}
}
});
}
}
public class FragmentB extends Fragment implements FragmentA.MyCallback{
public static FragmentB getInstance(){
return new FragmentB();
}
#Override
public void modifyTxT() {
}
}

OnClick not triggered inside Fragment

Got two empty Activites(A and B), which just hold two fragments inside ViewPager of Activity A.
I do not have code errors, everything seems fine.
When I lunch my app and click on button, nothing happens.I was trying just to log something, but still nothing is happening.
I am using ButterKnife, and so far everything was perfect.I got almost same Fragment and it is performing fine, but OnClick inside Fragment B is not working.I tried to add some more OnClick methods, but none of them worked for me.XML looks good,looks almost same as fragment A.
Fragment B is not complex, it just three TextViews and Button.
Here is code for my fragment B:
public class ForgotPasswordFragmentComplete extends BaseFragment
implements BaseView {
private Realm realm;
private Email model;
#Bind(R.id.btn_resend)
AppCompatButton resendEmail;
#Inject
ForgotPasswordPresenter presenter;
#OnClick(R.id.btn_resend)
public void resendButton() {
Log.d("ResendOnclick", "Checking OnClickMethod ");
Realm realm2 = getRealm();
RealmQuery<Email> queryUserResend = realm2.where(Email.class);
Email resultResend = queryUserResend.findFirst();
ForgotPasswordPayload forgotPayload = new ForgotPasswordPayload(resultResend.getUsername());
this.presenter.subscribe(forgotPayload);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DaggerForgotPasswordCompletedComponent.builder()
.applicationComponent(
((AndroidApplication) getActivity().getApplication()).getApplicationComponent())
.forgotPasswordCompletedModule(new ForgotPasswordCompletedModule())
.build()
.inject(this);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
protected void onCreateViewWidgetInitialization(View view) {
super.onCreateViewWidgetInitialization(view);
}
#Override
public void onStart() {
super.onStart();
getEmail();
}
public void getEmail(){
Realm realm = getRealm();
RealmQuery<Email> queryUser = realm.where(Email.class);
Email result1 = queryUser.findFirst();
resendEmailTxt = (AutoResizeTextView) getView().findViewById(R.id.resend_user_email);
if (resendEmailTxt != null) {
this.resendEmailTxt.setText(result1.getUsername());
}
}
#Override
public void onDestroy() {
super.onDestroy();
realm.close();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_forgot_password_fragment_complete, container, false);
}
#Override
protected int getFragmentLayoutId() {
return R.layout.fragment_forgot_password_fragment_complete;
}
You need to bind the fragment's view object before you can use it. Try putting the following code inside onCreateView() :
View rootView = inflater.inflate(R.layout.fragment_forgot_password_fragment_complete, container, false);
ButterKnife.bind(this, rootView);
return rootView;

Call a fragmentMethod from another fragment, but can't refer to them in parentFragmentActivity's View pager

I m new to android and i m having trouble with fragment communication, reading about it discovered the standard method of creating an interface and implementing it from the parentActivity which doesn't work in my case which is as follows.
I have an Activity named as ActivityA which extends fragment activity,in which i have a view pager for i want to keep two fragments namely fragmentA and fragmentB which should be swipable fragments.
fragmentA has a button which onClicked should make a change in fragmentB, to be precise on click it should add a string in the listView in fragmentA.
Now i have created the both the fragments's layouts as well as added the viewPAger to my FragmentActivity, they work great on swiping, the function is executed onButtonClick of fragmentA and logic works perfectly, after this is i want the changes to be reflected in fragmentB.
Using the interface method i can't find the reference to my fragment by id as it is added by viewPager to ActivityA
How do i do this??
help me out.
Stackoverflow says don't ask questions with out code so
Here is the Sample code
Activity A which has a virewPAger, need help how to get my fragment's Reference from the viewPager
public class ActivityA extends FragmentActivity implements FragmentA.Communicator
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_A);
viewPager= (ViewPager) findViewById(R.id.pager);
fragmentManager=getSupportFragmentManager();
viewPager.setAdapter(new myAdapter(fragmentManager));
}
class myAdapter extends FragmentPagerAdapter{
public myAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = null;
switch (i){
case 0: fragment = new listOfIDsScanned();
break;
case 1: fragment = new displayCounter();
break;
default: //something witch won't crush the app
break;
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
}
This is fragmentA , actual fragment name is something else just for simple representation calling it fragmentA, which has an interface Communicator to communicate between fragments
public class fragmentA extends android.support.v4.app.Fragment implements View.OnClickListener
{
TextView counter;
Button scanStudentID;
int count=0;
String name=null,rollNo=null;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.display_counter,container,false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
scanStudentID= (Button) getActivity().findViewById(R.id.startScanning);
scanStudentID.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
switch(v.getId()){
case R.id.startScanning:
startScanning();
break;
}
}
public void startScanning()
{
startActivityForResult(new Intent(getActivity(),Barcode.class),1);
}
public interface Communicator
{
// necessary methods
}
}
now finally fragmentB, in which methodToBeCalled(parameters) has to be invoked on the button click in fragementA
public class fragementB extends android.support.v4.app.Fragment
{
ListView listView;
ArrayList<String> rollNo= new ArrayList<>();
ArrayList<String> studentName= new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_list_of_ids_scanned,container,false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listView= (ListView) getActivity().findViewById(R.id.listView);
}
public void methodToBeCalled(String rollNo,String studentName)
{
if(!alreadyScanned(rollNo))
{
}
else
{
}
}
boolean alreadyScanned(String rollNo)
{
return true;
}
}

Categories

Resources