長圖的展開與收起(Android)


前言:

在app的文章中,經常會夾雜着一些特別長的長圖。在閱讀的時候需要滑動很久才能看圖片下方的文字,因此對於長圖只展示圖片上面一部分,並且可以展開這個功能是很重要的。

效果:

基本思路:

利用scaleType的matrix屬性以及直接改變圖片的高度來實現圖片的收起與展開。

過程:

開始嘗試:

scaleType屬性介紹:

  1. center:保持原圖的大小,顯示在ImageView的中心。當原圖的size大於ImageView的size,超過部分裁剪處理;
  2. centerInside:以原圖完全顯示為目的,將圖片的內容完整居中顯示,通過按比例縮小原圖的size寬(高)等於或小於ImageView的寬(高)。如果原圖的size本身就小於ImageView的size,則原圖的size不作任何處理,居中顯示在ImageView;
  3. centerCrop:以填滿整個ImageView為目的,將原圖的中心對准ImageView的中心,等比例放大原圖,直到填滿ImageView為止(指的是ImageView的寬和高都要填滿),原圖超過ImageView的部分作裁剪處理;
  4. matrix:不改變原圖的大小,從ImageView的左上角開始繪制原圖,原圖超過ImageView的部分作裁剪處理;
  5. fitCenter:把原圖按比例擴大或縮小到ImageView的高度,居中顯示;
  6. fitEnd:把原圖按比例擴大(縮小)到ImageView的高度,顯示在ImageView的下部分位置;
  7. fitStart:把原圖按比例擴大(縮小)到ImageView的高度,顯示在ImageView的上部分位置;
  8. 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的優勢在於開源,開源的好處在於易於學習,容易更改。對於開源的框架,僅僅是掌握是不夠的,還需要好好的了解框架設計的一些設計模式,框架的優缺點等。

 

大家如果有什么疑問或者建議可以通過評論或者郵件的方式聯系我,歡迎大家的評論~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM