我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android实现点击WebView界面中图片滑动浏览与保存图片功能

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android实现点击WebView界面中图片滑动浏览与保存图片功能

一、实现需求

最近在公司的项目中遇到需求如下:

1、点击 WebView 页面的图片实现开启查看图片模式,即可以显示点击的图片,然后滑动显示下一张图片。

3、长按 WebView 页面图片弹出对话框可以选择保存长按的图片到本地相册。

拿到这个需求笔者第一反应是没做过 WebView 相关的交互,甚至分不清这个需求是否需要服务端配合完成 Java 与 JavaScript 的互相调用,一脸茫然。

遇到这种情况笔者的解决思路一般分两个方向:

1、找一个比较出名的客户端有类似功能的,然后 Google 搜索,仿 XXXX,先粗略看一下有没有现成的 Demo 可以参考,比如我这个需要,先去搜索一下 ”Android 仿微信朋友圈浏览图片效果“ (这个搜索关键字很关键啊),可是笔者没找到符合该需要的 Demo。

2、在第一个方案不好使的情况下,我们没有了参考,那么咱们就得自己思考这个大概实现思路,然后把这个需求进行拆分,逐一击破。所以思考大概如下:

     (1)要想展示图片那么就得先拿到图片,要拿到图片只有两种可能,第一种可能是 WebView 本身缓存了图片,我们去缓存中读取图片进行显示,可是想一下,咱们浏览微博看图的时候如果没有网,这时候去点击图片那么图片是加载不出来的,所以这种可能否定了;所以只有第二种可能就是点击图片的时候拿到该图片对应的 URL 网址,然后咱们自己去网络加载图片进行显示,所以这个点我们 Get 到了。

     (2)要滑动图片进行显示下一张,那么就需要我们能拿到所有要显示的图片的 URL ,然后放到一个数组里面,每次滑动就进行加载一张图片,那么也就是我们一次性拿到所有 WebView 包含图片的 URL,这个就不是在点击图片的时候去获取,而是在 WebView 加载完成后获取到,这怎么能拿到?再想一下,WebView 进行加载显示的时候其实是加载 HTML(比如 Assets 目录中的文件)文本的字符串,然后进行渲染处理显示出来,所以 HTML文本文件里面包含了我们想要的图片网址,大家看一下下面这张截图就是一个带图片的 WebView 对应加载的 HTML文本文件部分截图,

其中标签 class="lazy" data-src 对象的内容就是我们想要的图片 URL,所以到这里我们就有了思路,我们先拿到 WebView 加载的 HTML 内容,然后在从 HTML 里面提取我要想要的 URL。

     (3)现在我们能拿到所有图片对应的 URL,那么滑动图片显示下一张就简单了,我们直接用一个 ViewPager 来实现滑动加载图片即可。

总结要实现这个需要我们需要做的工作有:

拿到 WebView 加载的 HTML 文本。 从 HTML 文本中提取所有图片对应的 URL。 处理 WebView 中图片的点击和长按响应事件。 用 ViewPager 来实现滑动加载下一张图片。

下面我们就按照以上几个步骤来实现我们想要的功能。

二、主要内容

2.1 获取 WebView 页面所有图片对应地址

2.1.1 解析 WebView 页面加载的 HTML文本文件

定义供 JavaScript 调用的交互接口


 
private class InJavaScriptLocalObj {
 
 @android.webkit.JavascriptInterface
 public void showSource(String html) {
  //从 HTML 文件中提取页面所有图片对应的地址对象
  getAllImageUrlFromHtml(html);
 }
 }

WebView 开启 JavaScript 脚本执行,调用 JavaScript 代码


 mWebView.getSettings().setJavaScriptEnabled(true);
 mWebView.addJavascriptInterface(new InJavaScriptLocalObj(), "local_obj");
 mWebView.setWebViewClient(new WebViewClient() {
  // 网页跳转
  @Override
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
  view.loadUrl(url);
  return true;
  }
  // 网页加载结束
  @Override
  public void onPageFinished(WebView view, String url) {
  super.onPageFinished(view, url);
  //解析 HTML
  parseHTML(view);
  }
 
private void parseHTML(WebView view) {
 //这段 js 代码是解析获取到了 HTML 文本文件,然后调用本地定义的 Java 代码返回
 //解析出来的 HTML 文本文件
 view.loadUrl("javascript:window.local_obj.showSource('<head>'+"
  + "document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}

2.1.2 从获取到的 HTML文本文件中提取页面所有图片对应的地址对象


 // 获取 img 标签正则
 private static final String IMAGE_URL_TAG = "<img.*class="lazy" data-src=(.*?)[^>]*?>";
 // 获取 class="lazy" data-src 路径的正则
 private static final String IMAGE_URL_CONTENT = "http:\"?(.*?)(\"|>|\\s+)";

private List<String> getAllImageUrlFromHtml(String html) {
 Matcher matcher = Pattern.compile(IMAGE_URL_TAG).matcher(html);
 List<String> listImgUrl = new ArrayList<String>();
 while (matcher.find()) {
 listImgUrl.add(matcher.group());
 }
 //从图片对应的地址对象中解析出 class="lazy" data-src 标签对应的内容
 getAllImageUrlFormclass="lazy" data-srcObject(listImgUrl);
 return listImgUrl;
}
 
 private List<String> getAllImageUrlFormclass="lazy" data-srcObject(List<String> listImageUrl) {
 for (String image : listImageUrl) {
  Matcher matcher = Pattern.compile(IMAGE_URL_CONTENT).matcher(image);
  while (matcher.find()) {
  listImgclass="lazy" data-src.add(matcher.group().substring(0, matcher.group().length() - 1));
  }
 }
 return listImgclass="lazy" data-src;
 }

到这里我们获取到了 WebView 页面中所有图片对象对应的 URL 地址,下面就还差一步,就是在点击 WebView 界面的图片时候去响应点击事件,然后把相应的 URL 地址传递给 ViewPager 进行显示就齐活了。

2.2 响应 WebView 界面图片的点击事件

2.2.1定义供 JavaScript 调用的交互接口


// js 通信接口,定义供 JavaScript 调用的交互接口
private class MyJavascriptInterface {
 private Context context;
 public MyJavascriptInterface(Context context) {
 this.context = context;
 }
 
 @android.webkit.JavascriptInterface
 public void openImage(String url) {
 Intent intent = new Intent();
 intent.putExtra("image", url);
 //listImgclass="lazy" data-src 该参数为页面所有图片对应的 url
 intent.putStringArrayListExtra(URL_ALL, (ArrayList<String>) listImgclass="lazy" data-src);
 intent.setClass(context, ShowImageFromWebActivity.class);
 context.startActivity(intent);
 }
}

2.2.2 WebView 开启 JavaScript 脚本执行,调用 JavaScript 代码


 mWebView.getSettings().setJavaScriptEnabled(true);
//载入 js
mWebView.addJavascriptInterface(new MyJavascriptInterface(this), "imageListener");
mWebView.setWebViewClient(new WebViewClient() {
 // 网页跳转
 @Override
 public boolean shouldOverrideUrlLoading(WebView view, String url) {
 view.loadUrl(url);
 return true;
 }
 // 网页加载结束
 @Override
 public void onPageFinished(WebView view, String url) {
 super.onPageFinished(view, url);
 // web 页面加载完成,添加监听图片的点击 js 函数
 addImageClickListener();
 }
 
 private void addImageClickListener() {
 mWebView.loadUrl("javascript:(function(){" +
  "var objs = document.getElementsByTagName(\"img\"); " +
  "for(var i=0;i<objs.length;i++) " +
  "{"
  + " objs[i].onclick=function() " +
  " { "
  + " window.imageListener.openImage(this.class="lazy" data-src); " +
  " } " +
  "}" +
  "})()");
 }

到这里我们完成了前两步,拿去到 WebView 界面图片对应的所有 URL 地址和响应 WebView 界面图片的点击事件,下面的事情就简单了,用 ViewPager 滑动显示每一张图片,再我们进行最后一步之前,我们再来实现一个功能就是长按 WebView 界面图片,弹出对话框来,然后可以选择保存图片功能,代码如下:

WebView 中图片长按点击事件处理


//长按点击事件
mWebView.setOnLongClickListener(new View.OnLongClickListener() {
 @Override
 public boolean onLongClick(View v) {
 //响应长按事件
 responseWebLongClick(v);
 return false;
 }
});
 
 private void responseWebLongClick(View v) {
 if (v instanceof WebView) {
  WebView.HitTestResult result = ((WebView) v).getHitTestResult();
  if (result != null) {
  int type = result.getType();
  //判断点击类型如果是图片
  if (type == WebView.HitTestResult.IMAGE_TYPE || type == WebView.HitTestResult.class="lazy" data-src_IMAGE_ANCHOR_TYPE) {
   longClickUrl = result.getExtra();
   //弹出对话框
   showDialog(longClickUrl);
  }
  }
 }
 }
 
 private void showDialog(final String url) {
 new ActionSheetDialog(this)
  .builder()
  .setCancelable(true)
  .setCanceledOnTouchOutside(true)
  .addSheetItem(
   "保存到相册",
   ActionSheetDialog.SheetItemColor.Blue,
   new ActionSheetDialog.OnSheetItemClickListener() {
    @Override
    public void onClick(int which) {
    //下载图片
    downloadImage(url);
    }
   }).show();
 }

2.3 ViewPager 滑动显示每一张图片,PhotoView 实现自由缩放功能

由于这部分代码比较简单,这里就直接贴出部分代码,文章中所用的 Demo 代码最终会上传到 GitHub上,有兴趣可以去瞧一瞧完整的代码,这里简单介绍几个类,ShowImageFromWebActivity.java 这个类内部就包含一个 ViewPager 和两个按钮, ViewPager 用来滑动显示每一张图片,按钮用来显示滑动的页数和实现点击保存图片功能,代码如下:


public class ShowImageFromWebActivity extends Activity implements View.OnClickListener {
 private ViewPager vpImageBrowser;
 private TextView tvImageIndex;//显示滑动页数
 private Button btnSave;//保存图片按钮
 private ImageBrowserAdapter adapter;
 private ArrayList<String> imgUrls;//WebView 页面所有图片 URL
 private String url;//WebView 页面所有图片中被点击图片对应 URL
 private int currentIndex;//标记被滑动图片在所有图片中的位置
 private Handler mHandler;//异步发送消息
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_show_image_from_web);
 initView();
 initListener();
 initData();
 }
 private void initView(){
 vpImageBrowser = (ViewPager) findViewById(R.id.vp_image_browser);
 tvImageIndex = (TextView) findViewById(R.id.tv_image_index);
 btnSave = (Button) findViewById(R.id.btn_save);
 }
 private void initData(){
 mHandler = new Handler();
 imgUrls=getIntent().getStringArrayListExtra(MainActivity.URL_ALL);
 url=getIntent().getStringExtra("image");
 //获取被点击图片在所有图片中的位置
 int position=imgUrls.indexOf(url);
 adapter=new ImageBrowserAdapter(this,imgUrls);
 vpImageBrowser.setAdapter(adapter);
 final int size=imgUrls.size();
 if(size > 1) {
  tvImageIndex.setVisibility(View.VISIBLE);
  tvImageIndex.setText((position+1) + "/" + size);
 } else {
  tvImageIndex.setVisibility(View.GONE);
 }
 vpImageBrowser.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
  @Override
  public void onPageSelected(int arg0) {
  currentIndex=arg0;
  int index = arg0 % size;
  tvImageIndex.setText((index+1) + "/" + size);
  }
  @Override
  public void onPageScrolled(int arg0, float arg1, int arg2) {
  // TODO Auto-generated method stub
  }
  @Override
  public void onPageScrollStateChanged(int arg0) {
  // TODO Auto-generated method stub
  }
 });
 vpImageBrowser.setCurrentItem(position);
 }
 private void initListener(){
 btnSave.setOnClickListener(this);
 }
 @Override
 public void onClick(View v) {
 switch (v.getId()){
  case R.id.btn_save :
  Toast.makeText(getApplicationContext(), "开始下载图片", Toast.LENGTH_SHORT).show();
  downloadImage();
  break;
 }
 
 private void downloadImage() {
 downloadAsync(imgUrls.get(currentIndex), Environment.getExternalStorageDirectory().getAbsolutePath() + "/ImagesFromWebView");
 }
 }

ShowImageFromWebActivity.java 对应 xml 文件


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@android:color/black"
 tools:context="activity.ShowImageFromWebActivity">
 <view.PhotoViewViewPager
 android:id="@+id/vp_image_browser"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 </view.PhotoViewViewPager>
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_alignParentBottom="true"
 android:orientation="horizontal"
 android:padding="16dp" >
 <TextView
  android:textSize="18sp"
  android:id="@+id/tv_image_index"
  android:layout_width="56dp"
  android:layout_height="36dp"
  android:background="@drawable/shape_corner_rect_gray"
  android:gravity="center"
  android:paddingTop="3dp"
  android:paddingBottom="3dp"
  android:paddingRight="10dp"
  android:paddingLeft="10dp"
  android:text="1/9"
  android:textColor="@android:color/white" />
 <View
  android:layout_width="0dp"
  android:layout_height="1dp"
  android:layout_weight="1" />
 <Button
  android:id="@+id/btn_save"
  android:textSize="@dimen/_16sp"
  android:layout_width="56dp"
  android:layout_height="36dp"
  android:background="@drawable/shape_corner_rect_gray"
  android:gravity="center"
  android:padding="4dp"
  android:text="保存"
  android:textColor="@color/white" />
 </LinearLayout>
</RelativeLayout>

ImageBrowserAdapter.java 类代码如下:


public class ImageBrowserAdapter extends PagerAdapter {
 private Activity context;
 private List<String> picUrls;
 public ImageBrowserAdapter(Activity context, ArrayList<String> picUrls) {
 this.context = context;
 this.picUrls = picUrls;
 }
 @Override
 public int getCount() {
 return picUrls.size();
 }
 @Override
 public boolean isViewFromObject(View view, Object object) {
 return view == object;
 }
 @Override
 public View instantiateItem(ViewGroup container, int position) {
 View view = View.inflate(context, R.layout.item_image_browser, null);
 ImageView iv_image_browser = (ImageView) view.findViewById(R.id.show_webimage_imageview);
 String picUrl = picUrls.get(position);
 final PhotoViewAttacher photoViewAttacher=new PhotoViewAttacher(iv_image_browser);
 photoViewAttacher.setScaleType(ImageView.ScaleType.FIT_CENTER);
 //显示图片
 Glide.with(context).
  load(picUrl)
  .crossFade()
  .placeholder(R.drawable.avatar_default)
  .error(R.drawable.image_default_rect)
  .into(new GlideDrawableImageViewTarget(iv_image_browser){
  @Override
  public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
   super.onResourceReady(resource, animation);
   photoViewAttacher.update();
  }
  });
 container.addView(view);
 return view;
 }
 @Override
 public void destroyItem(ViewGroup container, int position, Object object) {
 container.removeView((View) object);
 }

上面代码也很简单,就是根据 URL 来加载显示图片,然后利用 PhotoView 进行缩放。


//ImageBrowserAdapter Item 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center">
 <RelativeLayout
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:gravity="center_vertical">
  <uk.co.senab.photoview.PhotoView
  android:id="@+id/pv_show_image"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@android:color/white"
  android:class="lazy" data-src="@drawable/image_default_rect" />
 </RelativeLayout>
</RelativeLayout>

以上为本次学习内容,如有错误还望指正,谢谢!

文章中 Demo 已经上传在 GitHub上,地址为ShowImageFromWebView,大家也可以通过本地下载

总结

以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程网的支持。

您可能感兴趣的文章:基于Android实现保存图片到本地并可以在相册中显示出来Android实现保存图片到本地并在相册中显示Android开发实现保存图片到手机相册功能android创建数据库(SQLite)保存图片示例Android画图并保存图片的具体实现代码Android WebView实现长按保存图片及长按识别二维码功能Android编程实现保存图片到系统图库的方法示例Android拍照保存在系统相册不显示的问题解决方法Android开发实现的保存图片到相册功能示例


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android实现点击WebView界面中图片滑动浏览与保存图片功能

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android实现点击WebView界面中图片滑动浏览与保存图片功能

一、实现需求最近在公司的项目中遇到需求如下: 1、点击 WebView 页面的图片实现开启查看图片模式,即可以显示点击的图片,然后滑动显示下一张图片。3、长按 WebView 页面图片弹出对话框可以选择保存长按的图片到本地相册。拿到这个需求
2022-06-06

Android 实现WebView点击图片查看大图列表及图片保存功能

在日常开发过程中,有时候会遇到需要在app中嵌入网页,此时使用WebView实现效果,但在默认情况下是无法点击图片查看大图的,更无法保存图片。本文将就这一系列问题的实现进行说明。 图示:项目的知识点:加载网页后如何捕捉网页中的图片点击事件
2022-06-06

Android怎么实现图片预览与保存功能

这篇“Android怎么实现图片预览与保存功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android怎么实现图片预览与
2023-06-30

Android应用中图片浏览时实现自动切换功能的方法详解

先给最终效果图:当我们在最下边的gallery中切换图片时,上面的大图片会自动切换,切换时有动画效果哦,很简单的一个程序,有待完善更多的功能! activity代码:package cn.com.chenzheng_java; impor
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录