1. 程式人生 > >ScrollView巢狀ViewPager自適應高度,圖片高度小的會顯示空白

ScrollView巢狀ViewPager自適應高度,圖片高度小的會顯示空白

最近專案中遇到ScrollView巢狀ViewPager,ViewPager中存放的是ImagView,要求是,ImagView高度不定,接下來就是各種方法嘗試,比較普遍的方式就是自定義一個viewpager。程式碼如下:

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

/**
 * 自動適應高度的ViewPager
 * @author
 *
 */
public class CustomViewPager extends ViewPager {

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

   public CustomViewPager(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, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
         int h = child.getMeasuredHeight();
         if (h > height)
            height = h;
      }

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

      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
   }
}
可以看出,此自定義ViewPager的高度是根據子view的高度來決定的, if (h > height)
            height = h;迴圈過後,就是將高度最大的子view的高度賦值給ViewPager的高度,這樣可以解決ViewPager不顯示的問題,但是潛在的問題是,當view的高度小的時候,ViewPager中的view下面會留白。
            不符合需求,而且不美觀。
            接下來在csdn中找到如下自定義的ViewPager:
方式一:ViewPager中放的是View
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * Created by lzq 
 */
public class SignViewPager extends ViewPager{
    private int current;
    private int height = 0;
    /**
     * 儲存position與對於的View
     */
    private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();

    private boolean scrollble = true;

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

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


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mChildrenViews.size() > current) {
            View child = mChildrenViews.get(current);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            height = child.getMeasuredHeight();
        }

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

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void resetHeight(int current) {
        this.current = current;
        if (mChildrenViews.size() > current) {

            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
            if (layoutParams == null) {
                layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
            } else {
                layoutParams.height = height;
            }
            setLayoutParams(layoutParams);
        }
    }
    /**
     * 儲存position與對於的View
     */
    public void setObjectForPosition(View view, int position)
    {
        mChildrenViews.put(position, view);
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!scrollble) {
            return true;
        }
        return super.onTouchEvent(ev);
    }


    public boolean isScrollble() {
        return scrollble;
    }

    public void setScrollble(boolean scrollble) {
        this.scrollble = scrollble;
    }

}
接下來需要注意的是:
		條件1:
		pager.setOffscreenPageLimit(3);
		條件2:
		pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
			@Override
			public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

			}
			@Override
			public void onPageSelected(int position) {
				pager.resetHeight(position);//重置viewpager的高度
				//num.setText((position+1)+"/"+imageInfo.size());
				pager.resetHeight(0);  
 }
@Overridepublic void onPageScrollStateChanged(int state) {}});
條件3:在instantiateItem()方法中pager.setObjectForPosition(view1,position);setObjectForPosition方法是為了呼叫存放你的view和他對應的position這樣就完美解決了。
方式二:ViewPager中放Fragment
條件1:
setObjectForPosition()方法中是為了呼叫存放你的view和他對應的position,這個是參考了鴻洋大神的一篇文章,連結:http://blog.csdn.net/lmj623565791/article/details/38026503
,為了防止預載入導致的高度不匹配,我們加自身的fragment和position對應起來放在linkedmap裡。  
好了,剩下的就是呼叫vp.setObjectForPosition(view,1); 
setObjectForPosition()這個方法了,請看我的一個SecurityInfoFragment
public SecurityInfoFragment(CustomViewpager pager) {  //CustomViewpager 的引用傳到Fragment中,用來呼叫
        this.pager = pager;  
    }  
  
  
    @Nullable  
    @Override  
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
        View view = inflater.inflate(R.layout.fg_sc_filght_info, null);  
        
	pager.setObjectForPosition(view,1);  
        return view;  
    } 
條件2:
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {  
            @Override  
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  
            }  
  
            @Override  
            public void onPageSelected(int position) {  
                activityScdetailsBottomVp.resetHeight(position);  
            }  
            @Override  
            public void onPageScrollStateChanged(int state) {  
  
            }  
        });  
        pager.resetHeight(0);  //預設設定第0個頁面或view高度,當滑動的時候setOnPageChangeListener
呼叫activityScdetailsBottomVp.resetHeight(position); }