I am a noob to android and i have been using tutorials to construct a viewpager layout. However, i have not been able to find a tutorial that also shows how to implement the pagertitle strip as well. I have been able to gather bits and pieces and have the bar displaying, but I don't know how make the text display properly. Currently it shows multiple titles at once and loses sync with the pages. Any help is greatly appreciated.
public class MyPagerActivity extends Activity {
PagerTitleStrip mTitleStrip;
String myTitle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mypagermain);
MyPagerAdapter adapter = new MyPagerAdapter();
ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(2);
mTitleStrip = (PagerTitleStrip) findViewById(R.id.title_strip);
//some code
}
private class MyPagerAdapter extends PagerAdapter {
public int getCount() {
return 5;
}
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resId = 0;
switch (position) {
case 0:
resId = R.layout.news;
view = inflater.inflate(resId, null);
LinearLayout layout0=(LinearLayout)view.findViewById(R.id.LLnews);
WebView newsfeed = (WebView) view.findViewById(R.id.webViewnews);
((ViewPager) collection).addView(view, 0);
return view;
case 1:
resId = R.layout.coinshows;
view = inflater.inflate(resId, null);
LinearLayout layout1=(LinearLayout)view.findViewById(R.id.LLcoinshows);
WebView coinshows = (WebView) view.findViewById(R.id.webViewcoinshows);
((ViewPager) collection).addView(view, 0);
return view;
}
return resId;
}
}
#Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
#Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
#Override
public CharSequence getPageTitle(int position) {
return myTitle;
}
}
I recommend using PagerSlidingTabStrip. It's usage is very simple and the it emulates Play Store look&feel, very nice.
Usage
1.For a working implementation of this project see the sample/ folder.
Include the PagerSlidingTabStrip widget in your view. This should
usually be placed adjacent to the ViewPager it represents.
<com.astuetz.viewpager.extensions.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dip" />
2.In your onCreate method (or onCreateView for a fragment), bind the widget to the ViewPager.
// Set the pager with an adapter
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new TestAdapter(getSupportFragmentManager()));
// Bind the widget to the adapter
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setViewPager(pager);
3.(Optional) If you use an OnPageChangeListener with your view pager you should set it in the widget rather than on the pager directly.
// continued from above
tabs.setOnPageChangeListener(mPageChangeListener);
Related
I am using PagerSlidingTabStrip with a ViewPager.
Is there a way I can change the Tab icons dynamically, depending on some actions. Like when a notification is received, I want to change the icon on notifications tab to show how many notifications are unread.
Or any other library which would support that without much tweaking.
You can do it by implementing PagerSlidingTabStrip.CustomTabProvider interface. I made example project for your case, so let's explore it step by step.
Firstly, create a layout for our tab called tab_layout, for example. It will contain 2 TextView's for title and badge. In my case it looks like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tab_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="#android:color/white"
android:textStyle="bold"
android:textSize="16sp"
android:singleLine="true" />
<TextView
android:id="#+id/badge"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_toRightOf="#+id/tab_title"
android:textSize="12sp"
android:gravity="center"
android:layout_marginLeft="8dp"
android:layout_centerVertical="true"
android:textColor="#android:color/white"
android:background="#drawable/badge_background" />
</RelativeLayout>
Secondly, create a simple model for Tab, that will containt a tab title and number of notifications. I've called it ViewPagerTab:
public class ViewPagerTab {
public String title;
public int notifications;
public ViewPagerTab(String title, int notifications) {
this.title = title;
this.notifications = notifications;
}
}
Thirdly, implement PagerSlidingTabStrip.CustomTabProvider interface on your FragmentPagerAdapter. Here we will inflate tab layout and initialize the tab views, also we will define fragments for positions:
public class MainAdapter extends FragmentPagerAdapter
implements PagerSlidingTabStrip.CustomTabProvider {
ArrayList<ViewPagerTab> tabs;
public MainAdapter(FragmentManager fm, ArrayList<ViewPagerTab> tabs) {
super(fm);
this.tabs = tabs;
}
#Override
public View getCustomTabView(ViewGroup viewGroup, int i) {
RelativeLayout tabLayout = (RelativeLayout)
LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.tab_layout, null);
TextView tabTitle = (TextView) tabLayout.findViewById(R.id.tab_title);
TextView badge = (TextView) tabLayout.findViewById(R.id.badge);
ViewPagerTab tab = tabs.get(i);
tabTitle.setText(tab.title.toUpperCase());
if (tab.notifications > 0) {
badge.setVisibility(View.VISIBLE);
badge.setText(String.valueOf(tab.notifications));
} else {
badge.setVisibility(View.GONE);
}
return tabLayout;
}
#Override
public void tabSelected(View view) {
//if you don't want badges disappear when you select tab comment next lines
RelativeLayout tabLayout = (RelativeLayout) view;
TextView badge = (TextView) tabLayout.findViewById(R.id.badge);
badge.setVisibility(View.GONE);
}
#Override
public void tabUnselected(View view) {
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new OneFragment();
case 1:
return new TwoFragment();
case 2:
return new ThreeFragment();
}
return new OneFragment();
}
#Override
public int getCount() {
return tabs.size();
}
}
Fourthly, initialize tabs and pager in MainActivity's onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
pager = (ViewPager) findViewById(R.id.pager);
ArrayList<ViewPagerTab> tabsList = new ArrayList<>();
tabsList.add(new ViewPagerTab("One", 0));
tabsList.add(new ViewPagerTab("Two", 1));
tabsList.add(new ViewPagerTab("Three", 2));
adapter = new MainAdapter(getSupportFragmentManager(), tabsList);
pager.setAdapter(adapter);
tabs.setViewPager(pager);
pager.setOffscreenPageLimit(3);
getSupportActionBar().hide();
}
You will get something like this:
And finally, to get and change tab views in runtime, you can simply call getChildAt function of PagerSlidingTabStrip object in your Activity or Fragment, and do what you want:
private void notifyTabStripChanged(int position, int notificationsCount) {
LinearLayout tabHost = (LinearLayout) tabs.getChildAt(0);
RelativeLayout tabLayout = (RelativeLayout) tabHost.getChildAt(position);
TextView badge = (TextView) tabLayout.findViewById(R.id.badge);
if (notificationsCount > 0) {
badge.setVisibility(View.VISIBLE);
badge.setText(String.valueOf(notificationsCount));
} else {
badge.setVisibility(View.GONE);
}
}
Don't forget, that child views count is starting from 0. If you want to use images, just replace ImageView with TextView badge and change it's image resource instead of text. Enjoy!
You can achieve what you want by forking this lib and change the behaviour of IconTabProvider used there in sample app implemented to use only static resources.
Changes to do to your lib fork to add dynamic icon changes:
In PagerSlidingTabStrip:
Change return type (and name) of getPageIconResId method of IconTabProvider interface
public interface IconTabProvider {
//public int getPageIconResId(int position) becomes
public Bitmap getPageIconBitmap(int position)
}
This causes to update the call to this method in PagerSlidingTabStrip
--
And also to change the method addIconTab from
private void addIconTab(final int position, int resId) {
ImageButton tab = new ImageButton(getContext());
tab.setImageResource(resId);
addTab(position, tab);
}
to
private void addIconTab(final int position, bitmap icon) {
ImageButton tab = new ImageButton(getContext());
tab.setImageBitmap(icon);
addTab(position, tab);
}
Then you need to create an adapter for your tabs bar, here is an example:
public class DynamicIconPagerAdapter extends PagerAdapter implements IconTabProvider {
public HashMap<Integer, Bitmap> mapBetweenPositionAndIcons = new HashMap();
public DynamicIconPagerAdapter () {
super();
}
#Override
public int getCount() {
return mapBetweenPositionAndIcons.size();
}
#Override
public Bitmap getPageIconResId(int position) {
return mapBetweenPositionAndIcons.get(position);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
// looks a little bit messy here
TextView v = new TextView(getActivity());
v.setBackgroundResource(R.color.background_window);
v.setText("PAGE " + (position + 1));
final int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources()
.getDisplayMetrics());
v.setPadding(padding, padding, padding, padding);
v.setGravity(Gravity.CENTER);
container.addView(v, 0);
return v;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((View) view);
}
#Override
public boolean isViewFromObject(View v, Object o) {
return v == ((View) o);
}
}
Finally, when you want to update an icon just change the corresponding bitmap of the map (mapBetweenPositionAndIcons) and call notifyDataSetChanged() on your PagerSlidingTabStrip object.
I havn't tested my solution yet due to a lack of time, but I will as soon as possible! ;)
Hello I amtrying to develop app with Navigation Drawer and Swipe Tabs and I made like this in picture but here all tabs are located in one fragment can I divide and make fragment to each other tab(item 1,item 2...) inside can you help me make fragment to ech other(item 1,item 2...) and how and where add thanks
private SlidingTabLayout mSlidingTabLayout;
private ViewPager mViewPager;
public ScreenOne() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.screen_one, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Get the ViewPager and set it's PagerAdapter so that it can display items
mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
mViewPager.setAdapter(new SamplePagerAdapter());
// Give the SlidingTabLayout the ViewPager, this must be
// done AFTER the ViewPager has had it's PagerAdapter set.
mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setViewPager(mViewPager);
}
// Adapter
class SamplePagerAdapter extends PagerAdapter {
/**
* Return the number of pages to display
*/
#Override
public int getCount() {
return 10;
}
/**
* Return true if the value returned from is the same object as the View
* added to the ViewPager.
*/
#Override
public boolean isViewFromObject(View view, Object o) {
return o == view;
}
/**
* Return the title of the item at position. This is important as what
* this method returns is what is displayed in the SlidingTabLayout.
*/
#Override
public CharSequence getPageTitle(int position) {
return "Item " + (position + 1);
}
/**
* Instantiate the View which should be displayed at position. Here we
* inflate a layout from the apps resources and then change the text
* view to signify the position.
*/
#Override
public Object instantiateItem(ViewGroup container, int position) {
// Inflate a new layout from our resources
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
container, false);
// Add the newly created View to the ViewPager
container.addView(view);
// Retrieve a TextView from the inflated View, and update it's text
TextView title = (TextView) view.findViewById(R.id.item_title);
title.setText(String.valueOf(position + 1));
// Return the View
return view;
}
/**
* Destroy the item from the ViewPager. In our case this is simply
* removing the View.
*/
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
What you need is a Fragment Pager Adapater instead of a normal PagerAdapter. Check the documentation, it has a very complete working example.
In the CustomPagerAdapter of the ViewPager, in instantiateItem() method I'm trying to create an TextView and then for each page set a different text depending on certain condition. Text is read from a pages Cursor. Here is a code:
#Override
public Object instantiateItem(ViewGroup collection, int position) {
sc = new ScrollView(context);
sc.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
sc.setFillViewport(true);
tv = new TextView(context);
if(position < count) {
tv.setText(pages.getString(1));
pages.moveToPosition(position);
}else {
tv.setText("LOCKED");
}
tv.setTag(TAG_PAGE + position);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.BLACK);
tv.setTextSize(30);
sc.addView(tv);
((ViewPager) collection).addView(sc);
return sc;
}
However ViewPager behaves not as expected. The first and the second page have the same text, rest of the pages has a sign "LOCKED" as expected. When I swipe into the 4th page and come back to the first page then the first page consists of the text that suppose to be in the second page. I also tried to use myViewPager.setOffscreenPageLimit(numberOfPages) however it doesn't help.
I found this answer:
"Inside of instantiateItem, the position parameter is the position that is in need of rendering. It is NOT the position of the currently focused item that the user would see. The pages to the left and right of the currently displayed view need to be pre rendered in memory so that the animations to those screens will be smooth. "
It make sense to me but how then can I correctly display the pages content and then update it if desired? Please advise if there is different way to do it with skipping instantiateItem() method that introduce the mess and confusion into the problem. Thank you.
I have solved this problem by using a different implementation:
// Adapter class
private static class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
return PageFragment.newInstance(pages[index]); // Pages is an array of Strings
}
#Override
public int getCount() {
return numberOfPages;
}
}
// PageFragment class
public class PageFragment extends Fragment {
TextView tv;
public static PageFragment newInstance(String page) {
PageFragment pageFragment = new PageFragment();
Bundle bundle = new Bundle();
bundle.putString("pageContent", page);
pageFragment.setArguments(bundle);
return pageFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
tv = (TextView) view.findViewById(R.id.text_view);
tv.setText(getArguments().getString("pageContent"));
return view;
}
}
You can Create ViewPager Object and then set Listener onthis object.
ViewPager myPager = (ViewPager) findViewById(R.id.yourPagerid);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
myPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
//You can change textview word according to current page
switch (position) {
case 0:
break;
case 1:
break;
case 2:
break;
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Log.d("check","onPageScrolled");
}
#Override
public void onPageScrollStateChanged(int arg0) {
// Log.d("check","onPageScrollStateChanged");
}
});
I'm trying to implement ViewPager to combine two view within one activity, in which I'm facing NullPointerException when I'm trying to access items using findViewById in inflated views, my custom page adapter is as follows,
public class CustomPagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((View) object);
}
#Override
public void destroyItem(View view, int value, Object object) {
((ViewPager) view).removeView((View) object);
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public Object instantiateItem(View collection, int position) {
LayoutInflater layoutInflater = (LayoutInflater) collection.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resultId = 0;
switch (position) {
case 1:
resultId = R.layout.layout2;
break;
case 0:
default:
resultId = R.layout.layout1;
break;
}
View view = layoutInflater.inflate(resultId, null);
((ViewPager) collection).addView(view, 0);
return view;
}
}
And my activity is as follows, in which I'm trying to access button which is inside layout1 which throws null value.
public class PageSwiperActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpagerlayout);
Button myButton=(Button) findViewById(R.id.myButton);
}
}
My viewpagerlayout.xml contains only,
<android.support.v4.view.ViewPager
android:id="#+id/viewPagerLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
and my layout1.xml contains one button. Give me some guidance.
Thanks.
Did you set your PageAdapter to ViewPager?
If you don't set it, then remove line with button and add this code to your activity:
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPagerLayout);
viewPager.setAdapter(new CustomPagerAdapter());
instead of this
Button myButton = (Button) findViewById(R.id.myButton);
You can call findViewById to get your button in this method of your adapter:
#Override
public Object instantiateItem(View collection, int position) {
... // your previous code
final Button myButton = (Button) findViewById(R.id.myButton);
return view;
}
after you have inflated layout which contains this button.
After setContentView(R.layout.viewpagerlayout);
you are using
Button myButton=(Button) findViewById(R.id.myButton); directly.
But actually viewpagerlayout doesn't have any view with id myButton.
So that you are getting NULL Pointer Exception. Before using findViewById, you have to add views to ViewPager layout.
In the code you posted here, it seem to be you are adding, but you have to use it after setContentView.
)
I implemented a ViewPager in my application, and seems to work well, I use 3 XML Files for the views. on the "settings_view" there are two EditText and one Button. The Button instantiates correct, because in Debugg Mode I can see that it's not null, but when I'm clicking on, nothing happens. To understand it better, here a code excerpt:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LayoutInflater getView = getLayoutInflater();
View pushview = getView.inflate(R.layout.push_view,null);
View listenView =getView.inflate(R.layout.listen_view, null);
View settingsView = getView.inflate(R.layout.settings_view, null);
login = (Button)settingsView.findViewById(R.id.ok_button1);
login_user=(EditText)settingsView.findViewById(R.id.user1);
login_pw=(EditText)settingsView.findViewById(R.id.pw1);
ViewPager myPager = (ViewPager)findViewById(R.id.pager);
MyPagerAdapter adapter = new MyPagerAdapter();
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
login.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
do something
}
});
And here is my Pager Adapter:
class MyPagerAdapter extends PagerAdapter {
public int getCount() {
return 3;
}
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resId = 0;
switch (position) {
case 0:
resId = R.layout.settings_view;
break;
case 1:
resId = R.layout.push_view;
break;
case 2:
resId = R.layout.listen_view;
break;
}
View view = inflater.inflate(resId, null);
((ViewPager) collection).addView(view, 0);
return view;
}
#Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
#Override
public Parcelable saveState() {
return null;
}
public int getItemPosition(Object object) {
return POSITION_NONE;
}
So I cannot really figure out why it doesn't work, because it instantiates correct but the Listener doesn't react.
Is somebody here to open my eyes ?
Thanks
Update:
These are the values I get when instantiate the Button with findviewbyid:
login=Button (id=8300....)
mAttachInfo=null
.
.
.
android.widget.Button#4050d490
Is mAttachInfo neccessary?
or something else not normal?
Update:
Ok found out, that if I'm setting up the onclick in XML and then using just the method in code, it works fine, but now it's the same Problem Spinner.setAdapter, nothing happens...
update: solved it with that link, it's briliant
http://code.google.com/p/ratebeerforandroid/source/browse/RateBeerForAndroid/src/com/ratebeer/android/gui/fragments/SearchFragment.java#486
I am implement onTouchListerner and then try to detect onclicklisterner.
You can refer my answer here:
https://stackoverflow.com/a/13264379/968532