dynamic高度viewpager

我试图在自定义的滚动视图内创build一个自定义的viewpager,dynamic地包装当前孩子的身高。

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(); } } 

我希望这会围绕目前的碎片高度,但只考虑第一个孩子的高度。

示例github项目: https : //github.com/VihaanVerma89/DynamicViewPager

Solutions Collecting From Web of "dynamic高度viewpager"

在你的代码中做了一些调整,现在工作正常。

1] onMeasurefunction不正确。 使用下面的逻辑

 @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 。 做这个的好地方是setPrimaryItem函数

 @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()); } } } 

这里是链接到GitHub项目与这些调整: https : //github.com/vabhishek/WrapContentViewPagerDemo

@ abhishek的ans做什么是必需的,但是下面的代码也会在高度变化时添加animation

 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); } } 

添加@ vihaan的解决scheme,如果你有一个PagerTitleStrip或PagetTabStrip,你可以添加这个

 // Account for pagerTitleStrip or pagerTabStrip View tabStrip = getChildAt(0); if (tabStrip instanceof PagerTitleStrip) { tabStrip.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED)); height += tabStrip.getMeasuredHeight(); } 

在开始animation之前(在评论之前)

  //不是放这个animation的最好的地方,但是效果很好。

所以考虑到钢带的高度。

以防万一别人find像我这样的post。 工作版本没有最初零高度的错误:

 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(); } }