时间:2021-05-20
小米系统自带的长截屏应该很多人都用过,效果不错。当长截屏时listview就会自动滚动,当按下停止截屏时,就会得到一张完整的截屏。
该篇就介绍一下长截屏的原理
上篇中介绍了android屏幕共享实现方式,该篇的原理和上一篇基本一致。
获取view影像
当我们想得到一个view的影像时,我们可以调用系统api,得到view的bitmap,但有时可能得不到。我们可以通过另一种方式得到。
首先创建一个和view一样大小的bitmap
复制代码 代码如下:
Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
然后把view绘制到bmp上
Canvas canvas = new Canvas(); canvas.setBitmap(bmp); view.draw(canvas);执行完上面代码后bmp上就是view的影像了。
制造滚动事件,促使view滚动
我们可以创建一个MotionEvent,然后定时修改MotionEvent的y值,并分发给view,从而促使view上下滚动。当然我们也可以定时修改x值促使view左右滚动。
代码大致如下
final MotionEvent motionEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, view.getWidth() / 2, view.getHeight() / 2, 0); view.postDelayed(new Runnable() { @Override public void run() { motionEvent.setAction(MotionEvent.ACTION_MOVE); motionEvent.setLocation((int) motionEvent.getX(), (int) motionEvent.getY() - 1); //把事件分发给view view.dispatchTouchEvent(motionEvent); view.postDelayed(this, DELAY); } }, DELAY);注意:从分发DOWN事件到结束都要使用同一个MotionEvent对象,只需要不断改变x或y值。
每次x或y的值相对于上次改动不能过大,若过大,view实际滚动距离可能达不到为MotionEvent设置的值(因view滚动时卡顿导致)。
截屏
当为MotionEvent设置的x或y值正好时当前view的大小时,创建新的bitmap,通过上述方法把view绘制到bitmap上,想要停止截屏时拼接所有bitmap即可。
备注
当我们想要把Listview长截屏时,需要为ListView外面嵌套一层和ListView一样大小的View,以上的所有操作都在嵌套的这层view上操作。当我们调用嵌套的这层view的draw(new Canvas(bmp))时会把当前看到的这块ListView绘制到bmp上,不管ListView嵌套了多少层子view都可以绘制到当前bmp上。
由于ListView中根据滑动的距离是否大于ViewConfiguration.get(view.getContext()).getScaledTouchSlop() )来确定要不要滚动,所以一开始我们要特殊处理下,为什么是ViewConfiguration.get(view.getContext()).getScaledTouchSlop() )可以查看ListView的事件分发相关函数得到(dispatchTouchEvent),让Listview认为是开始滚动,这样才能保证以后分发的滑动距离和实际滚动距离一致。
Listview也要通知是否滚动到了最后,不然如果没有手动停止的话,虽然还是在一直分发滚动事件,但ListView不再滚动,导致最终截图后后面全是重复的最后一屏幕。
附 实现大致方式代码,有待优化
package com.example.wanjian.test;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.os.Environment;import android.os.SystemClock;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.LinearLayout;import android.widget.Toast;import java.io.File;import java.io.FileOutputStream;import java.lang.ref.WeakReference;import java.util.ArrayList;import java.util.List;/** * Created by wanjian on 16/8/18. */public class ScrollableViewRECUtil { public static final int VERTICAL = 0; private static final int DELAY = 2; private List<Bitmap> bitmaps = new ArrayList<>(); private int orientation = VERTICAL; private View view; private boolean isEnd; private OnRecFinishedListener listener; public ScrollableViewRECUtil(View view, int orientation) { this.view = view; this.orientation = orientation; } public void start(final OnRecFinishedListener listener) { this.listener = listener; final MotionEvent motionEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, view.getWidth() / 2, view.getHeight() / 2, 0); view.dispatchTouchEvent(motionEvent); motionEvent.setAction(MotionEvent.ACTION_MOVE); //滑动距离大于ViewConfiguration.get(view.getContext()).getScaledTouchSlop()时listview才开始滚动 motionEvent.setLocation(motionEvent.getX(), motionEvent.getY() - (ViewConfiguration.get(view.getContext()).getScaledTouchSlop() + 1)); view.dispatchTouchEvent(motionEvent); motionEvent.setLocation(motionEvent.getX(), view.getHeight() / 2); view.postDelayed(new Runnable() { @Override public void run() { if (isEnd) { //停止时正好一屏则全部绘制,否则绘制部分 if ((view.getHeight() / 2 - (int) motionEvent.getY()) % view.getHeight() == 0) { Bitmap bitmap = rec(); bitmaps.add(bitmap); } else { Bitmap origBitmap = rec(); int y = view.getHeight() / 2 - (int) motionEvent.getY(); Bitmap bitmap = Bitmap.createBitmap(origBitmap, 0, view.getHeight() - y % view.getHeight(), view.getWidth(), y % view.getHeight()); bitmaps.add(bitmap); origBitmap.recycle(); } //最后一张可能高度不足view的高度 int h = view.getHeight() * (bitmaps.size() - 1); Bitmap bitmap = bitmaps.get(bitmaps.size() - 1); h = h + bitmap.getHeight(); Bitmap result = Bitmap.createBitmap(view.getWidth(), h, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(); canvas.setBitmap(result); for (int i = 0; i < bitmaps.size(); i++) { Bitmap b = bitmaps.get(i); canvas.drawBitmap(b, 0, i * view.getHeight(), null); b.recycle(); } listener.onRecFinish(result); return; } if ((view.getHeight() / 2 - (int) motionEvent.getY()) % view.getHeight() == 0) { Bitmap bitmap = rec(); bitmaps.add(bitmap); } motionEvent.setAction(MotionEvent.ACTION_MOVE); //模拟每次向上滑动一个像素,这样可能导致滚动特别慢,实际使用时可以修改该值,但判断是否正好滚动了 //一屏幕就不能简单的根据 (view.getHeight() / 2 - (int) motionEvent.getY()) % view.getHeight() == 0 来确定了。 //可以每次滚动n个像素,当发现下次再滚动n像素时就超出一屏幕时可以改变n的值,保证下次滚动后正好是一屏幕, //这样就可以根据(view.getHeight() / 2 - (int) motionEvent.getY()) % view.getHeight() == 0来判断要不要截屏了。 motionEvent.setLocation((int) motionEvent.getX(), (int) motionEvent.getY() - 1); view.dispatchTouchEvent(motionEvent); view.postDelayed(this, DELAY); } }, DELAY); } public void stop() { isEnd = true; } private Bitmap rec() { Bitmap film = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565); Canvas canvas = new Canvas(); canvas.setBitmap(film); view.draw(canvas); return film; } public interface OnRecFinishedListener { void onRecFinish(Bitmap bitmap); }}activity代码
布局
效果图
屏幕
最终截屏
可以看到毫无拼接痕迹。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Android实现截屏功能的实例实现代码:publicclassScreenShot{//获取指定Activity的截屏,保存到png文件privatestat
本文介绍了android视频截屏&手机录屏实现代码,分享给大家,希望对大家有帮助问题在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以
IOS开发之ios视频截屏的实现代码现在好多视频截屏软件,这里提供一个IOS视频截屏的方法,大家可以参考下,实现代码:?12345678910111213141
本文实例为大家分享了Android实现截长图功能的具体代码,供大家参考,具体内容如下先看看手机自带的长截屏功能:机型:vivox9plus大胆推测实现逻辑:1:
本文实例为大家分享了Android实现全屏截图或长截屏功能的具体代码,供大家参考,具体内容如下全屏截图:/***传入的activity是要截屏的activity