Are UI elements initiated in Fragment or FragmentActivity? - android

I am porting Activity-type app to Fragments-type app. I am a bit confused where I am supposed to initiate UI elements of the fragment.
For example, if I initiate a button from Fragment class in FragmentActivity class, I get no error.
btnOne = (Button) findViewById(R.id.btn_one);
But, if I try to initiate onClick listener, then I get error of type java.lang.NullPointerException.
Then again, I cannot find method findViewById in the Fragment class.
Am I really forced to initiate in FragmentActivity and to specify listeners in Fragment?

You initiate your button in the fragment usually. An example would be:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.yourlayout, container, false);
Button yourbutton = (Button) fragmentView.findViewById(R.id.button);
yourbutton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//Do your thing
}
}
return fragmentView;
}

Related

fragment does not go to activity [Android]

It's been less than a week since I learned Android. trying to create a project, but there are some things that don't work.
Problem: Does not move from fragment to activity
Tried: Browse the document on Google. and I used #Override for onclickListener in HomeFragment.java A red line popped up and woke up remove, but still don't know what the error is.
HomeFragment.java
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
private Button btn_today;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
ViewGroup root_view = (ViewGroup)inflater.inflate(R.layout.fragment_home, container, false);
Button btn_today = (Button)root_view.findViewById(R.id.btn_today);
btn_today.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), HomeActivity.class);
startActivity(intent);
}
});
return root;
}
}
used the Navigation Drawer Activity when I first created the project.
what I want to do is click on the button btn_today to go to the activity page (in xml file)
I'm a beginner or I don't know what the problem is. appreciate any help
doing it all day, but I'm not sure.
You should be use root variable for finding button view id.
Button btn_today = (Button)root.findViewById(R.id.btn_today);

Fragment onClickListener Not registering Click

I've gone through all the search results on SO and I can't find one that solves my issue. I have a fragment and I am trying to use an ImageButton to close the fragment. But my onClickListener will not register a click. I placed a break-point on the line and it was never hit.
ImageButton closeButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView;
if (getArguments().getBoolean("invert") == true) {
rootView = inflater.inflate(R.layout.popup_inverted_header_and_text, container, false);
}else {
rootView = inflater.inflate(R.layout.popup_header_and_text, container, false);
}
rootView.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
closeButton = (ImageButton) rootView.findViewById(R.id.closeButton);
closeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getFragmentManager().popBackStackImmediate();
}
});
return rootView;
}
From my research, the way you add a fragment to a view could affect this, so here is the code where I add the fragment.
FragmentManager fragmentManager = getFragmentManager();
headerAndTextFragment hatf = headerAndTextFragment
.newInstance("Information on GlassFrogg review process",
"Here is some information about the review process that you probably didn't actually want to know",
true);
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.popupContainer, hatf);
transaction.addToBackStack(null).commit();
Please make sure you are using same id 's in both the layouts since you have a single ImageButton defined in the class on which the listener is registered.
Since you are inflating two different layouts. Are you sure both the Layout has that ImageButton ? and both have same ID ?
when you open the fragment, you don't add the fragment to backStack, so when you click to imagebutton, there is no fragment in the backStack to pop.
use this
closeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getFragmentManager().beginTransaction().remove(YOUR_FRAGMENT_NAME.this).commit();
}
});

Tabbed activity(fragment) to activity navigation using onClick

I have a Tabbed activity with 3 tabs and each tab has its own fragment.
there's a button inside the first tab which i want to click and navigate to another Tabbed activity (or any activity which has a fragment). How do I accomplish this ? I am trying to click on a button and open a new activity but i am unable to do so. I would really appreciate if i get some headers as I'm learning android. Here's a link to my fragment class for reference.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tutorials,container, false);
Button button1 = (Button) view.findViewById(R.id.introbtn1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent tutorial = new Intent(getActivity(), TutorialIntroduction.class);
startActivity(tutorial);
//Tried to create a toast to check if the button works but it doesn't
//Toast.makeText(getActivity(), "button is clicked!", Toast.LENGTH_LONG).show();
}
});
return view;
}
In your fragment create a ViewPager variable and a setter method for it that is called when the fragment is created in your activity(its better to do this in constructor but it says you require it empty). Then in the onClick
ViewPager.setCurrentItem(FragmentPostion)
FragmentPostion is the int of which page you want to switch to, in your case from 0-2 (or 1-3 can't remember, try both haha).

Fragment with buttons: onClick() vs. XML onClick

I have a rather simple screen that only has 4 buttons. I'm implementing it as a Fragment like so:
public class MainFragment extends Fragment implements View.OnClickListener {
// ...
#Override
public void onClick(View view) {}
}
Each button already has onClick specified to a function in the Activity that the Fragment is attached. The issue I'm having is that the onClick functions aren't called when the buttons are clicked. I've left MainFragment.onClick() empty - but is that the right approach? Does it need to be implemented for the functions to be invoked? If so, the onClick attributes in the Button layouts would seem redundant.
Any help will be appreciated.
Thanks
The right approach is to use a fragment listener to communicate back with the activity:
public static class MainActivity extends Activity
implements MainFragment.onFragmentInteraction{
...
public void onFragmentInteraction() {
// Do something
callFunction();
}
}
Then in your fragment:
mYourButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (mListener != null) {
mListener.onFragmentInteraction();
}
}
});
FWIW I never use the xml onClick attributes. Although they may save a couple of lines of typing, they make it more difficult to follow what's happening in your code.
If your class implements View.OnClickListener and you have correctly overriden the onClick method (which it looks like you have), then you can safely remove any onClicks in your layout files and instead assign methods to your widget clicks in the following way:
public class MainFragment extends Fragment implements View.OnClickListener {
private Button viewOne, viewTwo, viewThree;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout, container, false);
viewOne = (Button) rootView.findViewById(R.id.view_one);
viewTwo = //etc...
//"this" refers to the current object. As the object is of a class that implements OnClickListener,
//passing "this" satisfies the View.OnClickListener parameter required for the setOnClickListener() method.
viewOne.setOnClickListener(this);
viewTwo.setOnClickListener(this);
viewThree.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View view) {
//To identify the correct widget, use the getId() method on the view argument
int id = view.getId();
switch (id) {
case R.id.view_one:
//viewOne clicked
break;
case R.id.view_two:
//And so on...
}
}
}
If you set the onClick in your XML, the click events will go to your container Activity. But you can have the click events go directly to your Fragment by setting the onClickListener to your Fragment's implementation of it. So in your Fragment's onCreateView() method, you would inflate your layout, then set the Button's onClickListener to your Fragment's implementation like this...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_fragment, container, false);
Button button = (Button) view.findViewById(R.id.your_button);
button.setOnClickListener(this);
return view;
}
By setting the setOnClickListener() to this, you are sending all click events for that button to your Fragment instead of your Activity. Then you would just handle your onClick events as you're already doing...
#Override
public void onClick(View view) {
Log.d("YOUR BUTTON", "This is called from your Fragment instead of your Activity");
}

Referring to Views from different Fragments in same Activity

Let say the target application is built from 3 fragments which are all in the same activity public class MainActivity extends android.support.v4.app.FragmentActivity implements ActionBar.TabListener. Starting fragment is public class ButtonSectionFragment extends Fragment where there is a Button:
public class ButtonSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.btn, container, false);
Button mybutton = (Button) rootView.findViewById(R.id.mybutton);
mybutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
????????????????????
}
});
}
There are ?? in the onClick method, I will get to that. And there is another fragment like this:
public static class TextSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tv, container, false);
TextView textv = (TextView) rootView.findViewById(R.id.texty);
}
Both of the fragments are using different layouts so this is why rootView is being used right in front of findViewById.
The outcome I would like to achieve is: by Button from 1st fragment click set the TextView from 2nd fragment to Hello. What should I put in the ??? part to make it all work?
You need to use interface as callback to the activity then set the textview in fragment.
Two framgents should never communicate directly.
http://developer.android.com/training/basics/fragments/communicating.html.
Framgent1 -->Activity -->Fragment2.
You can comunicate value from fragment2 to activity first then from activity to fragment2. Then set text in fragment2
You just have to use getActivity().findViewById() instead of getView().findViewById()
final TextView tv = (TextView) getActivity().findViewById(R.id.texty);
if (tv != null)
tv.setText("Hello");
Fragments are just branches inside the common layout tree of activity. All fragment views of a common activity can be accessed through Activity.findViewByXXX(). The only complication is that fragments can be dynamically added, removed, replaced, etc. So you to be sure that the needed fragment is already inflated into the layout hierarchy. You can make initialization of the UI in onViewCreated() of the other fragment. That guarantees you the layout has been loaded already.
Fragment frag1 = new ButtonSectionFragment ();
Fragment frag2 = new TextSectionFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(layout, frag1);
ft.add(layout, frag2);
ft.commit();
View frag1RootView = frag1.getView();
View frag2RootView = frag2.getView();
Button btn = (Button)frag1RootView.findViewById(id);
TextView tv = (TextView)frag2RootView.findViewById(id);
untested but... I think that would do it...
EDIT: You should get the root views onActivityCreated(); or it'll throw you a null...
In continuation to Raghunandan's answer, you could check similar implementation in the link.
update TextView in fragment A when clicking button in fragment B
Do not forget to get a reference of the textview of the TextSectionFragment into the MainActivity.

Categories

Resources