在android開發(fā)的過程當中,有時候會遇到這樣的需求,須要顯示很大的圖片,而且還不容許壓縮。好比顯示:世界地圖、微博長圖等,那么如何完成這個需求呢?
首先咱們分析一下,圖片很是大,考慮到內存的狀況,咱們不能一次將整個圖片加載到內存中,由于這樣會OOM,而后圖片的寬或者高超出了手機屏幕的尺寸,要想顯示整張沒有壓縮過的圖片,咱們只能每次加載圖片的局部,而后監(jiān)聽控件的滑動事件,獲得滑動的方向和距離,來從新加載圖片的局部,這樣咱們就能夠利用拖動的方式顯示整張圖片了
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,能夠用來指定圖片的解碼格式,取樣率等
了解了以上內容后,咱們就能夠開發(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 源碼解析+核心筆記+面試真題》
一、加載高清大圖須要用到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源碼對三者的定義可以看出如下一個樹形繼承關系:
Node(節(jié)點)
從上述繼承關系上可以明確一點,文檔中的所有內容都可以看做是一個節(jié)點。節(jié)點有很多種類型:屬性節(jié)點(Attribute)、注釋節(jié)點(Note)、文本節(jié)點(Text)、元素節(jié)點(Element)等,通常所說的節(jié)點是這些多種節(jié)點的統(tǒng)稱。
Element(元素)
相比節(jié)點而言,元素則是一個更小范圍的定義。元素繼承于節(jié)點,是節(jié)點的子集,所以一個元素也是一個節(jié)點,節(jié)點擁有的公有屬性和方法在元素中也能使用。
Document(文檔)
文檔繼承于元素,指整個HTML文檔的源碼內容,通過 System.out.println(document.toString());
即可在控制臺打印出網頁源碼內容。
相互轉換
基于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(); } } }解析結果:
*請認真填寫需求信息,我們會在24小時內與您取得聯(lián)系。