整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Android 開發(fā)中如何利用拖動的方式顯示高清圖片

          Android 開發(fā)中如何利用拖動的方式顯示高清圖片?

          、概述html

          在android開發(fā)的過程當中,有時候會遇到這樣的需求,須要顯示很大的圖片,而且還不容許壓縮。好比顯示:世界地圖、微博長圖等,那么如何完成這個需求呢?

          首先咱們分析一下,圖片很是大,考慮到內存的狀況,咱們不能一次將整個圖片加載到內存中,由于這樣會OOM,而后圖片的寬或者高超出了手機屏幕的尺寸,要想顯示整張沒有壓縮過的圖片,咱們只能每次加載圖片的局部,而后監(jiān)聽控件的滑動事件,獲得滑動的方向和距離,來從新加載圖片的局部,這樣咱們就能夠利用拖動的方式顯示整張圖片了

          2、BitmapRegionDecoderandroid

          android加載圖片的局部須要用到BitmapRegionDecoder類,BitmapRegionDecoder類主要用來加載圖片的某一塊矩形區(qū)域,若是你想顯示圖片的某一塊矩形區(qū)域,那么這個類很是合適,下面來看一下它的用法:git

          BitmapRegionDecoder提供了一系列的newInstance方法來構造實例,支持傳入文件路徑,文件描述符,文件的數據流等,以下:

          public static BitmapRegionDecoder newInstance(InputStream is, boolean isShareable)
              public static BitmapRegionDecoder newInstance(String pathName, boolean isShareable)
              public static BitmapRegionDecoder newInstance(FileDescriptor fd, boolean isShareable)
              public static BitmapRegionDecoder newInstance(byte[] data, int offset, int length, boolean isShareable)

          利用圖片構造BitmapRegionDecoder對象后,咱們能夠調用它的decodeRegion方法來加載圖片中的指定區(qū)域,以下:

          Bitmap bitmap=mBitmapRegionDecoder.decodeRegion(mRect, mOptions);

          第一個參數指定加載區(qū)域,第二個參數是BitmapFactory.options,能夠用來指定圖片的解碼格式,取樣率等

          3、開發(fā)代碼ide

          了解了以上內容后,咱們就能夠開發(fā)加載高清大圖的控件了,下面是自定義的代碼,注釋很詳細:

          package com.liunian.androidbasic.addbigimage.view;
          
          import android.content.Context;
          import android.graphics.Bitmap;
          import android.graphics.BitmapFactory;
          import android.graphics.BitmapRegionDecoder;
          import android.graphics.Canvas;
          import android.graphics.Rect;
          import android.support.annotation.Nullable;
          import android.util.AttributeSet;
          import android.util.Log;
          import android.view.MotionEvent;
          import android.view.View;
          
          import com.liunian.androidbasic.utils.CloseUtils;
          
          import java.io.IOException;
          import java.io.InputStream;
          
          /**
           * Created by dell on 2018/4/12.
           */
          
          public class BigImageView extends View {
              private Context mContext;
              private BitmapRegionDecoder mBitmapRegionDecoder;
              private Rect mRect=new Rect();
              private int mImageWidth=0;
              private int mImageHeight=0;
              private BitmapFactory.Options mOptions;
          
              public BigImageView(Context context) {
                  this(context, null);
              }
          
              public BigImageView(Context context, @Nullable AttributeSet attrs) {
                  this(context, attrs, 0);
              }
          
              public BigImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                  super(context, attrs, defStyleAttr);
                  mContext=context;
                  init();
              }
          
              private void init() {
                  // 指定圖片的解碼格式為RGB_565
                  mOptions=new BitmapFactory.Options();
                  mOptions.inPreferredConfig=Bitmap.Config.RGB_565;
              }
          
              // 傳入須要加載的圖片的inputStream
              public void setInputStream(InputStream inputStream) {
                  try {
                      // 先得到圖片的寬高(在華為的手機上若是在構造BitmapRegionDecoder對象后得到圖片寬高將獲取失敗)
                      BitmapFactory.Options tmpOptions=new BitmapFactory.Options();
                      tmpOptions.inJustDecodeBounds=true; // 將inJuestDecodeBounds設為true,這樣BitmapFactory只會解析圖片的原始寬/高信息,并不會真正的去加載圖片
                      BitmapFactory.decodeStream(inputStream, null, tmpOptions); // 解析圖片得到圖片的寬高
                      mImageWidth=tmpOptions.outWidth; // 保存圖片的寬
                      mImageHeight=tmpOptions.outHeight; // 保存圖片的搞
          
                      // 根據圖片對應的BitmapRegionDecoder對象
                      mBitmapRegionDecoder=BitmapRegionDecoder.newInstance(inputStream, false);
                      requestLayout(); // 這里調用requestLayout方法,請求從新布局,觸發(fā)調用控件的onMeasure,初始化加載區(qū)域
                  } catch (IOException e) {
                      e.printStackTrace();
                  } finally {
                      CloseUtils.closeIO(inputStream);
                  }
              }
          
              // 保存上一次事件的發(fā)生位置
              float lastEventX=0;
              float lastEventY=0;
              // 保存當前事件的發(fā)生位置
              float eventX=0;
              float eventY=0;
          
              // 重載控件的onTouchEvent方法,監(jiān)控控件的事件
              @Override
              public boolean onTouchEvent(MotionEvent event) {
                  // 這里只處理了控件的Move事件,若是有更復雜需求,好比說根據手勢縮放圖片,能夠將事件交由給GestureDetector處理
                  if (event !=null) {
                      // 獲得當前事件的發(fā)生位置
                      eventX=event.getX();
                      eventY=event.getY();
                      switch (event.getAction()) {
                          case MotionEvent.ACTION_MOVE: // move事件
                              // 根據當前事件的發(fā)生位置和上一次事件的發(fā)生位置計算出用戶的滑動距離,并調整圖片的加載區(qū)域
                              move((int) (lastEventX - eventX), (int) (lastEventY - eventY));
                              break;
                      }
                      // 保存上一次事件的發(fā)生位置
                      lastEventX=event.getX();
                      lastEventY=event.getY();
                  }
                  return true;
              }
          
              // 根據滑動距離調整圖片的加載區(qū)域
              private void move(int moveX, int moveY) {
                  // 只有當圖片的高大于控件的高,控件縱向顯示不下圖片時,才須要調整加載區(qū)域的上下位置
                  if (mImageHeight > getHeight()) {
                      mRect.top=mRect.top + moveY;
                      mRect.bottom=mRect.top + getHeight();
                  }
                  // 只有當圖片的寬大于控件的寬,控件橫向顯示不下圖片時,才須要調整加載區(qū)域的左右位置
                  if (mImageWidth > getWidth()) {
                      mRect.left=mRect.left + moveX;
                      mRect.right=mRect.left + getWidth();
                  }
                  invalidate();
              }
          
              // 重寫onDraw方法,繪制圖片的局部
              @Override
              protected void onDraw(Canvas canvas) {
                  super.onDraw(canvas);
                  if (mBitmapRegionDecoder !=null) {
                      // 檢查繪制區(qū)域的寬高,以避免繪制到圖片覺得的區(qū)域
                      checkHeight();
                      checkWidth();
                      // 加載圖片的指定區(qū)域
                      Bitmap bitmap=mBitmapRegionDecoder.decodeRegion(mRect, mOptions);
                      Log.i("liunianprint:", "onDraw" + mRect.top + " " + mRect.left + " " + mRect.bottom + " " + mRect.right);
                      // 繪制圖片的局部到控件上
                      if (bitmap !=null) {
                          canvas.drawBitmap(bitmap, 0, 0, null);
                      }
                  }
              }
          
              /**
               * 檢查加載區(qū)域是否超出圖片范圍
               */
              private void checkWidth() {
                  // 只有當圖片的寬大于控件的寬,控件橫向顯示不下圖片時,才須要調整加載區(qū)域的左右位置
                  if (mImageWidth > getWidth()) {
                      if (mRect.right > mImageWidth) {
                          mRect.right=mImageWidth;
                          mRect.left=mRect.right - getWidth();
                      }
          
                      if (mRect.left < 0) {
                          mRect.left=0;
                          mRect.right=getWidth();
                      }
                  } else {
                      mRect.left=(mImageWidth - getWidth()) / 2;
                      mRect.right=mRect.left + getWidth();
                  }
              }
          
              /**
               * 檢查加載區(qū)域是否超出圖片范圍
               */
              private void checkHeight() {
                  // 只有當圖片的高大于控件的高,控件縱向顯示不下圖片時,才須要調整加載區(qū)域的上下位置
                  if (mImageHeight > getHeight()) {
                      if (mRect.bottom > mImageHeight) {
                          mRect.bottom=mImageHeight;
                          mRect.top=mRect.bottom - getHeight();
                      }
                      if (mRect.top < 0) {
                          mRect.top=0;
                          mRect.bottom=getHeight();
                      }
                  } else {
                      mRect.top=(mImageHeight - getHeight()) / 2;
                      mRect.bottom=mRect.top + getHeight();
                  }
              }
          
              /**
               * 重寫測量控件大小的方法,初始化圖片的加載區(qū)域
               *
               * @param widthMeasureSpec
               * @param heightMeasureSpec
               */
              @Override
              protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          
                  // 獲得控件的寬高
                  int width=getMeasuredWidth(); // 使用getMeasuredWidth,不要使用getWidth方法,getWidth可能為0
                  int height=getMeasuredHeight(); // getMeasuredHeight,不要使用getHeight方法,getWidth可能為0
          
                  // 初始化圖片的加載區(qū)域為圖片的中心,能夠自行根據需求調整
                  mRect.left=(mImageWidth - width) / 2;
                  mRect.right=mRect.left + width;
                  mRect.top=(mImageHeight - height) / 2;
                  mRect.bottom=mRect.top + height;
              }
          }

          使用方法

          <?xml version="1.0" encoding="utf-8"?>
          <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context="com.liunian.androidbasic.MainActivity">
              <com.liunian.androidbasic.addbigimage.view.BigImageView
                  android:id="@+id/big_image_view"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
          </RelativeLayout>
          mBigImageView=(BigImageView) findViewById(R.id.big_image_view);
                  try {
                      mBigImageView.setInputStream(getAssets().open("ditu.jpg"));
                  } catch (IOException e) {
                      e.printStackTrace();
                  }

          使用效果以下:

          滑動控件能夠加載地圖的其余區(qū)域

          有需要文章中完整代碼的同學 現(xiàn)在私信發(fā)送 “底層源碼” 即可免費獲取

          現(xiàn)在私信發(fā)送 “進階” 還可以獲取《更多 Android 源碼解析+核心筆記+面試真題》

          4、總結

          一、加載高清大圖須要用到BitmapRegionDecoder類,這個類能夠加載圖片的指定區(qū)域;

          二、因為圖片超出了控件的大小,咱們須要監(jiān)聽控件的滑動事件,實現(xiàn)能夠經過拖動的方式顯示整張圖片;

          三、加載圖片的指定區(qū)域,得到對應的Bitmap,而后經過重寫onDraw方法將Bitmap繪制到控件上

          應用名稱】:屏幕翻譯_3_1_2285_解鎖會員版
          【應用版本】:3.1.2
          【應用大小】:318.65MB
          【適用平臺】:Android
          【軟件標簽】:#屏幕翻譯

          軟件簡介:
          屏幕翻譯是專為Android用戶設計的實時翻譯應用,旨在解決游戲、視頻、聊天和網頁瀏覽中遇到的語言障礙。此應用支持多語言功能,能夠實時翻譯手機屏幕上顯示的文字,確保翻譯結果既快速又精準。

          主要功能:
          實時翻譯:能立即翻譯屏幕上出現(xiàn)的文字,無需等待。
          多場景適用:無論是在游戲中獲取任務信息,觀看外語視頻,還是瀏覽外文網站,都能輕松應對。
          用戶友好設計:簡潔的操作界面,使得任何用戶都能快速開始使用。
          高速精準:采用先進的翻譯技術,提供快速而準確的翻譯服務,滿足日常和專業(yè)的翻譯需求。

          屏幕翻譯v3.1.2解鎖會員版為需要跨語言交流的用戶提供了一個全面的翻譯工具,是理想的多語言交流助手。立即體驗,讓語言交流無界限。



          轉載網站:http://kskhk.cn/news/755.html


          【免責聲明】

          本站資源僅用于個人學習交流使用,不得用于商業(yè)用途,請在下載24小時內刪除。如有侵權請及時與我們聯(lián)系處理。感謝大家的支持~

          soup簡介

          jsoup 是一款Java的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數據。





          官網地址:
          http://jsoup.org/


          在官網中下載 jsou-1.8.3.jar 文件,添加到自己項目的lib庫中,便可使用Jsoup提供的api,官網中也提供了一套使用指南(Cookbook),便于開發(fā)者借鑒。
          Jsoup解析HTML得到一個Document對象,通過操作Document的屬性來獲取HTML頁面內容,所以,在開始之前,先介紹一下XML中Node、Element、Document等這些相關概念的區(qū)別,防止因概念混淆而導致亂用錯用。

          相關概念

          • Jsoup中的繼承關系

            public abstract class Node implements Cloneable
            public class Element extends Node
            public class Document extends Element

            從Jsoup源碼對三者的定義可以看出如下一個樹形繼承關系:

          1. Node(節(jié)點)
            從上述繼承關系上可以明確一點,文檔中的所有內容都可以看做是一個節(jié)點。節(jié)點有很多種類型:屬性節(jié)點(Attribute)、注釋節(jié)點(Note)、文本節(jié)點(Text)、元素節(jié)點(Element)等,通常所說的節(jié)點是這些多種節(jié)點的統(tǒng)稱。

          2. Element(元素)
            相比節(jié)點而言,元素則是一個更小范圍的定義。元素繼承于節(jié)點,是節(jié)點的子集,所以一個元素也是一個節(jié)點,節(jié)點擁有的公有屬性和方法在元素中也能使用。

          3. Document(文檔)
            文檔繼承于元素,指整個HTML文檔的源碼內容,通過 System.out.println(document.toString()); 即可在控制臺打印出網頁源碼內容。

          4. 相互轉換
            基于Node、Element和Document之間的“纏綿”關系,可以利用各個類中提供的方法適當轉換獲取所需對象,以供使用。

            使用案例

            Jsoup解析Html獲取Document對象的方式分為三類:在線Url、Html文本字符串、文件,對應API如下

          • connect(String url)

          • parse(String html)

          • parse(File in, String charsetName)


            在獲取到Document對象之后,可以結合HTML源碼,利用Jsoup提供的api通過class、tag、id、attribute等相關屬性獲取對應Element,進而得到所需要的網頁內容。
            下面以Jsoup的官網Cookbook頁面為例,解析并獲取頁面目錄內容。
            網頁內容:





            網頁源碼:

            <!DOCTYPE html>
            <!-- saved from url=(0031)http://www.open-open.com/jsoup/ -->
            <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>jsoup開發(fā)指南,jsoup中文使用手冊,jsoup中文文檔</title>
            <meta name="keywords" content="jsoup開發(fā)指南,jsoup中文使用手冊,jsoup中文文檔,jsoup java html解析器">
            <meta name="description" content="jsoup Cookbook中文版 - 由http://www.open-open.com翻譯整理"><link rel="stylesheet" type="text/css" href="./jsoup開發(fā)指南,jsoup中文使用手冊,jsoup中文文檔_files/style.css">
            </head><body class="n1-cookbook">
            <div class="wrap">
            <div class="header">
            <div class="nav-sections">
            <ul>
            <li class="n1-home">
            <h4><a >jsoup</a></h4></li>
            <li class="n1-news"><a >新聞</a></li>
            <li class="n1-bugs"><a >bugs</a></li>
            <li class="n1-discussion"><a >討論</a></li>
            <li class="n1-download"><a >下載</a></li>
            <li class="n1-api"><a >api參考</a></li>
            <li class="n1-cookbook"><a >Cookbook</a></li></ul>
            </div></div>
            <div class="breadcrumb"><a >jsoup</a> <span class="seperator">?</span> cookbook </div>
            <div class="content">
            <div class="col1">
            <h1>jsoup Cookbook(中文版)</h1>
            <div class="toc">
            <h3>入門</h3>
            <ol start="1">
            <li><a >解析和遍歷一個html文檔</a></li>
            </ol>
            <h3>輸入</h3>
            <ol start="2">
            <li><a >解析一個html字符串</a></li>
            <li><a >解析一個body片斷</a></li>
            <li><a >根據一個url加載Document對象</a></li>
            <li><a >根據一個文件加載Document對象</a></li>
            </ol>
            <h3>數據抽取</h3>
            <ol start="6">
            <li><a >使用dom方法來遍歷一個Document對象</a></li>
            <li><a >使用選擇器語法來查找元素</a></li>
            <li><a >從元素集合抽取屬性、文本和html內容</a></li>
            <li><a >URL處理</a></li>
            <li><a >程序示例:獲取所有鏈接</a></li>
            </ol>
            <h3>數據修改</h3>
            <ol start="11">
            <li><a >設置屬性值</a></li>
            <li><a >設置元素的html內容</a></li>
            <li><a >設置元素的文本內容</a></li>
            </ol>
            <h3> html清理</h3>
            <ol start="14">
            <li><a >消除不受信任的html (來防止xss攻擊)</a></li>
            </ol><script src="./jsoup開發(fā)指南,jsoup中文使用手冊,jsoup中文文檔_files/ca-pub-7963911354665843.js"></script><script type="text/javascript"><!--
            google_ad_client="pub-7963911354665843";
            /* 728x90, 創(chuàng)建于 11-1-27 */
            google_ad_slot="5890482646";
            google_ad_width=728;
            google_ad_height=90;
            //-->
            </script>
            <script type="text/javascript" src="./jsoup開發(fā)指南,jsoup中文使用手冊,jsoup中文文檔_files/show_ads.js">
            </script><ins id="aswift_0_expand" style="display:inline-table;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px;background-color:transparent"><ins id="aswift_0_anchor" style="display:block;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px;background-color:transparent"><iframe width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&&s.handlers,h=H&&H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&&d&&(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;"></iframe></ins></ins></div></div>
            <div class="col2"></div></div>
            <div class="footer"><b>jsoup</b> html parser: copyright ? 2009 - 2011 <a  rel="me"><b>jonathan hedley</b></a> </div></div>
            </body></html>
            Jsoup解析:
            import java.io.IOException;
            import java.text.ParseException;
            import org.jsoup.Jsoup;
            import org.jsoup.nodes.Document;
            import org.jsoup.select.Elements;
            /**
            * @author 亦楓
            * @created_time 2016年1月5日
            * @file_user_todo Java測試類
            * @blog http://www.jianshu.com/users/1c40186e3248/latest_articles
            */
            public class JavaTest {
            /**
            * 入口函數
            * @param args
            * @throws ParseException
            */
            public static void main(String[] args) throws ParseException {
            try {
            //解析Url獲取Document對象
            Document document=Jsoup.connect("http://www.open-open.com/jsoup/").get();
            //獲取網頁源碼文本內容
            System.out.println(document.toString());
            //獲取指定class的內容指定tag的元素
            Elements liElements=document.getElementsByClass("content").get(0).getElementsByTag("li");
            for (int i=0; i < liElements.size(); i++) {
            System.out.println(i + ". " + liElements.get(i).text());
            }
            } catch (IOException e) {
            System.out.println("解析出錯!");
            e.printStackTrace();
            }
            }
            }
            解析結果:

          主站蜘蛛池模板: 国产一区二区三区亚洲综合 | 少妇一夜三次一区二区| 精品成人av一区二区三区| 国产福利电影一区二区三区,日韩伦理电影在线福 | 国产a∨精品一区二区三区不卡| 午夜DV内射一区区| 无码人妻精品一区二区三区久久| 精品人妻一区二区三区四区在线 | 伊人久久大香线蕉AV一区二区| 亚洲图片一区二区| 精品爆乳一区二区三区无码av| 亚洲国产韩国一区二区| 国产SUV精品一区二区88| 成人国内精品久久久久一区| 免费在线视频一区| 久久精品免费一区二区| 亚洲日韩国产精品第一页一区| 国产在线一区二区三区av| 在线观看国产一区亚洲bd| 国产精品主播一区二区| 人妻体体内射精一区二区| 亚洲一区精品中文字幕| 亚洲av乱码一区二区三区| 男人的天堂亚洲一区二区三区| 台湾无码一区二区| 亚洲av无码一区二区乱子伦as| 丝袜无码一区二区三区| 国产免费av一区二区三区| 日本一区二区三区在线网| 日韩免费一区二区三区| 亚洲综合一区国产精品| 国产成人精品日本亚洲专一区| 亚洲一本一道一区二区三区| 三上悠亚一区二区观看| 真实国产乱子伦精品一区二区三区 | 午夜福利av无码一区二区| 日本精品一区二区三区在线视频| 国产一区二区不卡老阿姨| 视频一区二区精品的福利| 国产精品综合一区二区| 国产伦精品一区二区三区无广告|