I have followed a tutorial to create step by step a sliding menu and it works, but looking in the code I have noticed that when users touch a menu item the code will run this piece of code:
MainActivity:
....
/**
* Slide menu item click listener
* */
private class SlideMenuClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// display view for selected nav drawer item
displayView(position);
}
}
/**
* Diplaying fragment view for selected nav drawer list item
* */
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:{
fragment = new PersonaggiPrincipali();
break;
}
case 1:{
fragment = new PersonaggiSecondari();
break;
}
case 2:{
fragment = new Video();
break;
}
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
....
Basically it call a new Class when the item is clicked.
The class is formed in this way:
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PersonaggiPrincipali extends Fragment {
public PersonaggiPrincipali(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.personaggi_principali, container, false);
return rootView;
}
}
So it just return the layout and the displayView function above will replace the current with the returned one, right?
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
....
}
My question is, in the view returned how can I manipulate it if the class is just a return of the layout?
For example, let's assume that in the returned view I have a Button and I need to set a ClickListener or just create a function that will chenge the Activity (activity that should be insert in the main view with the SlidingMenu), How can I do that?
Should I write all the code in the MainActivity to manage that?
Ciao Christian, when you instantiate a Fragment you don't get a view as a result but a Fragment.
The onCreateView method is just part of the lifecycle of a fragment and that's where you have to return the main view of your fragment. Also, if your fragment has a Button you can set the listener in the onCreateView method of the Fragment.
http://developer.android.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
Example:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.personaggi_principali, container, false);
Button button = (Button) rootView.findViewById(R.id.REPLACE_WITH_YOUR_BUTTON_ID);
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// do you stuff here...
}
});
return rootView;
}
Please notice the Button in the example is just a local variable, if you need to access it later, it's better to declare it as a class variable.
Regarding communication (Fragment to Fragment, host Activity to Fragment), I think everything you need to know is well explained in the official documentation: http://developer.android.com/training/basics/fragments/communicating.html
You can either do it in the same (onCreateView()) method. Additionally, you could include private references to Views inside your fragment layout in your PersonaggiPrincipali class. Also implement get() methods for these Views and you can change them from your MainActivity.
For example:
public class PersonaggiPrincipali extends Fragment {
private Button fragButton;
public PersonaggiPrincipali(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.personaggi_principali, container, false);
fragButton = (Button) rootView.findViewById(R.id.fragButtonId); //replace R.id.fragButtonId with the appropriate Id from your xml layout
return rootView;
}
public Button getFragButton() {
return this.fragButton;
}
}
Related
I am facing a problem in regarding fragment.
In my scenario,
There are two fragment associated with FragmentActivity.
In FragmentActivity, there are a container layout (Frame Layout) in which all fragment will replace.
public void replaceFragment(Fragment fragmentClass) {
String selectedFragment = fragmentClass.getClass().getName();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction
.replace(R.id.content_frame, fragmentClass);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
First time , I set a List type fragment (Fragment A) in which get the data from web service and papulate over listview. I execute the AsyncTask from onCreateView() method.
In MainActivity: onCreate
SherlockFragment fragment = new FragmentA();
replaceFragment(fragment);
On list item click of Fragment A, Fragment A will callback the activity method to replace it to details type fragment Fragment B.
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
callback = (ICallBack) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/*View rootView = inflater.inflate(R.layout.fragment_locate, container,
false);*/
View rootView = inflater.inflate(R.layout.fragment_a, container,
false);
ListView list = (ListView) rootView
.findViewById(R.id.listView);
adapter = new MyListAdapter();
list.setAdapter(adapter);
list
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View convertView, int position, long id) {
SherlockFragment fragment = new SalonDetailFragment();
callback.replaceFragment(fragment);
}
});
ListDataTask task = new ListDataTask();
task.execute();
return rootView;
}
class ListDataTask extends AsynTask<Void,Void,List<Data>>{
public Void doInBackground(Void parems){
List<Data> = getDataFromServer();
}
onPostExecute(List<Data> data){
adapter.addAllData(data);
adapter.notifyDataSetChanged();
}
}
When I press back button, from Fragment B then Application will show Fragment A but it execute Asynctask again and get the data to papulate the listview.
So I need to know, How to maintain the pervious state of Fragment like Activity.
Is there are any way to not to create Fragment after come back from Other activity
Have a look my pseudo code.
I got solution. Simple.... do the check null value of rootview
public class FragmentA extends Fragment {
View _rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (_rootView == null) {
// Inflate the layout for this fragment
_rootView = inflater.inflate(R.layout.fragment_a, container, false);
// Find and setup subviews
_listView = (ListView)_rootView.findViewById(R.id.listView);
...
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove _rootView from the existing parent view group
// (it will be added back).
((ViewGroup)_rootView.getParent()).removeView(_rootView);
}
return _rootView
I have the same problem and solved by replacing
fragmentTransaction
.replace(R.id.content_frame, fragmentClass);
to
fragmentTransaction
.add(R.id.content_frame, fragmentClass);
Replace will always create new instance on back press while Add is just add a new fragment in Stack. for more information check this link
I have a supported fragment activity which will load diff fragments. The fragment has some textView with id = "score" and I want to get its handle but findViewById for score's textView returns null. Why so?
textView is placed in fragment
public class MyActivity extends extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks{
private TextView scoreBoardTextView = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) findViewById(R.id.score); //this returns null
}
#Override
public void onNavigationDrawerItemSelected(int position) {
//set fragment
}
}
Note:
Directly accessing fragment's views outside fragment is not a good idea. You should use fragment callback interfaces to handle such cases and avoid bugs. The following way works but it is not recommended as it is not a good practice.
If you want to access the TextView of Fragment inside its parent Activity then you should define a method inside your Fragment class like this:
public class MyFragment extends Fragment {
TextView mTextView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_main, container, false);
mTextView = (TextView) view.findViewById(R.id.textView1);
return view;
}
public void setTextViewText(String value){
mTextView.setText(value);
}
}
Now you can use this inside your Activity like this:
myFragment.setTextViewText("foo");
here myFragment is of type MyFragment.
If you want to access the whole TextView then you can define a method like this inside MyFragment.java:
public TextView getTextView1(){
return mTextView;
}
By this you can access the TextView itself.
Hope this Helps. :)
It is possible with following way:
Keep reference of inflated view in the Fragment like this :
public class MyFragment extends SherlockFragment{
MainMenuActivity activity;
public View view;
public MyFragment(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if ( getActivity() instanceof MainMenuActivity){
activity = (MainMenuActivity) getActivity();
}
view = inflater.inflate(R.layout.aboutus, container, false);
return view;
}
}
Create a function in the Activity, like this:
public class MainMenuActivity extends SherlockFragmentActivity {
SherlockFragment fragment = null;
public void switchContent(SherlockFragment fragment) {
this.fragment = fragment;
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.mainmenu, fragment)
.commit();
invalidateOptionsMenu();
}
Its purpose is to keep reference of current fragment. Whenever you wanna switch fragment, you call above function, like this (from fragment):
activity.switchContent( new MyFragment_2());
Now you've current fragment reference. So you can directly access Fragment's views in Activity like this: this.fragment.view
You have no need of reference of Fragment view to get its components in Activity. As you can directly access layout components of a Fragment in parent Activity.
Simply you can access any component by this
findViewById(R.id.child_of_fragment_layout);
In order to access the TextView or Button or whatever in your fragment you need to do the following:
public class BlankFragment extends Fragment {
public View view;
public TextView textView;
public Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view =inflater.inflate(R.layout.fragment_blank, container, false);
textView = (TextView)view.getRootView().findViewById(R.id.textView_fragment1);
return view;
}
public void changeTextOfFragment(String text){
textView.setText(text);
view.setBackgroundResource(R.color.colorPrimaryDark);
}
Once that is done in your MainActivity or any other where you want to access your TextView from your Fragment you should make sure to set up the fragment in your OnCreate() method other ways it will most likely throw nullPointer. So your activity where you want to change the TextView should look smth like this:
public class MainActivity extends AppCompatActivity {
private Button button1;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
BlankFragment blankFragment = new BlankFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button)findViewById(R.id.button1);
changeFragment();
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment1,blankFragment);
fragmentTransaction.commit();
}
private void changeFragment(){
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
blankFragment.changeTextOfFragment("Enter here the text which you want to be displayed on your Updated Fragment");
}
});
}
Hope this helps :)
You can access with getView method of Fragment class.
For example You have a TextView in Your MyFragment with id of "text_view" In Your Activity make a Fragment of Yours:
MyFragment myFragment = new MyFragment();
And when You need a child just call getView and then find Your childView.
View view = myFragment.getView();
if (view !=null) {
view.findViewById(R.id.text_view).setText("Child Accessed :D");
}
Note: if you want the root view of your fragment, then myFragment.getView(); is simply enough.
Just put in fragment instead of putting in activity:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new_work_order,
container, false);
TextView scoreBoardTextView = (TextView) rootView.findViewById(R.id.score);
return rootView;
}
Only doing this:
((Your_Activity) this.getActivity()).YouyActivityElements;
If your TextView placed inside Fragment that case you cannot access TextView inside your Fragment Parent Activity you can set the interface for intercommunication between Fragment and Activity and send Data when you click on TextView or anyother thing which you want to happend
You can't access Fragment element in Parent Activity, But You can pass values to your Fragment by following way.
in your onNavigationDrawerItemSelected method of MyActivity do the following
int myScore = 100;
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.container,
MyFragment.newInstance(myScore)).commit();
}
And in MyFragment class create a method called newInstance like following
private static final String SCORE = "score";
public static MyFragment newInstance(int score) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putInt(SCORE, score);
fragment.setArguments(args);
return fragment;
}
And in MyFragment's onCreateView() method
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView textView = (TextView) rootView
.findViewById(R.id.score);
textView.setText(Integer.toString(getArguments().getInt(
SCORE)));
return rootView;
}
That's All, I hope this will help you. If not please let me know.
The score textView is in the layout of fragment, it's not in the layout of the MyActivity, i.e. R.layout.activity_home. So you could find the score textview in that fragment once you inflate the corresponding layout file.
It returns null cause the TextView is an element of the Fragment, not the Activity.
Please note that the idea of using Fragment is to encapsulate a module inside the Fragment, which means the Activity should not have direct access to it's properties. Consider moving your logic where you get the TextView reference inside the Fragment
Simply declare TextView as public in fragment, initialize it by findViewById() in fragment's onCreateView(). Now by using the Fragment Object which you added in activity you can access TextView.
You need to call method findViewById from your fragment view.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) mNavigationDrawerFragment.getView().findViewById(R.id.score);
}
This way works for me.
I suggest you to make the textview part of your activity layout. Alternately you can have the textview as a separete fragment. Have a look at my question here. Its similar to yours but in reverse direction. Here's a stripped down version of code I used in my project. The explanation are along the code.
The Activity Class
public class MainActivity extends ActionBarActivity {
PlaceFragment fragment;
TextView fragmentsTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Bundle bundle = new Bundle();
bundle.putString("score", "1000");
fragment = PlaceFragment.newInstance(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, fragment);
ft.addToBackStack(null);
ft.commit();
// method 1
// fragment is added some ways to access views
// get the reference of fragment's textview
if (fragment.getTextView() != null) {
fragmentsTextView = fragment.getTextView();
}
// method 2
// using static method dont use in production code
// PlaceFragment.textViewInFragment.setText("2000");
// method 3
// let the fragment handle update its own text this is the recommended
// way wait until fragment transaction is complete before calling
//fragment.updateText("2000");
}
}
The fragment class:
public class PlaceFragment extends Fragment {
public TextView textViewInFragment;// to access via object.field same to
// string.length
// public static TextView textViewInFragment;//to access via
// PlaceFragment.textView dont try this in production code
public PlaceFragment() {
}
public static PlaceFragment newInstance(Bundle bundle) {
PlaceFragment fragment = new PlaceFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_place, container, false);
textViewInFragment = (TextView) view
.findViewById(R.id.textViewInFragment);
return view;
}
#Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
if (getArguments() != null) {
textViewInFragment.setText(getArguments().getString("score"));
}
}
public TextView getTextView() {
if (textViewInFragment != null) {
return textViewInFragment;// returns instance of inflated textview
}
return null;// return null and check null
}
public void updateText(String text) {
textViewInFragment.setText(text);// this is recommended way to alter
// view property of fragment in
// activity
}
}
Communication from activity to fragment is straight forward. This is because activity contains fragment. Keep the fragment object and access its property via setters and getters or the public fields inside it. But communication from fragment to activity requires an interface.
why you don't access it directly from your FragmentPagerAdapter,
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
and here is the full example:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Locale;
public class TabsActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabs);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
ActionBar.Tab tab = actionBar.newTab();
View tabView = this.getLayoutInflater().inflate(R.layout.activity_tab, null);
ImageView icon = (ImageView) tabView.findViewById(R.id.tab_icon);
icon.setImageDrawable(getResources().getDrawable(mSectionsPagerAdapter.getPageIcon(i)));
TextView title = (TextView) tabView.findViewById(R.id.tab_title);
title.setText(mSectionsPagerAdapter.getPageTitle(i));
tab.setCustomView(tabView);
tab.setTabListener(this);
actionBar.addTab(tab);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_tabs, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_logout) {
finish();
gotoLogin();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public ProfileFragment profileFragment;
public SubAccountFragment subAccountFragment;
public ChatFragment chatFragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
profileFragment = new ProfileFragment();
subAccountFragment = new SubAccountFragment();
chatFragment = new ChatFragment();
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return profileFragment;
case 1:
return subAccountFragment;
case 2:
return chatFragment;
}
return null;
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
public int getPageIcon(int position) {
switch (position) {
case 0:
return R.drawable.tab_icon_0;
case 1:
return R.drawable.tab_icon_1;
case 2:
return R.drawable.tab_icon_2;
}
return 0;
}
}
public void gotoLogin() {
Intent intent = new Intent(this, LoginActivity.class);
this.startActivity(intent);
}
public void requestConnectPressed(View view){
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
}
}
If the view is already inflated (e.g. visible) on the screen then you can just use findViewById(R.id.yourTextView) within the activity as normal and it will return the handle to the text view or null if the view was not found.
I just use methods to access fragment views from parent activity, because we create a new fragment class object to insert the fragment. So I do like this.
class BrowserFragment : Fragment(), Serializable {
private lateinit var webView: NestedScrollWebView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
webView = view.findViewById(R.id.web_view)
}
fun getWebView(): WebView {
return webView
}
}
In MainActivity
val browserFragment = BrowserFragment()
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.add(R.id.browser_fragment_placeholder, browserFragment)
fragmentTransaction.commit()
val webView = browserFragment.getWebView()
I am using http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/ to make Tab bar.I have also 3 tab first and the second Tab view contains a List view and third on e is Settings. Settings Contain Reload button. When I clicked the Reload Button I want to move to First Tab.How can I do this ?
Make following changes:
Pass the viewPager reference to your adapter and from adapter to your fragment:
public class TabsPagerAdapter extends FragmentPagerAdapter {
ViewPager viewPager;
public TabsPagerAdapter(FragmentManager fm,ViewPager viewPager) {
super(fm);
this.viewPager=viewPager;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new TopRatedFragment(viewPager);
case 1:
// Games fragment activity
return new GamesFragment(viewPager);
case 2:
// Movies fragment activity
return new MoviesFragment(viewPager);
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
In fragment on click of button call set selection on view pager object:
public class MoviesFragment extends Fragment {
private ViewPager viewPager;
public MoviesFragment (ViewPager viewPager;){
this.viewPager=viewPager;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_movies, container, false);
rootView.findViewById(<your button>).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
viewPager.setCurrentItem(0);
}
});
return rootView;
}
}
I know its quite late ....maybe it can help someone else...creating a constructor in fragments is not supported..so instead of passing viewpager as constructor..
we can write in the fragment on button click:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by medha singh on 6/17/2016.
*/
public class Fragment4 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
final View view1 = inflater.inflate(R.layout.new_lead2, container, false);
TextView tv=(TextView)view1.findViewById(R.id.hardware);
final ViewPager pager= (ViewPager)getActivity().findViewById(R.id.pager2);
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pager.setCurrentItem(1);
}
});
return view1;
}
}
So getactivity() is the solution: i got it from here: How to go other Tabs by clicking on a Button from the current Tab in Android?
Do this:
btn.setOnClickListener(new OnClickListener()
{
onClick(View v)
{
//Reload the data
tabHost.setCurrentTab(/*destination-tab-id*/);
}
}
)
this is the first application I am creating using a NavigationDrawer. I have a pretty simple question. How do I make the first page in the NavigationDrawer the main one? Also I'm not too familiar with formatting since this is my first time using the drawer so I would appreciate it if someone more familiar could tell me if I am doing it correctly. Right now each page just displays text but eventually it will do more. And one of my questions is how do I make it so that clicking a page in the drawer can open up a new page using a RelativeLayout for example. From my understanding Adapters are only for Views, would I create a completely new activity and call startActivity() in my iteration for the drawerclick? If so, is that efficient? Meaning will it take a long time for the page to load? My main activity is:
public class MainActivity extends Activity {
private String[] mPages;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawer_layout);
mPages = getResources().getStringArray(R.array.page_titles);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPages));
mTitle = mDrawerTitle = getTitle();
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open,
R.string.drawer_close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
/** Swaps fragments in the main content view */
private void selectItem(int position) {
// Create a new fragment and specify the planet to show based on position
Fragment fragment;
if(position == 0){
fragment = new OneFragment();
// Insert the fragment by replacing any existing fragment
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
}
else if(position == 1){
fragment = new TwoFragment();
// Insert the fragment by replacing any existing fragment
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
}
else if(position == 2){
fragment = new ThreeFragment();
// Insert the fragment by replacing any existing fragment
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
}
else if(position == 3){
fragment = new FourFragment();
// Insert the fragment by replacing any existing fragment
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
}
// Highlight the selected item, update the title, and close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPages[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
public static class OneFragment extends Fragment{
public OneFragment(){
}
View rootView;
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup contatiner,
Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.drawer_layout,
contatiner, false);
text = (TextView)rootView.findViewById(R.id.text_view1);
text.setText("One");
return rootView;
}
}
public static class TwoFragment extends Fragment{
public TwoFragment(){
}
View rootView;
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup contatiner,
Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.drawer_layout,
contatiner, false);
text = (TextView)rootView.findViewById(R.id.text_view1);
text.setText("Two");
return rootView;
}
}
public static class ThreeFragment extends Fragment{
public ThreeFragment(){
}
View rootView;
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup contatiner,
Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.drawer_layout,
contatiner, false);
text = (TextView)rootView.findViewById(R.id.text_view1);
text.setText("Three");
return rootView;
}
}
public static class FourFragment extends Fragment{
public FourFragment(){
}
View rootView;
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup contatiner,
Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.drawer_layout,
contatiner, false);
text = (TextView)rootView.findViewById(R.id.text_view1);
text.setText("Four");
return rootView;
}
}
}
I apologize for the lengthy question, but the developer site wasn't helping out too much and I want to make sure I do this correctly the first time so I don't have to go back too much
Whatever you want to show needs to be within the child of the DrawerLayout. In your case, I think you would do a fragment transaction in onCreate() to put whatever fragment you want visible first inside of the content area.
if (savedInstanceState == null) {
fragment = new OneFragment();
// Insert the fragment by replacing any existing fragment
getFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment).commit();
}
You can hold references to these fragments so you don't create a new instance of them each time the user makes a selection. You probably also want to make sure the new selection isn't the same as the current one, or else you will have extra transactions you don't need.
For opening a "new page", you want to use startActivity() and show another activity with it's own layout. Generally speaking, don't be concerned about how long it takes an Activity to load unless you are specifically doing some meaningful work (like loading a bunch of data out of a database).
Lastly, Adapters are specifically for AdapterViews (like ListView) and are an entirely different matter. They are used in conjunction with specific UI components to generate child views for representing potentially large data sets and which can be recycled for efficiency reasons. I suggest you watch The World of ListView if you want more information/clarity about that.
The Android 4.1 ActionBar provides a useful navigation mode as a list or tab. I am using a SpinnerAdapter to select from three fragments to be displayed in view android.R.id.content.
The onNavigationItemSelected() listener then inflates each fragment to the view and adds it to the back stack using FragmentTransaction.addToBackStack(null).
This all works as advertised, but I don't know how to update the ActionBar to reflect the current back stack. Using the ActionBar.setSelectedNavigationItem(position) works but also triggers a new OnNavigationListener() which also creates another FragmentTransaction (not the effect I want). The code is shown below for clarification. Any help with a solution is appreciated.
public class CalcActivity extends Activity {
private String[] mTag = {"calc", "timer", "usage"};
private ActionBar actionBar;
/** An array of strings to populate dropdown list */
String[] actions = new String[] {
"Calculator",
"Timer",
"Usage"
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
// may not have room for Title in actionbar
actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
actionBar.setListNavigationCallbacks(
// Specify a SpinnerAdapter to populate the dropdown list.
new ArrayAdapter<String>(
actionBar.getThemedContext(),
android.R.layout.simple_list_item_1,
android.R.id.text1,
actions),
// Provide a listener to be called when an item is selected.
new NavigationListener()
);
}
public class NavigationListener implements ActionBar.OnNavigationListener {
private Fragment mFragment;
private int firstTime = 0;
public boolean onNavigationItemSelected(int itemPos, long itemId) {
mFragment = getFragmentManager().findFragmentByTag(mTag[itemPos]);
if (mFragment == null) {
switch (itemPos) {
case 0:
mFragment = new CalcFragment();
break;
case 1:
mFragment = new TimerFragment();
break;
case 2:
mFragment = new UsageFragment();
break;
default:
return false;
}
mFragment.setRetainInstance(true);
}
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (firstTime == 0) {
firstTime++;
ft.add(android.R.id.content, mFragment, mTag[itemPos]);
} else {
ft.replace(android.R.id.content, mFragment, mTag[itemPos]);
ft.addToBackStack(null);
}
ft.commit();
Toast.makeText(getBaseContext(), "You selected : " +
actions[itemPos], Toast.LENGTH_SHORT).show();
return true;
}
}
public static class CalcFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_calc, container, false);
return v;
}
}
public static class TimerFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_timer, container, false);
return v;
}
}
public static class UsageFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_usage, container, false);
return v;
}
}
You could do something like this:
Create a boolean to track when you are selecting a navigation item based on the back button:
private boolean mListIsNavigatingBack = false;
Override onBackPressed, in the override, check if the backstack has items, if so handle yourself, if not call the superclass:
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() > 0){
mListIsNavigatingBack = true;
//You need to get the previous index in the backstack through some means
//possibly by storing it in a stack
int previousNavigationItem = ???;
getActionBar().setSelectedNavigationItem(previousNavigationItem);
}
else{
super.onBackPressed();
}
}
Inside NavigationListener, handle the mListIsNavigatingBack state, manually pop the back stack and unset the state:
if(mListIsNavigatingBack){
if(fm.getBackStackEntryCount() > 0){
fm.popBackStack();
}
mListIsNavigatingBack = false;
}