Android Fragment Implementation - android

I am trying to implement Fragments in my Project using the https://github.com/JakeWharton/Android-ViewPagerIndicator plugin.
My Fragment
public final class NearByFragment extends Fragment {
private static String TAG = "bMobile";
public static NearByFragment newInstance(String content) {
NearByFragment fragment = new NearByFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
return inflater.inflate(R.layout.fragment_search_nearby, null);
}
}
Now I want to execute some code like start start a new thread and download a JSON from the server and then assign a list view from the content I download. In fragments we are assigning views in onCreateView. so where should I write the
listview = (ListView) findViewById(R.id.list_items);
((TextView) findViewById(R.id.title_text))
.setText(R.string.description_blocked);
and other code to generate the Fragment view ?

You can search within the view that you just inflated:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View v = inflater.inflate(R.layout.fragment_search_nearby, null);
listview = (ListView)v.findViewById(R.id.list_items);
((TextView)v.findViewById(R.id.title_text))
.setText(R.string.description_blocked);
return v;
}
You can also use the Fragment.getView() function elsewhere in your code and call that view's findViewById() member.

You can use getActivity().findByView() from the Fragment if you want to have access to the layout elements. Alternatively, you can just put the findByView() call in the main Activity.

Related

adding dynamic content on fragments android

I'm new to fragments and they are a bit confusing to me right now.
I have read alot and actually built a test app using this tutorial
I was able to add more tabs and so on. But I don't want to display static
content (xmls). I want to be able to modify the UI add listviews, load json data with asynctasck and so on but the very first attempt I made has failed.
So on Tab1:
public class Tab1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
}
I tried to declare a textview and edit it's text with settext but
I get a crash and also findviewbyid is not available as a method.
It didn't throw and error when I typed getView().findViewById but
that's not the problem.
Are fragments limited or very different from traditional activities?
Do I need to make never ending customizations
in order to get a listview loading?
Thank you.
You should declare your TextView as a Member variable for your class and get a reference to that view in onCreateView like:
public class Tab1 extends Fragment {
// your TextView member variable
private TextView mTextView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1, container, false);
mTextView = (TextView) v.findViewById(R.id.my_text_view);
return v;
}
// It is safe to access the views here, not in onCreate since it is called before onCreateView
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
mTextView.setText("Hello, World!");
}
}
For reference on the Fragment lifecycle
Are fragments limited or very different from traditional activities?
A Fragment has its own lifecycle like that of an Activity but it is dependent upon the lifecycle of its parent Activity, so to answer your question they are not very different, it is just a good practice for modularizing code.
Do I need to make never ending customizations in order to get a listview loading?
A little unclear what you mean by never ending customizations but loading a dynamic ListView is very simple in Android.
For Example:
using fragment_one.xml we have just a FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fl_list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
And the code:
public class Tab1 extends Fragment {
// your FrameLayout member variable
private FrameLayout mFlParent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one, container, false);
mFlParent = (FrameLayout) v.findViewById(R.id.fl_list_container);
return v;
}
// It is safe to access the views here, not in onCreate since it is called before onCreateView
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Create a new list, adapter and add a item click listener
ListView myList = new ListView(context); // context needed
myList.setAdapter(new ArrayAdapter<String>(context, android.R.id.simple_list_item_1, new String []{"Item 1", "Item 2", "Item 3", "Item 4"}));
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//... handle clicks on list items as usual
}
});
// add the view to the FrameLayout
mFlParent.addView(myList); // may want to call mFlParent.removeAllViews(); before adding just to be safe
}
}
Good luck and happy coding.
Fragment doesn't have an activity methods.
If you want to use findViewById methods, you should use a class field.
public class Tab1 extends Fragment {
private View mView;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.tab_1,container,false);
return mView;
}
#Override
public void onCreate() {
// here you can use `findViewById` method via `mView` variable
mView.findViewById(YOUR_VIEW_ID);
}
}
There is basically 2 method to be use in fragment
1. onCreateView
2. onViewCreated
First one is use to inflate layout on your fragment
Second one is use to find all view used in your layout.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1, container, false);
return v;
}
#Override
public void onViewCreated(View v){
mTextView = (TextView) v.findViewById(R.id.my_text_view);
mTextView.setText("Hello, World!");
}

Using findViewById inside a Fragment

I am creating a new Tab interface and for every tab I have functionality like:
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) findViewById(R.id.classList);
return rootView;
}
}
But I am getting cannot resolve method findViewById also at another place I am also unable to use runOnUiThread and getting Error:(88, 29) error: cannot find symbol method runOnUiThread(<anonymous Runnable>)
I understand these will work fine if my class was extended from Activity but it’s a tab fragment so how can I use this funcitons?
you need
classListView = (ListView) rootView.findViewById(R.id.classList);
as that is the view you are concerned with
to get runOnUiThred you need to do getActivity().runOnUiThread
You need to reference findViewById using the view,
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) rootView .findViewById(R.id.classList);
return rootView;
}
}
For runOnUiThread is a possible duplicate of Modifying an Android view from a different thread
use its like,
activity.runOnUiThread(new Runnable());
Here is a shore explanation of findViewById method;
findViewById() method will work with the related object that your main layout is bound to. For example, In an activity, when you make a
setContentView(activity_main);
You imply that your Activity will retrieve its layouts from activity_main. So when you make a findViewById() in an activity, that actually means this.findViewById(), where this is your Activity.
So in your case, the layout class_view is bound to the rootView. But when you just write findViewById, it means that this.findViewById. And this is the scope you're in, which is the Fragment in your case. However, I don't think a Fragment has that capability. So you should refer to the rootView to retrieve your views.
rootView.findViewById()
Fragments don't have a findViewById() method like Activity, so you have to call the method of the root view of the fragment. Try doing rootView.findViewById(R.id.classList) instead.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_content_mediaplayer, container, false);
mSeekbar = (SeekBar) v.findViewById(R.id.seekBarMusic);
return v;
Use rootView.findViewById(R.id.classList) instead of findViewById(R.id.classList).
Try this:
public class ClassViewFragment extends Fragment {
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.class_view, container, false);
classListView = (ListView) rootView.findViewById(R.id.classList);
return rootView;
}
}
findViewById must run inside onViewCreated() method
ListView classListView = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.class_view, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
classListView = (ListView) view.findViewById(R.id.classList);
}
}`

Maintain fragment's view state

I have seen Link1 for this issue but could understand it right. I have a fragment that loads a list. When i click the list item it opens another activity. But i press back button it loads the list again. I want it to be at the same scroll position where it was before. In above mentioned link it specifies to use flag but i haven't got the point.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
android.app.Fragment fragment = new MeFragment();
getFragmentManager().beginTransaction().replace(R.id.layout_FragmentsContainer, fragment).addToBackStack(null).commit();
}
}
public class MeFragment extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_me, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
meLV = (ListView) getView().findViewById(R.id.lv_Inbox);
loadingListProgress = (ProgressBar) getView().findViewById(R.id.progress_LoadingList);
meList = new ArrayList<Message>();
meAdapter = new MessagesListAdapter(getActivity(), meList);
//addFooter();
meLV.setAdapter(meAdapter);
meLV.setOnItemClickListener(this);
pageCount = 0;
loadmoreProgressDialog = new ProgressDialog(getActivity());
loadmoreProgressDialog.setTitle("Please wait ...");
loadmoreProgressDialog.setMessage("Loading more ...");
loadmoreProgressDialog.setCancelable(true);
loadUserMessages();
meLV.setOnScrollListener(new EndlessScrollListener() {
#Override
public void onLoadMore(int page, int totalItemsCount) {
// TODO Auto-generated method stub
//addFooter();
loadmoreProgressDialog.show();
loadUserMessages();
}
});
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
Utils.showToast_msg(getActivity(), "MessageItemClicked");
ReferralDetailFragment fragment = new ReferralDetailFragment();
getFragmentManager().beginTransaction().replace(R.id.layout_FragmentsContainer, fragment).addToBackStack(null).commit();
}
}
public class ReferralDetailFragment extends Fragment implements OnClickListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_referraldetail,container, false);
linkToAcknowledge = (TextView) view.findViewById(R.id.lbl_Link_to_Acknowledge);
return view;
}
}
I implemented a simple solution for this in my app, basically when you press back to go to the fragment again, onCreateView() is called. Here in onCreateView() you have done all initialization, so we change
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_me, container, false);
/*
*Whatever you want to do
*
*/
return view;
}
to:
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if(view==null){
view = inflater.inflate(R.layout.fragment_me, container, false);
/*
*Whatever you want to do
*
*/
}
else{
((ViewGroup)view.getParent()).removeView(view);
}
return view;
}
Here, we move View view outside and make it a class variable. So if it is the first time the fragment is called, it is null and the initialization occurs, otherwise it goes to else black. Else block is required because onCreateView() adds whatever it returns as a child of the view's parent, so since view is already there, we remove it and onCreateView automatically adds it again.
According to our exchange in the comments, I completely deletde my answer and re-write a new one.
I copy/paste the code from one of my apps and removing the useless things and changing the names. Hope there is not too many typing mistakes, at that it is the minimum required to have it working.
When I pop back to FirstFragment from SecondFragment, the scroll position of FirstFragment is the same as when I clicked an item to load the SecondFragment.
Note that I don't extend FragmentActivity. I have an activity which loads the fragments.
Extend/modify to match your needs.
MainActivity :
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
}
}
FirstFragment Class :
public class FirstFragment extends Fragment implements OnItemClickListener {
private ListView mListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.first_fragment_layout, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListView = (ListView) getView().findViewById(R.id.listview_first_fragment);
mListView.setAdapter(mAdapter); // depends on your adapter
mListView.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListView.setItemChecked(position, true);
//in case you need, set the bundle here, for example pass the position
Bundle arguments = new Bundle();
arguments.putInt("position", position);
SecondFragment secondFragment = new SecondFragment();
secondFragment.setArguments(arguments);
getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack(null).commit();
}
}
SecondFragment Class :
public class SecondFragment extends Fragment {
private Integer mPosition;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.second_fragment_layout, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle arguments = getArguments();
if (arguments == null) {
mPosition= 0;
} else {
mPosition= arguments.getInt("Position");
}
}
}
What you are trying to achieve may be done with help of savedInstanceState. i also had this kind of problem which i resolved by using add() method instead of replace() in transition.
If you can change your method or already not using add() than give it a shot.
and if add() method didn't do the trick then check the implementation of savedInstanceState.
correctly save instance state.
How to save states of fragment views.

extends Activity with Fragment in Android

I am using Fragment for Sliding Menu. Now, I want to extend Activity to get reference of layout.xml and many more. But we can't bind Fragment and Activity together. So what is the way to solve this ?
Fragment Code :
public class FindPeopleFragment extends Fragment {
public FindPeopleFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.becomeexpert, container,
false);
return rootView;
}
}
If I am using extends Fragment then I can't use findViewbyId and many more things. So I am confused as I am using Fragment first time. Please help me regarding this.
Since you have the view inflated you can call rootView.findViewById(...)
I think this is what you are after:
public class FindPeopleFragment extends Fragment {
private View rootView;
private View myTextView;
public FindPeopleFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.becomeexpert, container,
false);
myTextView = rootView.findViewById(R.id.my_textview);
return rootView;
}
private void someFunction()
{
View myButton = rootView.findViewById(R.id.my_button);
}
}
You can save a reference to the views that you need before onCreateView returns, or you can save a reference to the rootView and call findViewById on that later on if you need to.

Android - Add code to a fragment

I am a beginner in coding for Android and i am trying to do an application with two fragments. Unfortunately, when i add code to set action to my layout, it makes my application crash, so i'm wondering where i should put my code on the fragment file. If i take out the function onCreate, the application doesn't crash and my layout is good.
Here is my code. Thank you so much for your answer.
public class FragmentOne extends Fragment{
public static final String TAG = "FragmentOne";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = View.inflate(getActivity(), R.layout.fragmentone, null);
return v;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final EditText etData = (EditText) getView().findViewById(R.id.etData);
}
}
First of all I can see a few mistakes in your code.First of all as #user1873880 mentioned, onCreate() is always called before onCreateView(), so you should consider dealing with your views in onCreateView(). Second mistake which I can see is that you are not creating your View as it's designed to be used on Fragment. In my opinion the way your Fragment should look is like this :
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentOne";
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// create your view using LayoutInflater
return inflater.inflate(R.layout.fragmentone, container, false);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// do your variables initialisations here except Views!!!
}
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
// initialise your views
EditText etData = (EditText) view.findViewById(R.id.etData);
}
}
Hope this helps you! : )
The reason is that onCreate is invoked before onCreateView, so you can manipulate with your views only after onCreateView callback. For more information check Fragment lifecycle here.

Categories

Resources