利用ViewPager显示banner的时候,一些人会直接写死ViewPager高度,比如在xml布局里面直接写成180dp。
这样的话,每个手机的宽度不同,viewpager里面内容的长宽比就不同,如果显示图片的话,里面的内容就很可能会变形。
本例在代码中动态设置ViewPager的高度,让他的高度始终和宽度呈固定比例。比如宽高比例是2:1,只要让后台配置的图片都是按2:1的话,图片显示就不会变形,体验明显提高一个档次。
本例将使用上一篇博客的代码,增加一些内容就行。上篇博客:Android ViewPager实现无限循环(2.加入小圆点,优化自动和手动滑动冲突)
布局基本没什么改变
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/rl_main"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="@+id/vp_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/ll_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:gravity="center"
android:orientation="horizontal" />
</RelativeLayout>
</RelativeLayout>
private RelativeLayout mRelativeLayout;
mRelativeLayout = (RelativeLayout) findViewById(R.id.rl_main);
/**
* 动态设置代码高度
* addOnPreDrawListener,顾名思义,在view要显示之前将会回调
*/
mRelativeLayout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mRelativeLayout.getViewTreeObserver().removeOnPreDrawListener(this);
ViewGroup.LayoutParams layoutParams = mRelativeLayout.getLayoutParams();
layoutParams.height = (int) (mRelativeLayout.getWidth() / 2);
mRelativeLayout.setLayoutParams(layoutParams);
return true;
}
});
增加的内容也非常的少
注册一个监听器,在view要显示之前会回调他。在回调的时候,把view的宽度取出来,如果你的需求是高度为宽度的一半,就除了2。
注意:removeOnPreDrawListener一定要记得调用,不然会无限次的触发onPreDraw方法。
当然了,也有其它的方法,比如你直接获取手机屏幕的宽度,再除以2也行。
但是ViewPager不一定是横向铺满全屏,可能设置有margin个5dp之类的,你就要在代码中将dp转成px,再用屏幕宽度减去它。
或者一些时候view的宽高因为其它的一些原因而要在运行时才能确定的,但又要求要固定比例的时候,用这个方法就好解决了。
以下三张截图演示ViewPager不同margin情况时候的显示
当没有margin时
当左右margin都为30dp时
当左右margin为80dp时
可以看到ViewPager的宽度比高度都是2:1
最后再给个提示,onPreDraw方法里面不只是能够把自己的LayoutParams取出来,在保证其它view已经被系统设置好宽高的时候,也可以拿其它的view的LayoutParams来操作,比如可以拿他的父view,因为在子要显示之前,父view的宽高已经确定了(至少我目前用过的都是正确的)。
比如有一个需求,横着放三个按钮(或图片),三个按钮都是正方的,就像微信朋友圈、qq空间发9张图片的时候,一行是3张正方形且铺满屏幕的图片,就可以用这样的代码来做:
mChildView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mChildView.getViewTreeObserver().removeOnPreDrawListener(this);
ViewGroup.LayoutParams layoutParams = mChildView.getLayoutParams();
// 让子view的宽度为父view的3分之1
layoutParams.height = mParentView.getWidth() / 3;
// 如果你的每两个相邻view的间隔是x大小的话,还要减去这个值
// layoutParams.height = mParentView.getWidth() / 3 - 2 * x;
mChildView.setLayoutParams(layoutParams);
return true;
}
});