I've been trying to create a simple Horizontal scrolling option.
I have 2 ListFragments, which I would like to scroll between.
I'm getting a "Source Not Found" error when returning the View from onCreateView function.
This is my MainActivity Class:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
AppSectionsPagerAdapter mAppSectionsPagerAdapter;
ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
final ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAppSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mAppSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.app.FragmentTransaction fragmentTransaction) {
}
public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {
public AppSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
Fragment a;
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
return new FragmentA();
default:
return new FragmentB();
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
return "Section " + (position + 1);
}
}
}
This is one of my ListFragment class (the second is the same but different name & layout file):
public class FragmentA extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.favorites_layout, container, false);
updateStationsView(0);
return rootView;
}
}
updateStationView is a function that populates the List. removing it did not help, so I figured it's harmless.
The error is thrown right after the:
return rootView;
which returns to the onCreate functions of MainActivity.
When I'm changing the ListFragment to be a simple Fragment it works. I think I'm lacking some knowledge to figure this one out. I really want to use ListFragment...
Can someone please try an help ?
Many thanks for your efforts.
Adding the XML files:
activity_main.xml:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
favorites_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
I im quite sure the issue is that your custom layout for the ListFragment does not contain a ListView. These lines of code are causing the error because you need to have a ListView inside your "favourites_layout" .xml file.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.favorites_layout, container, false);
updateStationsView(0);
return rootView;
}
ListFragment has a default layout that consists of a single list view.
However, if you desire, you can customize the fragment layout by
returning your own view hierarchy from onCreateView(LayoutInflater,
ViewGroup, Bundle). To do this, your view hierarchy must contain a
ListView object with the id "#android:id/list" (or list if it's in
code)
So your layout could for example look like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
See here for more:
http://developer.android.com/reference/android/app/ListFragment.html
Related
i'm trying to get this pageviewer with fragments to work however i'm stumbled on a problem where the view stays on screen on swipe. Ideally, i'd want it to only be on a particular layout yet i'm not too sure why it "carries over" to other screens (it also stays on screen during the transition between fragments).
Any feedback will be appreciated!
Link to Imgur Screenshots
Main:
private void initUI()
{
// ---------Page Viewer with Fragments -----------
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
Adapter:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Main Frag
return new Fragment1();
case 1:
// Second Frag
return new Fragment2();
case 2:
// Third Frag
return new Fragment3();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
Fragment classes are basically this:
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main, container, false);
return rootView;
}
}
Main Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
The EditText is in the main layout, the same layout that the ViewPager is in. It should be inflated within the tab. You'll need to create a separate layout for each tab.
Main layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
layout_fragment_1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
Then you need to inflate the new layout in fragment 1.
View rootView = inflater.inflate(R.layout.layout_fragment_1, container, false);
return rootView;
I have a TabLayout and ViewPager to hold and navigate between my fragments (3 of them) and that is working fine however I'm getting confused as to how I interact with each fragment for example button clicks or edit texts. Here is my main activity xml.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.TabLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tabLayout"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#color/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill" />
<android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/viewPager"
android:layout_centerHorizontal="true"
android:layout_below="#+id/tabLayout" />
</RelativeLayout>
This is the activity for it.
public class ActivityMain extends AppCompatActivity {
private String tabTitles[] = new String[] { "contacts", "home", "search" };
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new CustomAdapater(getSupportFragmentManager(),getApplicationContext()));
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
});
}
private class CustomAdapater extends FragmentPagerAdapter {
private String fragments [] = {"contacts", "home", "search"};
public CustomAdapater(FragmentManager supportFragmentManager, Context applicationContext) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new FragmentContacts();
case 1:
return new FragmentMain();
case 2:
return new FragmentSearch();
default:
return null;
}
}
#Override
public int getCount() {
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
}
And here is a fragment activity.
public class FragmentSearch extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragment_search,container,false);
}
}
Now say in my R.layout.fragment_search I had a button just for examples sake, how do I set an onclicklistener for it? Is it within the FragmentSearch or ActivityMain? I've searched around but I'm just getting more confused.
You'd set your onClickListener in the fragment's onCreateView method by doing something like:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment1, container, false);
myButton = (Button) rootView.findViewById(R.id.buttonId);
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
return rootView;
}
Everything is the same regarding the onClickListener, as you can see. The only difference is that you have to inflate to view and use that view to find the appropriate components (e.g. buttons, textviews..)
Now, if you want to communicate between Fragments, you will need to implement more things. The basic way is to use interfaces to be implemented by your activity, so each fragment can call those methods within the activities.
There are also messaging libraries such as Otto and EventBus, they are great by sending stuff between not just fragments, but services also.
I have a MainActivity which contains a Sliding drawer for menu and a FragmentContainer to switch fragments.
I have a Fragment called History which has a layout like this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.astuetz.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#color/colorPrimary"
android:textColor="#FFFFFF"
app:pstsIndicatorColor="#FFFFFF" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tabs" />
</RelativeLayout>
And the class looks like this
public class HistoryFragment extends Fragment {
public HistoryFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_history, container, false);
// Initialize the ViewPager and set an adapter
ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
pager.setAdapter(new PagerAdapter(getActivity().getSupportFragmentManager()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);
tabs.setViewPager(pager);
return view;
}
class PagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = {"Last Transaction", "History"};
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new LastTransaction();
case 1:
return new AboutFragment();
}
return null;
}
}
}
This History page works fine the first time when it is called from the NavigationSlider menu. The history page contains two sliding tabs with two fragments. These are displayed the first time and everything works fine.
The problem happens, when they are called the second time or after that.
There is no error shown, the layout is loaded, the sliding tabs are shown, but their fragments are not shown and the sliders malfunction.
What may be the reason for this problem ?
I tried to use a different approach for implementing the sliders in fragments as per this StackOverflow answer. Still the same problem.
Thanks in advance.
replace
pager.setAdapter(new PagerAdapter(getActivity().getSupportFragmentManager()));
with
pager.setAdapter(new PagerAdapter(getActivity().getChildFragmentmanager()));
Reason:
The CHILD FragmentManager is the one that handles Fragments contained within the Fragment that it was added to.
This is MyTabActivity.java class
public class MyTabActivity extends FragmentActivity {
ViewPager Tab;
TabPagerAdapter TabAdapter;
ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_layout);
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager)findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar = getActionBar();
actionBar.setSelectedNavigationItem(position); }
});
Tab.setAdapter(TabAdapter);
actionBar = getActionBar();
//Enable Tabs on Action Bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener(){
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
Toast.makeText(getBaseContext(), "Tab ReSelected: " + tab.getPosition(), Toast.LENGTH_SHORT).show();
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
Tab.setCurrentItem(tab.getPosition());
Toast.makeText(getBaseContext(), "Tab Selected: " + tab.getPosition(), Toast.LENGTH_SHORT).show();
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
Toast.makeText(getBaseContext(), "Tab UnSelected: " + tab.getPosition(), Toast.LENGTH_SHORT).show();
}};
//Add New Tab
actionBar.addTab(actionBar.newTab().setText("Tab1").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Tab2").setTabListener(tabListener));
}
}
This is TabPagerAdapter.java
public class TabPagerAdapter extends FragmentStatePagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
return new Tab1Activity();
case 1:
return new Tab2Activity();
}
return null;
}
#Override
public int getCount() {
//No of Tabs
return 2;
}
}
public class Tab1Activity extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_main, container, false);
/// code to display LIstView
.
.
//here i m trying to invoke other tab on click of list item...this where i stuck
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adptr, View view, int pos,
long id) {
/// this code here is not working for me
Tab2Activity myDetailFragment = new Tab2Activity ();
Bundle bundle = new Bundle();
bundle.putString("KEY_DETAIL", "Hi");
myDetailFragment.setArguments(bundle);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.attach(myDetailFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}});
return monthlyView;
}
}
This is Tab2Activity.java
public class Tab2Activity extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View dailyView = inflater.inflate(R.layout.activity_mian, container, false);
// displaying list item based on the input from tab1
return dailyView;
}
}
This is activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ListView
android:id="#+id/list_View1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</RelativeLayout>
This is pager.xml
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- The main content view starts -->
<LinearLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
Now my question is, i am displaying a list of item using listview in tab1
and i want to invoke tab2 when user click on the list item of tab1
and display some data on tab2 by sending some data from tab1 to tab2.
I an mew to android, please guide me with proper solutions. Thanks :)
Use viewPager.setCurrentItem(position, true); to switch between tabs.
Then, use this to get the current fragment.
Then you call a public method of that fragment that you create to do whatever you want.
Please, advice. I can't get ViewPager working. Here is what I'am doing:
1) This is my LinearLayout in which I will put the ViewPager. I'am sure that it's work. I can put any View in it:
<LinearLayout
android:id="#+id/view_contact_values_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/view_contact_sub_nav"
android:orientation="vertical"
android:paddingLeft="10dip" >
</LinearLayout>
2) Next I'm creating the ViewPager in code:
private void createViewPager() {
ViewPager viewPager = new ViewPager(this);
DatesPagerAdapter datesPagerAdapter = new DatesPagerAdapter(this);
viewPager.setAdapter(datesPagerAdapter);
viewPager.setCurrentItem(1);
llContainer.addView(viewPager);
}
3) And the ViewPagerAdapter (PagerAdapter):
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = (LayoutInflater) container.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.dates_carusel_item, null);
((ViewPager) container).addView(v, 0);
return v;
}
#Override
public int getCount(){
return 5;
}
But when I open my Activity, there is nothing showing in my LinearLayout.
P.S.: Sorry for the bad question styling. Code tag in this editor is strange.
Take a class extending Fragemnt
class ExampleFragment extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dates_carusel_item, null);
return v;
}
And in your PagerAdapter do this
private class DatesPagerAdapter extends FragmentPagerAdapter
{
public DatesPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
ExampleFragment fragment=new ExampleFragment();
Bundle bundle=new Bunlde();
//put bundle data here
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
5;
}
}
Whatever view you want to set do it on the Example Fragment and add your viewPager
ViewPager pager=new ViewPager(this);
pager.setAdapter(new DatesPagerAdapter);
llContainer.addView(pager)
Add your ViewPager in xml itself to get it proprly alligned or else you can setLayoutParams in runtime if its a visibilty error
android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_below="#id/view_contact_sub_nav"android:id="+id/view_contact_values_container"
android:paddingLeft="10dip">
<android.support.v4.view.ViewPager
android:id="#+id/imagesgallery"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>