ViewPager高度自适应

本文是在对大神文章的理解基础上写的,算是对大神的文章做注解吧!大神文章地址:原文地址

ViewPager用的很多,比如广告条等等,可是高度却不能自适应内容,总是会占满全屏,即使设置android:height=”wrap_content”也是没有用的。后来通过网上搜索,发现了几个思路:

一、使用LinearLayout布局,利用其使用weight来自动调整ViewPager的高度;
二、使用高度固定写死的方法来解决;
三、通过自定义ViewPager,重写其onMeasure方法;
四、最后是通过代码来动态的获取ViewPager的子View高度,然后将这个高度赋值给ViewPager。

我们现在就来说说每个方法的使用:
首先第一个,适用于父布局占据整个屏幕的时候,如图:
这里写图片描述
使用方法(代码和效果图片不一样,只是这里举例说明使用方法):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1.0" />

    <ImageView
        android:id="@+id/ivCursor"
        android:layout_width="60dp"
        android:layout_height="5dp"
        android:scaleType="fitCenter"
        android:src="@drawable/cursor" />

    <LinearLayout
        android:id="@+id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

LinearLayout>

第二种、使用高度固定写死的方法来解决。这种情况需要使用的ViewPager里面的内容全部固定尺寸,不需要随着设备屏幕的变变化而变化,所以屏幕适配就不达标。具体使用情况可以考虑定制设备的项目,比如银行的交互式平板,设备提供商软件部分就可以这么干,因为只有这一种设备来使用程序。

第三种情况就是通过自定义ViewPager,重写其onMeasure方法。适用于ViewPager的子View高度一定,比如最大化或者固定尺寸,使用后效果如上面地图效果。但是这种方法也有局限性,不良效果如图片:

ViewPager高度自适应_第1张图片

这里ViewPager里面包裹的Fragment使用了Gridview且Gridview高度自适应,在onMeasure中返回childView的高度就只有Gridview默认的一排内容高度。

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;

public class WrapContentHeightViewPager extends ViewPager {

    public WrapContentHeightViewPager(Context context) {
        super(context);
    }

    public WrapContentHeightViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int height = 0;
        //下面遍历所有child的高度
        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) //采用最大的view的高度。
                height = h;
        }

        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

最后一种方法,使用代码动态的获取Fragment高度,然后将高度赋值给ViewPager。先上代码然后讲解:

/**
     * 设置ViewPager的自适应
     * @param childViewHeight
     */
    private void setViewPagerWrapContentHeight(int childViewHeight)
    {

        int viewPagerIndex = main.indexOfChild(viewPager);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, childViewHeight );//这里设置params的高度。
          main.removeView(viewPager);
         main.addView(viewPager, viewPagerIndex , params);//使用这个params
    }

mian代表父布局,这里要注意,如果父布局是LinearLayout或者其它布局,那么main声明的时候就是这个布局,不能声明为View或者其它布局,否则这里容易造成类型转换异常。这一句代码也很简单,就是获取ViewPager在父布局的子View中排行老几?
LinearLayout.LayoutParams这个参数根据父布局来定,切忌不要用了父布局的子类或者与父布局无关的类(即只能用父布局本身或者其父类),否则这里设置高度的时候会造成类型转换异常。这一句代码就是设置一个属性宽度最大、高度为给定的childViewHeight的一个属性params。
如果上面两句代码代码照做了,后面就没有问题了,代码执行逻辑是删除ViewPager,然后马上在之前ViewPager的位置加上ViewPager,且对其属性修改为我们刚刚设置的属性。

Tip:这里我也不明白为什么ViewPager的属性是LinearLayout.LayoutParams,因为viewgroup的属性没有带参数的方法,或许LinearLayout是ViewPager的父类或者是祖宗类,这里求知道因由的大神在评论处解释一下,谢谢!

setViewPagerWrapContentHeight这个方法在什么地方调用我就不说了,最后唠叨一点,子View高度怎么取?我是在ViewPager包裹的Fragment的OnCreateView方法里面使用handler传回来的。这里要注意,直接在OnCreateView方法方法里面取view.getHeight()只能得到0,这里正确打开姿势是这样的:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 
    {
        View layout = inflater.inflate(R.layout.emoji_icon_fragment, container, false);
        mGridView = (GridView) layout.findViewById(R.id.gview);
        EmojiFragmentAdapter adapter = new EmojiFragmentAdapter(getActivity(), bitmapData);
        mGridView.setAdapter(adapter);
        mGridView.setOnItemClickListener(this);
        mGridView.post(new Runnable() {

            @Override
            public void run() {
                handler.sendEmptyMessage(mGridView.getHeight());

            }
        });
        return layout;
    }

最后效果如图:
ViewPager高度自适应_第2张图片

参考文章:http://my.oschina.net/lifj/blog/283346

你可能感兴趣的:(实用技术)