1. 程式人生 > >Android 根據圖片高度動態設定ViewPager高度

Android 根據圖片高度動態設定ViewPager高度

有圖片的地方,就有需求。
為什麼一個App有那麼多的Banner,這裡就不吐槽了。我們還是直接進主題,如何讓ViewPager自適應圖片的高度。
效果如下:
這裡寫圖片描述
如何去改變ViewPager的高度,都知道用setLayoutParams,我們不清楚的是,在什麼時候給Viewpager設定。聰明的孩子馬上就想到,我們用ViewPager的時候,有一個OnPageChangeListener是用來監聽viewpager滑動翻頁的。

@Override
    public void onPageScrolled(int position, float positionOffset, int
positionOffsetPixels) { } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { }

在這三個方法中,只有onPageScrolled是滑動過程一直呼叫的,而且剛好有個positionOffset是代表Viewpager的偏移量。這裡我們不用OnPageSelected,光看Log日誌,我們就知道它只有在頁面position位置改變才會被呼叫,不滿足Viewpager高度慢慢變化這個動態過程。
那麼在onPageScrolled裡我們要如何操作呢。為了更通俗的解決這個初中數學問題,我決定拿出我封印多年的截圖塗鴉技術,look
這裡寫圖片描述


從圖片1到圖片2,我們可以看成是圖片1高度慢慢變大的過程,高度增量y =(img1高度-img2高度)的絕對值。看到這裡,相信很多小夥伴就知道怎麼算了,舉個例子,如果你已經滑動了20%頁面,那你滑動距離就是0.2x0.2x/高度增量h=x/y ,算出來的h就是圖片1增長的高度了,而我們是要給ViewPager setLayoutParams,需要拿到的具體高度就是 圖片1高度+h了。
具體程式碼如下:

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import
android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.ImageViewTarget; import com.bumptech.glide.request.target.SimpleTarget; public class MainActivity extends AppCompatActivity { private ViewPager mViewpager; private String[] urls = { "http://f.hiphotos.baidu.com/zhidao/pic/item/3b87e950352ac65cbdbeff61fcf2b21193138a6d.jpg" , "http://c.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a1359aa88b6f103918fa0ecc030.jpg", "http://c.hiphotos.baidu.com/zhidao/pic/item/faf2b2119313b07e6077d3bc0ad7912396dd8cb8.jpg" }; private int[] imgheights; private int screenWidth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); screenWidth=ScreenUtil.getScreenWidth(this); initView(); } public void initView() { mViewpager = (ViewPager) findViewById(R.id.viewpager); // mViewpager.setOffscreenPageLimit(3); Glide.with(this).load(urls[0]).asBitmap().into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { float scale = (float) resource.getHeight() / resource.getWidth(); int defaultheight = (int) (scale * screenWidth); initViewPager(defaultheight); } }); } //獲取第一張圖片高度後,給viewpager設定adapter private void initViewPager(final int defaultheight) { mViewpager.setAdapter(new PagerAdapter() { @Override public int getCount() { if (imgheights == null || imgheights.length != urls.length){ imgheights = null; imgheights = new int[urls.length];} return urls.length; } @Override public Object instantiateItem(ViewGroup container, final int position) { final ImageView imageView = new ImageView(MainActivity.this); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); Glide.with(getApplicationContext()).load(urls[position]).asBitmap().into(new ImageViewTarget<Bitmap>(imageView) { @Override protected void setResource(Bitmap loadedImage) { if(loadedImage!=null) { float scale = (float) loadedImage.getHeight() / loadedImage.getWidth(); imgheights[position] = (int) (scale * screenWidth); imageView.setImageBitmap(loadedImage); }else { Toast.makeText(MainActivity.this, "圖片為空", Toast.LENGTH_LONG).show(); } } }); container.addView(imageView); return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } }); mViewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (position == imgheights.length - 1) { return; } //計算ViewPager現在應該的高度,heights[]表示頁面高度的陣列。 int height = (int) ((imgheights[position] == 0 ? defaultheight : imgheights[position]) * (1 - positionOffset) + (imgheights[position + 1] == 0 ? defaultheight : imgheights[position + 1]) * positionOffset); //為ViewPager設定高度 ViewGroup.LayoutParams params = mViewpager.getLayoutParams(); params.height = height; mViewpager.setLayoutParams(params); } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }); } }

還有一個需要注意的地方就是,我們平時載入網路圖片的時候,是需要時間載入的,我們必須加載出viewpager的高度(第一張圖片的高度)之後,才能去給viewpager設定adapter。我覺得比較好的方案是,在上個頁面獲取這個預設高度,或者讓伺服器返回第一張圖片的寬高,我們就可以算出viewpager的預設高度了。而我在demo中是先網路請求出第一張圖片的bitmap算出將要顯示的高度defaultheight,才去setAdapter:
這裡寫圖片描述
不提倡專案裡用這種做法,除非後臺完全不搭理你的要求~
PS:
程式碼傳送門http://download.csdn.net/detail/qq_31390699/9715350
PPS: = =因為以前用Eclipse,轉Studio都是自己摸索的,沒注意上傳資源只需要app這個資料夾,其他資料夾都可以刪除,所以程式碼的壓縮包搞得好大…下次改進~