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

uni-app跨端图片保存全攻略:微信小程序与App端实现方案详解 在移动应用开发中,文件下载与本地存储是常见的功能需求,其核心原理涉及网络请求、文件系统操作和平台权限管理。通过跨端框架如uni-app,开发者可以编写一套代码适配多平台,但不同平台的安全模型和API差异显著。H5环境受浏览器沙盒限制,主要通过引导用户操作实现;微信小程序通过授权机制开放有限系统能力;而App端则可调用原生API实现完整功能。理解这些底层机制,对于实现如“图片保存到相册”这类提升用户体验、促进内容传播的功能至关重要。本文聚焦于uni-app开发中的**web-view通信**与**条件编译** 阅读详情

在日常开发过程中,有时候会遇到需要在app中嵌入网页,此时使用WebView实现效果,但在默认情况下是无法点击图片查看大图的,更无法保存图片。本文将就这一系列问题的实现进行说明。

图示:

 

项目的知识点:

 

  1. 加载网页后如何捕捉网页中的图片点击事件;
  2. 获取点击的图片资源后进行图片显示,获取整个页面所有的图片;
  3. 支持查看上下一张的图片以及对图片缩放显示;
  4. 对图片进行保存;
  5. 其他:图片缓存的处理(不用每次都重新加载已查看过的图片)

 

项目代码结构:

 

前期准备(添加权限、依赖和混淆设置):

添加权限:

    <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'

 

混淆文件设置:

-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的类用来实现js调用本地的方法;2.自定义MyWebViewClient来实现对WebView的监听管理。

 

MyWebViewClient代码如下:

public class MyWebViewClient extends WebViewClient {
    @Override
    public void onPageFinished(WebView view, String url) {
        view.getSettings().setJavaScriptEnabled(true);
        super.onPageFinished(view, url);
        addImageClickListener(view);//待网页加载完全后设置图片点击的监听方法
    }

    @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代码找到标签为img的代码块,设置点击的监听方法与本地的openImage方法进行连接
                "    }  " +
                "}" +
                "})()");
    }
}


该类继承自WebViewClient,在onPageFinished方法中设置addImageClickListener的监听方法——>当整个WebView页面加载完毕后,为每张图片设置监听事件——>这意味着,整个页面未加载完毕时,点击是无效的。

addImageClickListener的代码实现也很简单,通过js找到相应的img标签,这样就知道是图片了,然后为这些图片设置点击监听事件——>每当点击时调用自定义的openImage(url)方法。这个openImage(url)方法与MJavascriptInterface中对应的方法交相辉映,这样就形成了js调用本地的方法。

 

MJavascriptInterface代码(主要为与js对应的本地方法的实现):

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)方法实现的逻辑是:通过传递当前图片的url与该WebView整个页面的图片列表(imageUrls)进行跳转至PhotoBrowserActivity中。PhotoBrowserActivity就是用来显示大图的图片列表的页面。

此处的疑问:imageUrls怎么获得呢?

方式:1.服务器端直接将WebView中所有的图片按照顺序组合成String数组传递过来;2.或者直接将所有含img标签的html代码传递过来,从而让客户端自己解析出所有图片地址组合成的String数组。(此处是采用的第二种,具体如何解析,可以下载源码查看。)

 

OK,到了这里算是完成了项目知识点的第1点:1.加载网页后如何捕捉网页中的图片点击事件;

接下来就说明后面的几点:

2.获取点击的图片资源后进行图片显示,获取整个页面所有的图片;
3.支持查看上下一张的图片以及对图片缩放显示;
4.对图片进行保存;

 

其他所有的几点实现均在PhotoBrowserActivity中,代码如下:主要就是将图片放进ViewPager中进行显示:

 

 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) {//如果当前页面未加载完毕,则显示加载动画,反之相反;
            showLoadingAnimation();
        }
        photoOrderTv.setText((curPosition + 1) + "/" + imageUrls.length);//设置页面的编号

        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) {//如果当前页面未加载完毕,则显示加载动画,反之相反;
                    showLoadingAnimation();
                } else {
                    hideLoadingAnimation();
                }
                curPosition = position;
                photoOrderTv.setText((position + 1) + "/" + imageUrls.length);//设置页面的编号
                mPager.setTag(position);//为当前view设置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方法来获得用户点击的是哪一张图片的位置并设置当前是哪一个page——>通过遍历当前url与所有url来匹配获取;

2.通过addOnPageChangeListener来实现对页面滑动事件的监听——>此处主要用来处理设置当前页面的position、动画、页面序号显示的逻辑;

3.PagerAdapter的实现——>每一页内容的初始化,主要为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来实现图片的伸缩显示;2.通过Glide来加载图片等处理;

PhotoView是什么——>就是图片组件,对图片的伸缩、动效、缓存等方面进行了处理,点击地址查看GitHub介绍>>:

Gilde是什么——>Google推荐的图片加载库,此处用它的理由是好用、简单,点击地址查看GitHub介绍>>:

Glide的简化形式——>Glide.with(...).load(图片地址).override(加载图片的大小).listener(设置监听方法).into(某个一个组件,此处是PhotoView),此处使用的是原图加载,监听方法中有两个回调方法:

onException和onResourceReady,此处在onResourceReady做的处理是:当资源加载完毕时调用——>此时取消加载动画的显示。

 

页面中的“页面编号”和“保存”的组件显示是通过写在整个Activity的布局文件中实现的,而不是通过在每一页中写入这些组件。以下为获取图片资源对象的代码:

 

 

 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();
                        }
                    });
                }
            });
        }
    }


因为下载图片需要知道当前处于哪一页,所以在ViewPager初始化显示和滑动时都给每一页设置了tag,此时就派上了用场——>mPager.findViewWithTag获取当前page中的布局对象,然后获得对应的PhotoView对象,从而经过处理最终获取到Bitmap对象。这样已经很简单了,接下来只要将Bitmap对象保存至本地即可,代码如下:

 

 

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");//设置以当前时间格式为图片名称
                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();
                }

                //保存图片后发送广播通知更新数据库
                Uri uri = Uri.fromFile(file);
                context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
            }
        }).start();
    }

   public interface SaveResultCallback{
        void onSavedSuccess();
        void onSavedFailed();
    }
}

图片如何保存已经如代码所示,但要注意的是需要将已经保存的图片进行广播通知数据库更新——>这样立马进入微信或者扣扣点击发送图片,就可以看到刚刚保存的图片。

缓存的处理:

使用Glide其中的一个好处是会将图片默认缓存,在需要清除缓存时,只需要执行下面的代码(此处是放在MainActivity中,退出页面即清除缓存):

   @Override
    protected void onDestroy() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Glide.get(MainActivity.this).clearDiskCache();//清理磁盘缓存需要在子线程中执行
            }
        }).start();
        Glide.get(this).clearMemory();//清理内存缓存可以在UI主线程中进行
        super.onDestroy();
    }

 

特别注意:

1.若项目配置中将targetSdkVersion 指定为22以上,则要加入动态权限申请的模块,否则在进行保存操作时则会提示失败!

2.项目中暴露的js接口类:MJavascriptInterface不能混淆,其调用的方法的声明也不能混淆,所以还要添加如下混淆设置代码(代码因包名而变化):

 

-keepclassmembers class com.example.administrator.webviewpagescannerapp.other.MJavascriptInterface{
  public *;
}

-keepattributes *Annotation*
-keepattributes *JavascriptInterface*

 

源码已经上传至GitHub,点击此处查看>>

 

Cocos Creator安卓APK构建实战:从环境配置到多渠道打包 在移动游戏开发中,APK构建是将游戏项目打包为安卓可安装应用的关键环节,它直接关系到应用的最终分发与用户体验。其核心原理在于通过构建工具链(如Gradle)将代码、资源与原生库进行编译、压缩与签名,生成符合安卓平台规范的安装包。这一过程的技术价值在于确保应用的完整性、安全性,并优化其性能与体积。在实际应用场景中,开发者常需处理环境配置、签名管理、资源优化及多渠道适配等问题。本文聚焦于Cocos Creator引擎下的安卓构建,详细解析了**JDK版本选择**与**Gradle配置**等基础但易错的热点环节, 阅读详情

相关推荐

uniapp - 如何跟内嵌 web-view 组件内的网页交互,与 web-view 内嵌网页进行双向通信(uniapp 与 webview 网页之间的 “相互“ 传值)提供详细的示例代码及解决方案

uni-app如何实现在H5环境中与web-view中的网页交互通讯uniappuni-app 与 web-view内嵌网页 双向通信 如何跟内嵌web-view交互uniappAPP与webview子页面交互uniappAPP与webview子页面交互关于uni-app 使用 web-view 页面之间互相跳转、通信等问题uniapp的web-view嵌入网页,网页与uniapp通信webview如何与uniapp写的H5页面交互嵌套webview调用uniapp各种API组件实现H5和app通讯和交互

✅ 精选推荐文章 1万+

Android控件WebView(浏览器)常用功能(图片、缩放)例子介绍

http://orgcent.com/android-webview-image-zoom-example/

宁静致远 1683

android中webview图片点击及图片手势操作

资源博客地址 http://blog.youkuaiyun.com/wangtingshuai/article/details/8635787

Android使用WebView显示网页(图片缩放)

上周写了一篇关于webview的博文:Android使用WebView显示网页(图片大小的处理及内容的自适应) 后来通过自己想的第三种办法实现了图片的适配,方法是设置html的img标签属性,把图片的宽度设置为设备屏幕的宽度,涉及的知识点就是,获取设备宽度值、java代码 添加/修改 html标签属性。 1. 获取设备屏幕信息: /** * 获取设备的屏幕信息 * @par

年少的风 2万+

Android WebView中图片浏览及缩放效果

本文实例为大家分享了Android WebView图片浏览及缩放效果展示的具体代码,供大家参考,具体内容如下 此工程用到了两个开源库: PhotoView支持图片的缩放 Android-Universal-Image-Loader图片的异步加载 (android studio)将两个源工程中的library文件夹导入到Demo Module所在的Project中,修改各自的build.gradle文件,让里面的版本号、所用的android包等与Demo Module相同即可。大致如图: 源代码: 主Activity.java public class MainActiv

Linux内核模块开发实战指南(2025版)

2025年Linux内核模块开发迎来革命性突破!本文将从零开始手把手教你构建可动态加载的AI加速驱动模块,揭秘最新内核特性与开发技巧,更包含独家性能调优方案与跨架构移植秘籍。文末附赠价值百万的调试脚本,助你轻松突破开发瓶颈!

资深全栈架构师,乐于在 优快云 分享技术见解,与大家携手共进,共攀技术巅峰! 1809

通过JavaScript实现在Android WebView中点击查看图片,长按识别二维码

序言 最近的项目中,客户需要在WebView中实现长按点击识别二维码的功能。但是原有的图片点击已经和查看图片事件绑定。要不破坏原有的功能,还能添加长按事件。这是第一次遇到这种需求。最后我还是完成了这个功能。但是在完成的过程中也遇到一些坑。再次记录一下,先看一下我实现的效果。 1.原有的点击查看图片功能 2.长按识别二维码 3识别失败给出提示 实现 1.长按事件的监测 背景知识 要实现对长按事...

SOLO的博客 3800

Ubuntu22.04下3分钟搞定GitHub加速:SwitchHosts+小鱼工具保姆级配置指南

本文提供Ubuntu22.04下快速解决GitHub下载超时问题的保姆级教程,通过SwitchHosts图形化工具和小鱼一键换源工具实现高效加速。详细步骤包括环境准备、工具安装配置及验证方法,帮助开发者轻松优化GitHub访问速度,提升工作效率。

weixin_29258297的博客 564

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

看到一篇好的实现WebView点击图片查看大图列表及图片保存功能的文章,记录一下: https://www.jb51.net/article/106272.htm

u011028777的专栏 1831

奔图M6700-M6800-M7100-M7200 系列打印机拆解教程?

奔图M6700-M6800-M7100-M7200 系列打印机拆解教程?

m0_58098052的博客 1599

拯救者R7000P(2021)装双系统Ubuntu20.04 解决联发科MT7921无线网卡在Ubuntu中不能联网

拯救者R7000P(2021)装双系统Ubuntu20.04/Ubuntu18.04 电脑配置:联想拯救者R7000P CPU:AMD R7-5800H GPU:RTX3060-6G 内存:16GB 固态:500G(原装)+500(加装) 1.做系统盘(本文以Ubuntu20.04为例) 1.下载Ubuntu20.04镜像 直接去Ubuntu官网或者一些国内的镜像去下载都可以,这里给出一个网址https://ubuntu.com/download/desktop,根据需要下载自己学要的Ubuntu版本,后缀

qq_41108639的博客 1万+

android webview 下载图片,Android 实现WebView点击图片查看大图列表及图片保存功能...

在日常开发过程中,有时候会遇到需要在app中嵌入网页,此时使用WebView实现效果,但在默认情况下是无法点击图片查看大图的,更无法保存图片。本文将就这一系列问题的实现进行说明。图示:项目的知识点:加载网页后如何捕捉网页中的图片点击事件;获取点击的图片资源后进行图片显示,获取整个页面所有的图片;支持查看上下一张的图片以及对图片缩放显示;对图片进行保存;其他:图片缓存的处理(不用每次都重新加载已查看...

weixin_39652658的博客 568

【局部规划模块轨迹优化算法】EM_planner最大期望滚动优化算法

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对EM_planner最大期望滚动优化算法做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

qq_35635374的博客 761

Android WebView保存图片的方式(模仿网易图片下载逻辑)

目前我在实现WebView上图片保存的时候有两种解决方案,下面简单介绍吧。       方案一:使用registerForContextMenu菜单,效果图如下:          这个使用比较简单,步骤如下:  1.注册: 2.菜单添加条目: 3.处理点击事件,开始下载:(ps 这里就不实现下载了!)

u010052279的专栏 1499

linux内核学习(一)---内核社区介绍及补丁提交

本系列开始会对linux内核进行系统性的学习,以源码与内核社区为基础,了解前沿的内核机制,同时也深度了解linux内核中的一些经典机制 本章会先对linux内核社区进行简单的介绍,包括源码下载、内核社区的修改提交

文艺小少年的博客 536

Qt | 开发过程中总结的经验

关于如何判断自己的Qt库是多少位,有个误区就是很多人要么看成了QtCreator的关于信息中列出的位数,要么以为自己是64位的系统就认为是64位的Qt,最终要在Qt构建套件中查看具体位数,大概从Qt5.14开始基本上很少提供32位的库,尤其是Qt6.0以后基本上默认就是只有64位的库了,这也是顺应时代潮流,毕竟不久的将来(个人预计2030年以前)基本上32位的系统占比不超过1%,放心大胆的用64位的库吧,抛弃烦人的32位以及XP系统。Qt常用类的头文件的函数看完学完使用一遍并加以融会贯通,月薪30K起步。

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 492

Android 进阶篇---> App运行时大图监控

背景 最近看滴滴开源的Dokit框架中有一个大图监控的功能,可以对图片的文件大小和所占用的内存大小设置一个阈值,当图片超过该值的时候进行提示。 这个功能对于我们在做APK体积压缩,内存管理的时候还是很有用的,比如当我们要从后台返回的连接中加载一张图片,这张图片的大小我们是不知道的,虽然现在大家都使用Glide等三方 图片加载框架,框架会自动对图片进行压缩,但是依然会出现压缩后所占内存超过预期的情况。 这时候我们可以在开发、测试和预生产阶段使用大图监控来识别出那些超标的图片。 需求 在讨论如何做之前,我们必须

qq_42795723的博客 2273

【毕业设计】基于雷达与深度学习的摔倒检测——雷达数据集的建立

运动物体的微多普勒效应为人体动作识别提供了可能,基于雷达的居家检测具有良好的隐私保护性,且不易受环境因素影响(如光照、温度等),近年来已受到国内外学者的广泛关注。基于雷达与深度学习的摔倒检测使用自建的雷达数据集进行人体摔倒检测的研究。雷达数据集的建立分为雷达数据采集和雷达数据处理两部分工作。

洋洋Young的博客 3403

从Demo到生产级:基于auto-scroll-capture方案扩展RecyclerView、WebView长截屏的完整路线图

**auto-scroll-capture** 是一个轻量级的 Android 自动滚动长截屏开源项目:它像 MIUI 长截图一样,通过模拟触摸事件让页面自动滚动,配合 `view.draw()` 逐屏截图并拼接成一张长图。本文基于仓库里的 Demo,拆解“画、滚、截”三步原理,并给出一条把该方案扩展到 **RecyclerView 长截屏** 和 **WebView 整页截屏** 两个高频场景、

gitblog_00448的博客 783

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

android 新闻频道,GitHub - xiyy/TopNews: 一款Android新闻客户端,并提供电视台直播功能...

TopNews一款Android新闻客户端,独立开发完成,主要功能包括:1 新闻频道分类,头条、社会、国内、娱乐、体育、军事、科技、财经、时尚使用ViewPager+FragmentPagerAdapter+Fragment+TabLayout完成布局使用HttpOK从聚合数据获取新闻数据使用Gson对新闻数据解析使用EventBus传递消息2 新闻内容浏览使用RecyclerView完成新闻列表...

weixin_42544461的博客 388

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

uni-app跨端截图全攻略:Canvas实现全屏与区域截图保存

在移动应用开发中,截图功能是用户内容分享、问题反馈和数据保存的常见需求,其核心原理是将屏幕或指定区域的视觉内容转换为可存储的图片文件。Canvas技术因其跨平台兼容性和对图形绘制的底层控制能力,成为实现这一功能的关键技术。通过Canvas绘制,开发者可以精确控制输出内容,生成高质量的图片,这对于提升用户体验和应用功能性具有重要价值。在实际工程中,该技术广泛应用于生成分享卡片、保存用户凭证、内容存档等场景。本文聚焦于uni-app框架下的实现,详细解析了如何利用Canvas绘制、结合uni.canvasToT

ciya3282的博客 420

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

mac 个人网站收藏(二)

Dialog app实现摄像头视频展示需要服务器 浅谈android中的自定义封装易用的Dialog android自定义弹出框样式实现 Android自定义控件-EditText(可用于登陆界面) Android仿QQ消息提示实现弹出式对话框RecyclerView 【Android】 RecyclerView、ListView实现单选列表的优雅之路. 有关RecyclerView瀑布流的问题处

Kenway090704的博客 418

吐血整理!究极深入Android内存优化(四)

对于内存优化的专项优化而言,我们要着重注意两点,即优化大方向 和 优化细节。在这篇文章中,我们除了建立了内存的监控闭环这一核心体系之外,还实现了以下十大组件 / 策略1)、根据设备分级来使用不同的内存和分配回收策略。2)、针对低端机做了功能或图片加载格式的降级处理。3)、针对缓存滥用的问题实现了统一的缓存管理组件。4)、实现了大图监控和重复图片的监控。5)、在前台每隔一定时间去获取当前应用内存占最大内存的比例,当超过设定阈值时则主动释放应用 cache。6)、

2401_85730762的博客 921

uni-app跨端开发:App页面截图与保存相册全攻略

在移动应用开发中,页面截图与保存是常见的功能需求,它涉及前端视图渲染、Canvas绘图、文件系统操作等多个技术环节。其核心原理是通过将DOM或原生视图内容转换为图片数据流,再调用系统API写入相册。这一技术对于内容分享、信息保存等场景具有重要价值,尤其在社区、电商类App中应用广泛。本文聚焦于uni-app这一跨端框架,深入剖析了全屏截图与自定义区域截图两种实现路径,并针对Canvas绘制、像素适配、权限管理等关键问题提供了工程实践方案。文中详细介绍了uni.createSelectorQuery、uni.

weixin_30680385的博客 404
上一篇: Android 底部支付弹窗
下一篇: Android 图片转Base64字符串
ganshenml
博客等级 码龄16年 445粉丝 108原创
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ganshenml

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值