我已按照this和that个回答,我还找到了this个链接。
我使用这些资源进行试验&错误。现在,我的自定义ViewPager
成功衡量了其内容,但只显示了第一个。仅供参考,我的ViewPager
包含一些复杂的视图,例如ExpendableListView
- 这就是为什么这些资源中的代码都没有完美运行,我需要自己修改代码。
我有4个片段(内容),所以我使用pager.setOffscreenPageLimit(3);
这是我的自定义ViewPager
:
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);
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
}
这是我的CustomPagerTabStrip
:
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
android.view.ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
这是我的XML:
<RelativeLayout
android:id="@+id/relativePager"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.xxx.yyy.util.CustomViewPager
android:id="@+id/detailPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.xxx.yyy.util.CustomPagerTabStrip
android:id="@+id/detailTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#161C28"
android:textColor="#FFFFFF" />
</com.xxx.yyy.util.CustomViewPager>
</RelativeLayout>
示例案例:
如果第一个片段的高度为100px,那么所有其他片段将保持在100px。 因此,如果第二个片段的高度为130px,则将其切割为100px。
当我尝试调试时,我onMeasure
上的CustomViewPager
在创建Activity
时总是被调用4次,但所有这些都只读取了第一个片段。在此之后,onMeasure
永远再次被调用,即使我从一个片段更改(向左/向右滑动)到另一个片段。
请帮帮我,我花了很多时间让这件事工作。 只要问我是否需要更多信息,感谢您的时间。
答案 0 :(得分:15)
嗨Blaze发现有些东西用完了,以下解决方案对我有用。
它包括自定义滚动视图和自定义视图寻呼机。目的自定义视图寻呼机是根据子节点的高度动态计算高度,其高度设置为最初包装内容,滚动视图的目的是处理触摸事件,如果用户垂直滚动屏幕,它将即使滚动也不会通过触摸,因此用户可以滚动页面。
自定义滚动视图
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 SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return (Math.abs(distanceY) > Math.abs(distanceX));
}
}
}
自定义视图寻呼机
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();
}
}
布局文件
<com.example.demo2.activity.widget.CustomScrollView 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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
style="@style/text"
android:text="Text 1" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 2" />
<com.example.demo2.activity.widget.CustomPager
android:id="@+id/myViewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 4" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 5" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 6" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 7" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 8" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 9" />
<View style="@style/text_divider" />
<TextView
style="@style/text"
android:text="Text 10" />
</LinearLayout>
<强>活动强>
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyPagerAdapter pageAdapter = new MyPagerAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager)findViewById(R.id.myViewPager);
pager.setAdapter(pageAdapter);
}
}
片段适配器
不同高度的碎片被添加到viewpager,FragmentBlue,Green等只是片段用于添加到viewpager你可以使用自己的片段,有一点要记住的是他们的外部布局应该是相同的,在我的情况下我使用了衬垫所有
的布局public class MyPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
this.fragments = new ArrayList<Fragment>();
fragments.add(new FragmentBlue());
fragments.add(new FragmentGreen());
fragments.add(new FragmentPink());
fragments.add(new FragmentRed());
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
答案 1 :(得分:3)
public CustomPager (Context context) {
super(context);
}
public CustomPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
int getMeasureExactly(View child, int widthMeasureSpec) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int height = child.getMeasuredHeight();
return MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
@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);
if (tab == null) {
return;
}
int width = getMeasuredWidth();
if (wrapHeight) {
// Keep the current measured width.
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
}
Fragment fragment = ((Fragment) getAdapter().instantiateItem(this, getCurrentItem()));
heightMeasureSpec = getMeasureExactly(fragment.getView(), widthMeasureSpec);
//Log.i(Constants.TAG, "item :" + getCurrentItem() + "|height" + heightMeasureSpec);
// super has to be called again so the new specs are treated as
// exact measurements.
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}