前言:
在app的文章中,經常會夾雜着一些特別長的長圖。在閱讀的時候需要滑動很久才能看圖片下方的文字,因此對於長圖只展示圖片上面一部分,並且可以展開這個功能是很重要的。
效果:
基本思路:
利用scaleType的matrix屬性以及直接改變圖片的高度來實現圖片的收起與展開。
過程:
開始嘗試:
scaleType屬性介紹:
- center:保持原圖的大小,顯示在ImageView的中心。當原圖的size大於ImageView的size,超過部分裁剪處理;
- centerInside:以原圖完全顯示為目的,將圖片的內容完整居中顯示,通過按比例縮小原圖的size寬(高)等於或小於ImageView的寬(高)。如果原圖的size本身就小於ImageView的size,則原圖的size不作任何處理,居中顯示在ImageView;
- centerCrop:以填滿整個ImageView為目的,將原圖的中心對准ImageView的中心,等比例放大原圖,直到填滿ImageView為止(指的是ImageView的寬和高都要填滿),原圖超過ImageView的部分作裁剪處理;
- matrix:不改變原圖的大小,從ImageView的左上角開始繪制原圖,原圖超過ImageView的部分作裁剪處理;
- fitCenter:把原圖按比例擴大或縮小到ImageView的高度,居中顯示;
- fitEnd:把原圖按比例擴大(縮小)到ImageView的高度,顯示在ImageView的下部分位置;
- fitStart:把原圖按比例擴大(縮小)到ImageView的高度,顯示在ImageView的上部分位置;
- fitXY:把原圖按照指定的大小在View中顯示,拉伸顯示圖片,不保持原比例,填滿ImageView
根據以上屬性介紹,可以知道matrix屬性是我們要的。
基本布局:
1 <ImageView 2 android:id="@+id/iv_long_picture" 3 android:layout_width="match_parent" 4 android:layout_height="@dimen/dp_146" 5 android:layout_below="@id/tv_main_content_question" 6 android:adjustViewBounds="true" 7 android:scaleType="matrix" 8 android:src="@color/color_333333" /> 9 <TextView 10 android:id="@+id/tv_expand_collapse" 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:layout_below="@id/iv_long_picture" 14 android:layout_marginBottom="@dimen/dp_16" 15 android:layout_marginTop="@dimen/dp_10" 16 android:drawableEnd="@drawable/down_icon" 17 android:drawablePadding="@dimen/dp_7" 18 android:text="@string/expand_all" 19 android:textColor="@color/color_99" 20 android:textSize="@dimen/sp_14" 21 android:textStyle="bold" 22 android:visibility="gone" />
加載圖片:
使用Glide加載的圖片,
1 Glide.with(this) 2 .load(mainContentBean.getAccessory().get(0)) 3 .into(ivLongPicture);
點擊事件:
直接通過設置imageView的高度來實現圖片的展開與收起,
1 tvExpandCollapse.setOnClickListener(new View.OnClickListener() { 2 boolean expanded = false; 3 @Override 4 public void onClick(View v) { 5 if (expanded) { 6 // 收起 7 ViewGroup.LayoutParams params = ivLongPicture.getLayoutParams(); 8 params.width = RelativeLayout.LayoutParams.MATCH_PARENT; 9 params.height = DensityUtil.dip2px(MainContentActivity.this, 146); 10 ivLongPicture.setLayoutParams(params); 11 expanded = false; 12 tvExpandCollapse.setText(R.string.expand_all); 13 tvExpandCollapse.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.down_icon, 0); 14 scMainContent.smoothScrollTo(0, 0); 15 } else { 16 // 展開 17 ViewGroup.LayoutParams params = ivLongPicture.getLayoutParams(); 18 params.width = RelativeLayout.LayoutParams.MATCH_PARENT; 19 params.height = RelativeLayout.LayoutParams.WRAP_CONTENT; 20 ivLongPicture.setLayoutParams(params); 21 expanded = true; 22 tvExpandCollapse.setText(R.string.collapse_all); 23 tvExpandCollapse.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.upper_icon, 0); 24 } 25 } 26 });
遇到問題:
根據以上的思路以及代碼實現,普通的長圖確實能夠做到“展開”和“收起”功能。
但是對於原圖寬度超過手機寬度的圖片來說,寬度並沒有顯示完全!
對於Glide版本4.0以上,如果寬度過大,會等比例縮放至寬度等於ImageView的寬度,因此並不會有問題,但是我們的項目用Glide版本是3.7的,而且不容易升級,故此方法不可行。
解決:
查閱了Glide的文檔,了解了Glide可以在圖片下載完成后對圖片進行一些操作,操作完成之后的圖片自然就成了ImageView認為的原圖了。
因此,可以在加載之前將寬度過大的圖片等比例縮放,縮放完成后再加載到ImageView中去。
加載圖片改進:
1 Glide.with(this) 2 .load(mainContentBean.getAccessory().get(0)) 3 .asBitmap() 4 .listener(new RequestListener<String, Bitmap>() { 5 @Override 6 public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) { 7 return false; 8 } 9 10 @Override 11 public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) { 12 int imageWidth = resource.getWidth(); 13 int imageHeight = resource.getHeight(); 14 15 WindowManager manager = (WindowManager) MainContentActivity.this 16 .getSystemService(Context.WINDOW_SERVICE); 17 18 // 屏幕寬度減去margin值 19 int width = manager.getDefaultDisplay().getWidth() - DensityUtil.dip2px(MainContentActivity.this, 32); 20 21 float scaleRate = width * 1.0f / imageWidth; 22 23 //設置matrix 24 Matrix matrix = new Matrix(); 25 26 //設置放縮比例 27 matrix.setScale(scaleRate, scaleRate); 28 29 ivLongPicture.setImageMatrix(matrix); 30 31 if (imageHeight * scaleRate > DensityUtil.dip2px(MainContentActivity.this, 146)) { 32 tvExpandCollapse.setVisibility(View.VISIBLE); 33 } else { 34 tvExpandCollapse.setVisibility(View.GONE); 35 } 36 37 return false; 38 } 39 }) 40 .into(ivLongPicture);
總結:
- ImageView的scaleType屬性的各個屬性值需要了解;
- Glide版本之間的差異需要了解;
- ImageView如何根據scaleType進行圖片切割的需要了解(之后有時間閱讀源碼);
- Glide是一個龐然大物,也是一個很值得學習的框架,需要熟悉掌握(之后有時間閱讀源碼)
Android的優勢在於開源,開源的好處在於易於學習,容易更改。對於開源的框架,僅僅是掌握是不夠的,還需要好好的了解框架設計的一些設計模式,框架的優缺點等。
大家如果有什么疑問或者建議可以通過評論或者郵件的方式聯系我,歡迎大家的評論~