這篇文章將為大家詳細(xì)講解有關(guān)在Android項(xiàng)目使用 WebView實(shí)現(xiàn)點(diǎn)擊圖片放大功能,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
創(chuàng)新互聯(lián)公司為您提適合企業(yè)的網(wǎng)站設(shè)計(jì)?讓您的網(wǎng)站在搜索引擎具有高度排名,讓您的網(wǎng)站具備超強(qiáng)的網(wǎng)絡(luò)競(jìng)爭(zhēng)力!結(jié)合企業(yè)自身,進(jìn)行網(wǎng)站設(shè)計(jì)及把握,最后結(jié)合企業(yè)文化和具體宗旨等,才能創(chuàng)作出一份性化解決方案。從網(wǎng)站策劃到網(wǎng)站制作、成都網(wǎng)站制作, 我們的網(wǎng)頁設(shè)計(jì)師為您提供的解決方案。
圖示:
項(xiàng)目的知識(shí)點(diǎn):
加載網(wǎng)頁后如何捕捉網(wǎng)頁中的圖片點(diǎn)擊事件;
獲取點(diǎn)擊的圖片資源后進(jìn)行圖片顯示,獲取整個(gè)頁面所有的圖片;
支持查看上下一張的圖片以及對(duì)圖片縮放顯示;
對(duì)圖片進(jìn)行保存;
其他:圖片緩存的處理(不用每次都重新加載已查看過的圖片)
項(xiàng)目代碼結(jié)構(gòu):
前期準(zhǔn)備(添加權(quán)限、依賴和混淆設(shè)置):
添加權(quán)限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
添加依賴:
compile 'com.bm.photoview:library:1.4.1' compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:support-v4:25.0.0'
混淆文件設(shè)置:
-keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; }
代碼解析:
MainActivity很簡單,代碼如下:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); contentWebView = (WebView) findViewById(R.id.webView); contentWebView.getSettings().setJavaScriptEnabled(true); contentWebView.loadUrl("http://a.mp.uc.cn/article.html?uc_param_str=frDNSnpfvecpntnwprdssskt&client=ucweb&wm_aid=c51bcf6c1553481885da371a16e33dbe&wm_id=482efebe15ed4922a1f24dc42ab654e6&pagetype=share&btifl=100"); contentWebView.addJavascriptInterface(new MJavascriptInterface(this,imageUrls), "imagelistener"); contentWebView.setWebViewClient(new MyWebViewClient()); }
很顯然,就是WebView的基本初始化操作。其中1.自定義了MJavascriptInterface的類用來實(shí)現(xiàn)js調(diào)用本地的方法;2.自定義MyWebViewClient來實(shí)現(xiàn)對(duì)WebView的監(jiān)聽管理。
MyWebViewClient代碼如下:
public class MyWebViewClient extends WebViewClient { @Override public void onPageFinished(WebView view, String url) { view.getSettings().setJavaScriptEnabled(true); super.onPageFinished(view, url); addImageClickListener(view);//待網(wǎng)頁加載完全后設(shè)置圖片點(diǎn)擊的監(jiān)聽方法 } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { view.getSettings().setJavaScriptEnabled(true); super.onPageStarted(view, url, favicon); } private void addImageClickListener(WebView webView) { webView.loadUrl("javascript:(function(){" + "var objs = document.getElementsByTagName(\"img\"); " + "for(var i=0;i<objs.length;i++) " + "{" + " objs[i].onclick=function() " + " { " + " window.imagelistener.openImage(this.src); " +//通過js代碼找到標(biāo)簽為img的代碼塊,設(shè)置點(diǎn)擊的監(jiān)聽方法與本地的openImage方法進(jìn)行連接 " } " + "}" + "})()"); } }
該類繼承自WebViewClient,在onPageFinished方法中設(shè)置addImageClickListener的監(jiān)聽方法——>當(dāng)整個(gè)WebView頁面加載完畢后,為每張圖片設(shè)置監(jiān)聽事件——>這意味著,整個(gè)頁面未加載完畢時(shí),點(diǎn)擊是無效的。
addImageClickListener的代碼實(shí)現(xiàn)也很簡單,通過js找到相應(yīng)的img標(biāo)簽,這樣就知道是圖片了,然后為這些圖片設(shè)置點(diǎn)擊監(jiān)聽事件——>每當(dāng)點(diǎn)擊時(shí)調(diào)用自定義的openImage(url)方法。這個(gè)openImage(url)方法與MJavascriptInterface中對(duì)應(yīng)的方法交相輝映,這樣就形成了js調(diào)用本地的方法。
MJavascriptInterface代碼(主要為與js對(duì)應(yīng)的本地方法的實(shí)現(xiàn)):
public class MJavascriptInterface { private Context context; private String [] imageUrls; public MJavascriptInterface(Context context,String[] imageUrls) { this.context = context; this.imageUrls = imageUrls; } @android.webkit.JavascriptInterface public void openImage(String img) { Intent intent = new Intent(); intent.putExtra("imageUrls", imageUrls); intent.putExtra("curImageUrl", img); intent.setClass(context, PhotoBrowserActivity.class); context.startActivity(intent); } }
可以看到,openImage(url)方法實(shí)現(xiàn)的邏輯是:通過傳遞當(dāng)前圖片的url與該WebView整個(gè)頁面的圖片列表(imageUrls)進(jìn)行跳轉(zhuǎn)至PhotoBrowserActivity中。PhotoBrowserActivity就是用來顯示大圖的圖片列表的頁面。
此處的疑問:imageUrls怎么獲得呢?
方式:1.服務(wù)器端直接將WebView中所有的圖片按照順序組合成String數(shù)組傳遞過來;2.或者直接將所有含img標(biāo)簽的html代碼傳遞過來,從而讓客戶端自己解析出所有圖片地址組合成的String數(shù)組。(此處是采用的第二種,具體如何解析,可以下載源碼查看。)
OK,到了這里算是完成了項(xiàng)目知識(shí)點(diǎn)的第1點(diǎn):1.加載網(wǎng)頁后如何捕捉網(wǎng)頁中的圖片點(diǎn)擊事件;
接下來就說明后面的幾點(diǎn):
2.獲取點(diǎn)擊的圖片資源后進(jìn)行圖片顯示,獲取整個(gè)頁面所有的圖片;
3.支持查看上下一張的圖片以及對(duì)圖片縮放顯示;
4.對(duì)圖片進(jìn)行保存;
其他所有的幾點(diǎn)實(shí)現(xiàn)均在PhotoBrowserActivity中,代碼如下:主要就是將圖片放進(jìn)ViewPager中進(jìn)行顯示:
mPager = (ViewPager) findViewById(R.id.pager); mPager.setPageMargin((int) (getResources().getDisplayMetrics().density * 15)); mPager.setAdapter(new PagerAdapter() { @Override public int getCount() { return imageUrls.length; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, final int position) { if (imageUrls[position] != null && !"".equals(imageUrls[position])) { final PhotoView view = new PhotoView(PhotoBrowserActivity.this); view.enable(); view.setScaleType(ImageView.ScaleType.FIT_CENTER); Glide.with(PhotoBrowserActivity.this).load(imageUrls[position]).override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).fitCenter().crossFade().listener(new RequestListener<String, GlideDrawable>() { @Override public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { if (position == curPosition) { hideLoadingAnimation(); } showErrorLoading(); return false; } @Override public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { occupyOnePosition(position); if (position == curPosition) { hideLoadingAnimation(); } return false; } }).into(view); container.addView(view); return view; } return null; } @Override public void destroyItem(ViewGroup container, int position, Object object) { releaseOnePosition(position); container.removeView((View) object); } }); curPosition = returnClickedPosition() == -1 ? 0 : returnClickedPosition(); mPager.setCurrentItem(curPosition); mPager.setTag(curPosition); if (initialedPositions[curPosition] != curPosition) {//如果當(dāng)前頁面未加載完畢,則顯示加載動(dòng)畫,反之相反; showLoadingAnimation(); } photoOrderTv.setText((curPosition + 1) + "/" + imageUrls.length);//設(shè)置頁面的編號(hào) mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (initialedPositions[position] != position) {//如果當(dāng)前頁面未加載完畢,則顯示加載動(dòng)畫,反之相反; showLoadingAnimation(); } else { hideLoadingAnimation(); } curPosition = position; photoOrderTv.setText((position + 1) + "/" + imageUrls.length);//設(shè)置頁面的編號(hào) mPager.setTag(position);//為當(dāng)前view設(shè)置tag } @Override public void onPageScrollStateChanged(int state) { } }); } private int returnClickedPosition() { if (imageUrls == null || curImageUrl == null) { return -1; } for (int i = 0; i < imageUrls.length; i++) { if (curImageUrl.equals(imageUrls[i])) { return i; } } return -1; }
1.首先通過returnClickedPosition方法來獲得用戶點(diǎn)擊的是哪一張圖片的位置并設(shè)置當(dāng)前是哪一個(gè)page——>通過遍歷當(dāng)前url與所有url來匹配獲取;
2.通過addOnPageChangeListener來實(shí)現(xiàn)對(duì)頁面滑動(dòng)事件的監(jiān)聽——>此處主要用來處理設(shè)置當(dāng)前頁面的position、動(dòng)畫、頁面序號(hào)顯示的邏輯;
3.PagerAdapter的實(shí)現(xiàn)——>每一頁內(nèi)容的初始化,主要為instantiateItem,核心代碼再次拖出來如下;
if (imageUrls[position] != null && !"".equals(imageUrls[position])) { final PhotoView view = new PhotoView(PhotoBrowserActivity.this); view.enable(); view.setScaleType(ImageView.ScaleType.FIT_CENTER); Glide.with(PhotoBrowserActivity.this).load(imageUrls[position]).override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).fitCenter().crossFade().listener(new RequestListener<String, GlideDrawable>() { @Override public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) { if (position == curPosition) { hideLoadingAnimation(); } showErrorLoading(); return false; } @Override public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { occupyOnePosition(position); if (position == curPosition) { hideLoadingAnimation(); } return false; } }).into(view); container.addView(view); return view; }
大體思路:
1.通過PhotoView來實(shí)現(xiàn)圖片的伸縮顯示;2.通過Glide來加載圖片等處理;
PhotoView是什么——>就是圖片組件,對(duì)圖片的伸縮、動(dòng)效、緩存等方面進(jìn)行了處理,點(diǎn)擊地址查看GitHub介紹>>:
Gilde是什么——>Google推薦的圖片加載庫,此處用它的理由是好用、簡單,點(diǎn)擊地址查看GitHub介紹>>:
Glide的簡化形式——>Glide.with(...).load(圖片地址).override(加載圖片的大小).listener(設(shè)置監(jiān)聽方法).into(某個(gè)一個(gè)組件,此處是PhotoView),此處使用的是原圖加載,監(jiān)聽方法中有兩個(gè)回調(diào)方法:
onException和onResourceReady,此處在onResourceReady做的處理是:當(dāng)資源加載完畢時(shí)調(diào)用——>此時(shí)取消加載動(dòng)畫的顯示。
頁面中的“頁面編號(hào)”和“保存”的組件顯示是通過寫在整個(gè)Activity的布局文件中實(shí)現(xiàn)的,而不是通過在每一頁中寫入這些組件。以下為獲取圖片資源對(duì)象的代碼:
private void savePhotoToLocal() { ViewGroup containerTemp = (ViewGroup) mPager.findViewWithTag(mPager.getCurrentItem()); if (containerTemp == null) { return; } PhotoView photoViewTemp = (PhotoView) containerTemp.getChildAt(0); if (photoViewTemp != null) { GlideBitmapDrawable glideBitmapDrawable = (GlideBitmapDrawable) photoViewTemp.getDrawable(); if (glideBitmapDrawable == null) { return; } Bitmap bitmap = glideBitmapDrawable.getBitmap(); if (bitmap == null) { return; } FileUtils.savePhoto(this, bitmap, new FileUtils.SaveResultCallback() { @Override public void onSavedSuccess() { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(PhotoBrowserActivity.this, "保存成功", Toast.LENGTH_SHORT).show(); } }); } @Override public void onSavedFailed() { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(PhotoBrowserActivity.this, "保存失敗", Toast.LENGTH_SHORT).show(); } }); } }); } }
因?yàn)橄螺d圖片需要知道當(dāng)前處于哪一頁,所以在ViewPager初始化顯示和滑動(dòng)時(shí)都給每一頁設(shè)置了tag,此時(shí)就派上了用場(chǎng)——>mPager.findViewWithTag獲取當(dāng)前page中的布局對(duì)象,然后獲得對(duì)應(yīng)的PhotoView對(duì)象,從而經(jīng)過處理最終獲取到Bitmap對(duì)象。這樣已經(jīng)很簡單了,接下來只要將Bitmap對(duì)象保存至本地即可,代碼如下:
public class FileUtils { public static void savePhoto(final Context context, final Bitmap bmp , final SaveResultCallback saveResultCallback) { new Thread(new Runnable() { @Override public void run() { File appDir = new File(Environment.getExternalStorageDirectory(), "out_photo"); if (!appDir.exists()) { appDir.mkdir(); } SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//設(shè)置以當(dāng)前時(shí)間格式為圖片名稱 String fileName = df.format(new Date()) + ".png"; File file = new File(appDir, fileName); try { FileOutputStream fos = new FileOutputStream(file); bmp.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); saveResultCallback.onSavedSuccess(); } catch (FileNotFoundException e) { saveResultCallback.onSavedFailed(); e.printStackTrace(); } catch (IOException e) { saveResultCallback.onSavedFailed(); e.printStackTrace(); } //保存圖片后發(fā)送廣播通知更新數(shù)據(jù)庫 Uri uri = Uri.fromFile(file); context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); } }).start(); } public interface SaveResultCallback{ void onSavedSuccess(); void onSavedFailed(); } }
圖片如何保存已經(jīng)如代碼所示,但要注意的是需要將已經(jīng)保存的圖片進(jìn)行廣播通知數(shù)據(jù)庫更新——>這樣立馬進(jìn)入微信或者扣扣點(diǎn)擊發(fā)送圖片,就可以看到剛剛保存的圖片。
緩存的處理:
使用Glide其中的一個(gè)好處是會(huì)將圖片默認(rèn)緩存,在需要清除緩存時(shí),只需要執(zhí)行下面的代碼(此處是放在MainActivity中,退出頁面即清除緩存):
@Override protected void onDestroy() { new Thread(new Runnable() { @Override public void run() { Glide.get(MainActivity.this).clearDiskCache();//清理磁盤緩存需要在子線程中執(zhí)行 } }).start(); Glide.get(this).clearMemory();//清理內(nèi)存緩存可以在UI主線程中進(jìn)行 super.onDestroy(); }
特別注意:
1.若項(xiàng)目配置中將targetSdkVersion 指定為22以上,則要加入動(dòng)態(tài)權(quán)限申請(qǐng)的模塊,否則在進(jìn)行保存操作時(shí)則會(huì)提示失??!
2.項(xiàng)目中暴露的js接口類:MJavascriptInterface不能混淆,其調(diào)用的方法的聲明也不能混淆,所以還要添加如下混淆設(shè)置代碼(代碼因包名而變化):
-keepclassmembers class com.example.administrator.webviewpagescannerapp.other.MJavascriptInterface{ public *; } -keepattributes *Annotation* -keepattributes *JavascriptInterface*
關(guān)于在Android項(xiàng)目使用 WebView實(shí)現(xiàn)點(diǎn)擊圖片放大功能就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
網(wǎng)站題目:在Android項(xiàng)目使用WebView實(shí)現(xiàn)點(diǎn)擊圖片放大功能
瀏覽路徑:http://aaarwkj.com/article34/gpiepe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、網(wǎng)站排名、移動(dòng)網(wǎng)站建設(shè)、App設(shè)計(jì)、自適應(yīng)網(wǎng)站、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)