I want to change the height of a ViewPager because it contains some childs with different height. I have read that wrap_content is not possible for ViewPager so I want to change the height of it in runtime.
I have tried this but it is not working:
pager.getLayoutParams().height=1000;
Could someone offer help please?
CustomViewPager.class
public class CustomViewPager extends ViewPager {
/**
* Constructor
*
* #param context
* the context
*/
public CustomViewPager(Context context) {
super(context);
}
/**
* Constructor
*
* #param context
* the context
* #param attrs
* the attribute set
*/
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height)
height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
xml file:
<com.arsoft.ex.viewpager.CustomViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.arsoft.ex.viewpager.CustomViewPager>
MainClass:
tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
pager = (CustomViewPager) findViewById(R.id.viewPager);
adapter = new MyPagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
final int pageMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getResources()
.getDisplayMetrics());
pager.setPageMargin(pageMargin);
tabs.setViewPager(pager);
FragmentPagerAdapter:
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = { "Cook", "Recipe", "Comments" };
public MyPagerAdapter(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: **pager.getLayoutParams().height=100;**
return CookCardFragment.newInstance(position, pager);
case 1: **pager.getLayoutParams().height=400;**
return RecipeCardFragment.newInstance(position, pager);
case 2: **pager.getLayoutParams().height=1000;**
return CookCardFragment.newInstance(position, pager);
}
return null;
}
}
I have seen this problem before.
Maybe you could use the fumction like this:
ViewPager vp = (CustomViewPager) findViewById(R.id.viewPager);
...
ViewGroup.LayoutParams params = vp.getLayoutParams();
params.height = 1000;
vp.setLayoutParams(params);
Check my answer, I was able to change the height of ViewPager when you change the page or change the height of it child
https://stackoverflow.com/a/25710358/1835245
Related
I would like to know if is it possible to have a PagerAdapter with wrap_content without using getChildCount() and getChildAt(i)?
I have checked the answer below, but since on my adapter doesn't have children it doesn't work.
https://stackoverflow.com/a/20784791/10020799
Does someone know how to make an wrap_content adapter in this case?
My PagerAdapter code is:
public class SectionsPagerAdapter extends PagerAdapter {
private Integer pagerTotal = 10;
public SectionsPagerAdapter(Context c) {
super();
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setPagerTotal(Integer item) {
pagerTotal = item;
}
#Override
public int getCount() {
return pagerTotal;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.home_top_page, null);
container.addView(layout);
topMain = (ImageView) layout.findViewById(R.id.top_main);
if(imageBitmapArray != null && imageBitmapArray.length > 0){
topMain.setImageBitmap(imageBitmapArray[position]);
}else{
if(intImageArray != null) {
topMain.setImageResource(R.drawable.top_main_01);
}
}
return layout;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
}
You can resize the ViewPager to it's current page size on page swipe from this answer.
You can use the following code:
public class WrapContentViewPager extends ViewPager {
private int mCurrentPagePosition = 0;
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
if (wrapHeight) {
View child = getChildAt(mCurrentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
}
} catch (Exception e) {
e.printStackTrace();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void reMeasureCurrentPage(int position) {
mCurrentPagePosition = position;
requestLayout();
}
}
Use it in xml:
<your.package.name.WrapContentViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</your.package.name.WrapContentViewPager>
After that call reMeasureCurrentpage function on page swipe.
final WrapContentViewPager wrapContentViewPager = (WrapContentViewPager) findViewById(R.id.view_pager);
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
wrapContentViewPager.reMeasureCurrentPage(wrapContentViewPager.getCurrentItem());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Note that a list can have hundreds of items then this is not good to use this wrap_content ViewPager.
Even with a not expandable adapter is possible to use getChildCount() and getChildAt(i) functions.
Based on Khemraj's answer and this post's answer, I was able to solve the problem with the following code:
class:
public class WrapContentViewPager extends ViewPager {
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for(int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if(h > height) height = h;
}
if (height != 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
xml:
<your.package.name.WrapContentViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</your.package.name.WrapContentViewPager>
on page swipe:
final WrapContentViewPager wrapContentViewPager = (WrapContentViewPager) findViewById(R.id.view_pager);
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I am having view pager with 4 different fragments. In this, 3 fragments only contains webview. All the fragments load different contents. I unable to set a height based on the loaded content. For that, I wrote a custom viewpager to measure height of viewpager. For the first viewpager fragment, height is calculated properly. But when navigate to second or third fragment, viewpager height is not calculated accurately. I don't know, what is the issue is in my code and what i need to change to calculate proper height for each fragment after navigate to that view pager page. Here is my view pager and pager adapter codes. Kindly help me.
Custom View pager:
public class CustomViewPager extends ViewPager {
public CustomViewPager (Context context) {
super(context);
}
public CustomViewPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
final View tab = getChildAt(0);
int width = getMeasuredWidth();
int tabHeight = tab.getMeasuredHeight();
if (wrapHeight) {
// Keep the current measured width.
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
}
int fragmentHeight = measureFragment(((Fragment) getAdapter().instantiateItem(this, getCurrentItem())).getView());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(tabHeight + fragmentHeight + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()), MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
#Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
requestLayout();
invalidate();
super.setOnPageChangeListener(listener);
}
#Override
public void addOnPageChangeListener(OnPageChangeListener listener) {
super.addOnPageChangeListener(listener);
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
}
PagerAdapter:
public class MerchantsCataAdapter extends FragmentPagerAdapter {
Context context;
Merchant merchant;
Fragment fragment;
private int mCurrentPosition = -1;
private String[] tabs = {"Home", "About Us","Promotions","Store Information"};
public MerchantsCataAdapter(FragmentManager fm, Context context,Merchant merchant) {
super(fm);
this.context = context;
this.merchant = merchant;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
fragment= new HomeContentFragment().newInstance(merchant.getCompany_home_content(),merchant.getVideo_url());
break;
case 1:
fragment= new AboutusFragment().newInstance(merchant.getFull_description(),merchant.getVideo_url());
break;
case 2:
fragment= new AboutusFragment().newInstance(merchant.getCompany_promotions(),merchant.getVideo_url());
break;
case 3:
fragment= new FragmentStoreInformation().newInstance(merchant.getMerchantId(),merchant.getName());
break;
}
return fragment;
}
#Override
public int getCount() {
return tabs.length;
}
public String getTabView(int position) {
return tabs[position];
}
Finally, I find the answer. Place below property in Webview in xml. This will take webview height automatically based on the content.
android:scrollbarStyle="insideOverlay"
I have 3 Tabs (Slidingtablayout). The left tab has a fragment and the right tab has a fragment.
But the tab in the middle should start a new activity and not have a fragment.
Is this possible and how can i do this?
MainActivity
public class MainActivity extends ActionBarActivity {
MyPageAdapter pagerAdapter;
List<Fragment> fragments;
ViewPager viewPager;
SlidingTabLayout tabLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing SlidiTabLayout
tabLayout = (SlidingTabLayout) findViewById(R.id.tabLayout);
// Customizing SlidingTabLayout
tabLayout.setCustomTabView(R.layout.custom_tab, 0);
tabLayout.setDistributeEvenly(true);
// initializing PagerAdapter
fragments = getFragments();
pagerAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments, this);
// initializing ViewPager
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(pageAdapter);
tabLayout.setViewPager(viewPager);
}
// adding fagments
public List<Fragment> getFragments() {
List<Fragment> addFragment = new ArrayList<Fragment>();
addFragment.add(ExampleFragment.newInstance());
// Activity instead of fragment
addFragment.add(Change this .newInstance());
addFragment.add(ExampleFragment.newInstance());
return addFragment;
}
MyPagerAdapter
public class MyPageAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> fragments;
private CharSequence Titles[];
private Context context;
int icons [] = {R.drawable.lefticon, R.drawable.middleicon, R.drawable.righticon};
Drawable drawable;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments, Context context) {
super(fm);
this.fragments = fragments;
this.context = context;
}
#Override
public CharSequence getPageTitle(int position) {
drawable = context.getResources().getDrawable(icons[position]);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
SpannableString sb = new SpannableString(" ");
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
// this.fragments.get(position)
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
How the fragments look like:
public class PlayFragment extends Fragment {
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final ExampleFragment newInstance()
{
PlayFragment mf = new PlayFragment();
Bundle bd = new Bundle(1);
mf.setArguments(bd);
return mf;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View v = inflater.inflate(R.layout.example_fragment, container, false);
return v;
}
}
SlidingTabLayout
public class SlidingTabLayout extends HorizontalScrollView {
/**
* Allows complete control over the colors drawn in the tab layout. Set with
* {#link #setCustomTabColorizer(TabColorizer)}.
*/
public interface TabColorizer {
/**
* #return return the color of the indicator used when {#code position} is selected.
*/
int getIndicatorColor(int position);
}
private static final int TITLE_OFFSET_DIPS = 24;
private static final int TAB_VIEW_PADDING_DIPS = 16;
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
private int mTitleOffset;
private int mTabViewLayoutId;
private int mTabViewTextViewId;
private boolean mDistributeEvenly;
private ViewPager mViewPager;
private SparseArray<String> mContentDescriptions = new SparseArray<String>();
private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
private final SlidingTabStrip mTabStrip;
public SlidingTabLayout(Context context) {
this(context, null);
}
public SlidingTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Disable the Scroll Bar
setHorizontalScrollBarEnabled(false);
// Make sure that the Tab Strips fills this View
setFillViewport(true);
mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
/**
* Set the custom {#link TabColorizer} to be used.
*
* If you only require simple custmisation then you can use
* {#link #setSelectedIndicatorColors(int...)} to achieve
* similar effects.
*/
public void setCustomTabColorizer(TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
/**
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
* circular array. Providing one color will mean that all tabs are indicated with the same color.
*/
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
/**
* Set the {#link ViewPager.OnPageChangeListener}. When using {#link SlidingTabLayout} you are
* required to set any {#link ViewPager.OnPageChangeListener} through this method. This is so
* that the layout can update it's scroll position correctly.
*
* #see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
*/
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
/**
* Set the custom layout to be inflated for the tab views.
*
* #param layoutResId Layout id to be inflated
* #param textViewId id of the {#link TextView} in the inflated view
*/
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
/**
* Sets the associated view pager. Note that the assumption here is that the pager content
* (number of tabs and tab titles) does not change after this call has been made.
*/
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.setOnPageChangeListener(new InternalViewPagerListener());
populateTabStrip();
}
}
/**
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
* {#link #setCustomTabView(int, int)}.
*/
protected TextView createDefaultTabView(Context context) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
outValue, true);
textView.setBackgroundResource(outValue.resourceId);
textView.setAllCaps(true);
int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new TabClickListener();
// adapter.getCount();
for (int i = 0; i < adapter.getCount(); i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
// If there is a custom tab view layout id set, try and inflate it
tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
false);
tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
}
if (tabView == null) {
tabView = createDefaultTabView(getContext());
}
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
tabTitleView = (TextView) tabView;
}
if (mDistributeEvenly) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
}
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
}
}
public void setContentDescription(int i, String desc) {
mContentDescriptions.put(i, desc);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mViewPager != null) {
scrollToTab(mViewPager.getCurrentItem(), 0);
}
}
private void scrollToTab(int tabIndex, int positionOffset) {
final int tabStripChildCount = mTabStrip.getChildCount();
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
return;
}
View selectedChild = mTabStrip.getChildAt(tabIndex);
if (selectedChild != null) {
int targetScrollX = selectedChild.getLeft() + positionOffset;
if (tabIndex > 0 || positionOffset > 0) {
// If we're not at the first child and are mid-scroll, make sure we obey the offset
targetScrollX -= mTitleOffset;
}
scrollTo(targetScrollX, 0);
}
}
private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
private int mScrollState;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int tabStripChildCount = mTabStrip.getChildCount();
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
return;
}
mTabStrip.onViewPagerPageChanged(position, positionOffset);
View selectedTitle = mTabStrip.getChildAt(position);
int extraOffset = (selectedTitle != null)
? (int) (positionOffset * selectedTitle.getWidth())
: 0;
scrollToTab(position, extraOffset);
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mTabStrip.onViewPagerPageChanged(position, 0f);
scrollToTab(position, 0);
}
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
mTabStrip.getChildAt(i).setSelected(position == i);
}
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageSelected(position);
}
}
}
private class TabClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
return;
}
}
}
}
}
And i tried something too. Because i want to have:
3 Tabs
2 Fragments
Tab in the middle should be without fragment
I edited this method here (MainActivity):
// adding fragments
public List<Fragment> getFragments() {
List<Fragment> addFragment = new ArrayList<Fragment>();
addFragment.add(ExampleFragment.newInstance());
delete middle fragment
//addFragment.add(ExampleFragment.newInstance());
addFragment.add(ExampleFragment.newInstance());
return addFragment;
}
I deleted one Fragment.
Which means i accomplished the goal to have 2 Fragments.
2 Fragments check
Because i only have as much tabs as fragments, that would mean that i'd only have 2 Tabs too.
So i went to the SlidingTabLayout and changed this method:
I changed the for loop to this |i < 3| instead of |i < adapter.getCount();|
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new TabClickListener();
// 3 instead of adapter.getCount(); | For 3 tabs
for (int i = 0; i < 3; i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
// If there is a custom tab view layout id set, try and inflate it
tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
false);
tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
}
if (tabView == null) {
tabView = createDefaultTabView(getContext());
}
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
tabTitleView = (TextView) tabView;
}
if (mDistributeEvenly) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
}
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
}
}
And Now:
3 Tabs check
and
2 SlidingTablayout check
but not
Tab in the middle should be without fragment
I had 3 Fragments and 3 Tabs i deleted one Fragment and this caused that the last fragment moved one position up. Now the right fragment is in the position of the middle fragment. Now when i click on the middle tab i get the fragment which was on the right tab.
In this case my question is how to get the fragment which moved now in the position of the middle tab back to the right tab.
Hope you understand what i want. Sorry for my bad english :).
Firstly, You NEED those fragments to Navigate between 3 tabs. So my solution is, since you need to launch an activity from 2nd Tab, Use 3 fragment. Yes 3 fragments, so use this code in the onResume() method of the Middle fragment:
Intent intent = new Intent(getActivity(), YOUR_ACTIVITY_NAME.class);
startActivity(intent);
This should take you to a new activity.
Secondly, launching Activity for the 2nd Tab is a very bad design of your Application. I recommend not following this design if you are planning to release this application in the Play store. Use Navigation Drawer instead.
Create two fragment and one activity
Add activity to the tab as below
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
intent = new Intent().setClass(this, SecondActivity.class);
spec = tabHost.newTabSpec("Second").setIndicator("Second")
.setContent(intent);
tabHost.addTab(spec);
Follow the link below to add activity to tabs.
http://www.technotalkative.com/android-tab-bar-example-1/
I'm trying to create a custom viewpager inside custom scroll viewthat dynamically wraps the current child's height.
package com.example.vihaan.dynamicviewpager;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ScrollView;
/**
* Created by vihaan on 1/9/15.
*/
public class CustomScrollView extends ScrollView {
private GestureDetector mGestureDetector;
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev)
&& mGestureDetector.onTouchEvent(ev);
}
// Return false if we're scrolling in the x direction
class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return (Math.abs(distanceY) > Math.abs(distanceX));
}
}
}
CustomPager
/**
* Created by vihaan on 1/9/15.
*/
public class CustomPager extends ViewPager {
public CustomPager (Context context) {
super(context);
}
public CustomPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
final View tab = getChildAt(0);
int width = getMeasuredWidth();
int tabHeight = tab.getMeasuredHeight();
if (wrapHeight) {
// Keep the current measured width.
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
}
int fragmentHeight = measureFragment(((Fragment) getAdapter().instantiateItem(this, getCurrentItem())).getView());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(tabHeight + fragmentHeight + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()), MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
}
MyPagerAdapter
public class MyPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fragments = new ArrayList<Fragment>();
fragments.add(new FirstFragment());
fragments.add(new SecondFragment());
fragments.add(new ThirdFragment());
fragments.add(new FourthFragment());
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
}
I was hoping that this would wrap around current fragments height but it is only taking the height of first child into consideration.
Sample github project : https://github.com/VihaanVerma89/DynamicViewPager
Made a few tweaks in your code and it is working fine now.
1] onMeasure function wasn't proper. Use below logic
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCurrentView == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
int height = 0;
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = mCurrentView.getMeasuredHeight();
if (h > height) height = h;
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
2] ViewPager needs to be re-measured each time a page is changed. Good place to do this is setPrimaryItem function of PagerAdapter
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
Fragment fragment = (Fragment) object;
CustomPager pager = (CustomPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
Here is the link to GitHub project with these tweaks:
https://github.com/vabhishek/WrapContentViewPagerDemo
#abhishek's ans does what is required but the code below also adds animation during height change
public class WrappingViewPager extends ViewPager {
private Boolean mAnimStarted = false;
public WrappingViewPager(Context context) {
super(context);
}
public WrappingViewPager(Context context, AttributeSet attrs){
super(context, attrs);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(!mAnimStarted && null != getAdapter()) {
int height = 0;
View child = ((FragmentPagerAdapter) getAdapter()).getItem(getCurrentItem()).getView();
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
height = child.getMeasuredHeight();
if (VersionUtils.isJellyBean() && height < getMinimumHeight()) {
height = getMinimumHeight();
}
}
// Not the best place to put this animation, but it works pretty good.
int newHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
if (getLayoutParams().height != 0 && heightMeasureSpec != newHeight) {
final int targetHeight = height;
final int currentHeight = getLayoutParams().height;
final int heightChange = targetHeight - currentHeight;
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime >= 1) {
getLayoutParams().height = targetHeight;
} else {
int stepHeight = (int) (heightChange * interpolatedTime);
getLayoutParams().height = currentHeight + stepHeight;
}
requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mAnimStarted = true;
}
#Override
public void onAnimationEnd(Animation animation) {
mAnimStarted = false;
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
a.setDuration(1000);
startAnimation(a);
mAnimStarted = true;
} else {
heightMeasureSpec = newHeight;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Just in case someone else find this post like me. Worked version without bug of initially zero height:
public class DynamicHeightViewPager extends ViewPager {
private View mCurrentView;
public DynamicHeightViewPager(Context context) {
super(context);
}
public DynamicHeightViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mCurrentView != null) {
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int height = Math.max(0, mCurrentView.getMeasuredHeight());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void measureCurrentView(View currentView) {
mCurrentView = currentView;
requestLayout();
}
}
And used it in custom FragmentPagerAdapter, like this
public abstract class AutoheightFragmentPagerAdapter extends FragmentPagerAdapter {
private int mCurrentPosition = -1;
public AutoheightFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition && container instanceof DynamicHeightViewPager) {
Fragment fragment = (Fragment) object;
DynamicHeightViewPager pager = (DynamicHeightViewPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
}
Adding to #vihaan's solution, if you have a PagerTitleStrip or PagetTabStrip, you can add this
// Account for pagerTitleStrip or pagerTabStrip
View tabStrip = getChildAt(0);
if (tabStrip instanceof PagerTitleStrip) {
tabStrip.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED));
height += tabStrip.getMeasuredHeight();
}
just before starting the animation (before the comment
// Not the best place to put this animation, but it works pretty good.
so that the height of the strip is taken into account.
public class WrapContentViewPager extends ViewPager {
private Boolean mAnimStarted = false;
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!mAnimStarted && null != getAdapter()) {
int height = 0;
View child = ((CommonViewPagerAdapter) getAdapter()).getItem(getCurrentItem()).getView();
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
height = child.getMeasuredHeight();
if (height < getMinimumHeight()) {
height = getMinimumHeight();
}
}
// Not the best place to put this animation, but it works pretty good.
int newHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
if (getLayoutParams().height != 0 && heightMeasureSpec != newHeight) {
final int targetHeight = height;
final int currentHeight = getLayoutParams().height;
final int heightChange = targetHeight - currentHeight;
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime >= 1) {
getLayoutParams().height = targetHeight;
} else {
int stepHeight = (int) (heightChange * interpolatedTime);
getLayoutParams().height = currentHeight + stepHeight;
}
requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mAnimStarted = true;
}
#Override
public void onAnimationEnd(Animation animation) {
mAnimStarted = false;
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
a.setDuration(100);
startAnimation(a);
mAnimStarted = true;
} else {
heightMeasureSpec = newHeight;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
==============================
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
wrapContentViewPager.measure(wrapContentViewPager.getMeasuredWidth(), wrapContentViewPager.getMeasuredHeight());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
This few lines of code will solve the problem.
Create a custome widget for viewpager class. and in xml use it for viewpager.
public class DynamicHeightViewPager extends ViewPager {
private View mCurrentView;
public DynamicHeightViewPager(Context context) {
super(context);
}
public DynamicHeightViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mCurrentView != null) {
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int height = Math.max(0, mCurrentView.getMeasuredHeight());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void measureCurrentView(View currentView) {
mCurrentView = currentView;
requestLayout();
}
}
Then in the view pager adapter override the below method and add the code.
#Override
public void setPrimaryItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
super.setPrimaryItem(container, position, object);
if (container instanceof DynamicHeightViewPager) {
// instead of card view give your root view from your item.xml file.
CardView cardView = (CardView) object;
((DynamicHeightViewPager) container).measureCurrentView(cardView);
}
}
Make your view pager height wrap_content inside xml file so you can check the result.
I'm developing an app before the news of Lollipop, then I'm using ActionBar, Tabs (view pager) and navigation drawer.
With the changes of the Lollipop that ActionBar does not exists anymore, what should I change in my app from now on?
Thanks!
You should use toolbar. You can create it like this and set it up as an actionbar:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:background="#2196F3"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.Toolbar>
In your activity/fragment:
// Set a toolbar to replace the action bar.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
If you want to have tabs as like you had with your actionbar:
Create 2 classes into your project.
SlidingTabStrip:
class SlidingTabStrip extends LinearLayout {
private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0;
private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3;
private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
private final int mBottomBorderThickness;
private final Paint mBottomBorderPaint;
private final int mSelectedIndicatorThickness;
private final Paint mSelectedIndicatorPaint;
private final int mDefaultBottomBorderColor;
private int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout.TabColorizer mCustomTabColorizer;
private final SimpleTabColorizer mDefaultTabColorizer;
SlidingTabStrip(Context context) {
this(context, null);
}
SlidingTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
final float density = getResources().getDisplayMetrics().density;
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
final int themeForegroundColor = outValue.data;
mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
mDefaultTabColorizer = new SimpleTabColorizer();
mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
mBottomBorderPaint = new Paint();
mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
mSelectedIndicatorPaint = new Paint();
}
void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
mCustomTabColorizer = customTabColorizer;
invalidate();
}
void setSelectedIndicatorColors(int... colors) {
// Make sure that the custom colorizer is removed
mCustomTabColorizer = null;
mDefaultTabColorizer.setIndicatorColors(colors);
invalidate();
}
void onViewPagerPageChanged(int position, float positionOffset) {
mSelectedPosition = position;
mSelectionOffset = positionOffset;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
final int height = getHeight();
final int childCount = getChildCount();
final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
? mCustomTabColorizer
: mDefaultTabColorizer;
// Thick colored underline below the current selection
if (childCount > 0) {
View selectedTitle = getChildAt(mSelectedPosition);
int left = selectedTitle.getLeft();
int right = selectedTitle.getRight();
int color = tabColorizer.getIndicatorColor(mSelectedPosition);
if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
if (color != nextColor) {
color = blendColors(nextColor, color, mSelectionOffset);
}
// Draw the selection partway between the tabs
View nextTitle = getChildAt(mSelectedPosition + 1);
left = (int) (mSelectionOffset * nextTitle.getLeft() +
(1.0f - mSelectionOffset) * left);
right = (int) (mSelectionOffset * nextTitle.getRight() +
(1.0f - mSelectionOffset) * right);
}
mSelectedIndicatorPaint.setColor(color);
canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
height, mSelectedIndicatorPaint);
}
// Thin underline along the entire bottom edge
canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
}
/**
* Set the alpha value of the {#code color} to be the given {#code alpha} value.
*/
private static int setColorAlpha(int color, byte alpha) {
return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
}
/**
* Blend {#code color1} and {#code color2} using the given ratio.
*
* #param ratio of which to blend. 1.0 will return {#code color1}, 0.5 will give an even blend,
* 0.0 will return {#code color2}.
*/
private static int blendColors(int color1, int color2, float ratio) {
final float inverseRation = 1f - ratio;
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
return Color.rgb((int) r, (int) g, (int) b);
}
private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
private int[] mIndicatorColors;
#Override
public final int getIndicatorColor(int position) {
return mIndicatorColors[position % mIndicatorColors.length];
}
void setIndicatorColors(int... colors) {
mIndicatorColors = colors;
}
}
}
SlidingTabLayout:
public class SlidingTabLayout extends HorizontalScrollView {
/**
* Allows complete control over the colors drawn in the tab layout. Set with
* {#link #setCustomTabColorizer(TabColorizer)}.
*/
public interface TabColorizer {
/**
* #return return the color of the indicator used when {#code position} is selected.
*/
int getIndicatorColor(int position);
}
private static final int TITLE_OFFSET_DIPS = 24;
private static final int TAB_VIEW_PADDING_DIPS = 16;
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
private int mTitleOffset;
private int mTabViewLayoutId;
private int mTabViewTextViewId;
private boolean mDistributeEvenly;
private ViewPager mViewPager;
private SparseArray<String> mContentDescriptions = new SparseArray<String>();
private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
private final SlidingTabStrip mTabStrip;
public SlidingTabLayout(Context context) {
this(context, null);
}
public SlidingTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Disable the Scroll Bar
setHorizontalScrollBarEnabled(false);
// Make sure that the Tab Strips fills this View
setFillViewport(true);
mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
/**
* Set the custom {#link TabColorizer} to be used.
*
* If you only require simple custmisation then you can use
* {#link #setSelectedIndicatorColors(int...)} to achieve
* similar effects.
*/
public void setCustomTabColorizer(TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
/**
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
* circular array. Providing one color will mean that all tabs are indicated with the same color.
*/
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
/**
* Set the {#link ViewPager.OnPageChangeListener}. When using {#link SlidingTabLayout} you are
* required to set any {#link ViewPager.OnPageChangeListener} through this method. This is so
* that the layout can update it's scroll position correctly.
*
* #see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
*/
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
/**
* Set the custom layout to be inflated for the tab views.
*
* #param layoutResId Layout id to be inflated
* #param textViewId id of the {#link TextView} in the inflated view
*/
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
/**
* Sets the associated view pager. Note that the assumption here is that the pager content
* (number of tabs and tab titles) does not change after this call has been made.
*/
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.setOnPageChangeListener(new InternalViewPagerListener());
populateTabStrip();
}
}
/**
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
* {#link #setCustomTabView(int, int)}.
*/
protected TextView createDefaultTabView(Context context) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
outValue, true);
textView.setBackgroundResource(outValue.resourceId);
textView.setAllCaps(true);
textView.setTextColor(getResources().getColor(android.R.color.white));
int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new TabClickListener();
for (int i = 0; i < adapter.getCount(); i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
// If there is a custom tab view layout id set, try and inflate it
tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
false);
tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
}
if (tabView == null) {
tabView = createDefaultTabView(getContext());
}
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
tabTitleView = (TextView) tabView;
}
if (mDistributeEvenly) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
}
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
}
}
public void setContentDescription(int i, String desc) {
mContentDescriptions.put(i, desc);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mViewPager != null) {
scrollToTab(mViewPager.getCurrentItem(), 0);
}
}
private void scrollToTab(int tabIndex, int positionOffset) {
final int tabStripChildCount = mTabStrip.getChildCount();
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
return;
}
View selectedChild = mTabStrip.getChildAt(tabIndex);
if (selectedChild != null) {
int targetScrollX = selectedChild.getLeft() + positionOffset;
if (tabIndex > 0 || positionOffset > 0) {
// If we're not at the first child and are mid-scroll, make sure we obey the offset
targetScrollX -= mTitleOffset;
}
scrollTo(targetScrollX, 0);
}
}
private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
private int mScrollState;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int tabStripChildCount = mTabStrip.getChildCount();
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
return;
}
mTabStrip.onViewPagerPageChanged(position, positionOffset);
View selectedTitle = mTabStrip.getChildAt(position);
int extraOffset = (selectedTitle != null)
? (int) (positionOffset * selectedTitle.getWidth())
: 0;
scrollToTab(position, extraOffset);
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mTabStrip.onViewPagerPageChanged(position, 0f);
scrollToTab(position, 0);
}
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
mTabStrip.getChildAt(i).setSelected(position == i);
}
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageSelected(position);
}
}
}
private class TabClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
return;
}
}
}
}
}
Create an adapter. This is where you write which fragments you want to create.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
FirstFragment tab1 = new FirstFragment();
return tab1;
}
else if(position == 1) // As we are having 3 tabs if the position is now 0 it must be 1 so we are returning second tab
{
SecondFragment tab2 = new SecondFragment();
return tab2;
} else {
ThirdFragment tab3 = new ThirdFragment();
return tab3;
}
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
Go to your layout where you want to have the tabs:
<YOURPACKAGENAME.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar"
android:background="?attr/colorPrimary"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_below="#+id/tabs"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
></android.support.v4.view.ViewPager>
Finally go to your fragment/activity and set everything up:
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[]={"Tab 1","Tab 2","Tab 3"};
int Numboftabs =3;
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(2);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Set custom tab layout
tabs.setCustomTabView(R.layout.home_tab, 0);
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);