Android知识点——Glide获取图片宽高

Android知识点——Glide获取图片宽高,第1张

  先很负责任的说一下,这个内容也是百度来的,但是很不负责任的是,当初只记录解决方案,忘了记录是查看的哪篇博客了,这里先对不知道借鉴的谁表示感谢。无法分享链接,就厚着脸皮把(转)字去掉了,请大家谅解。

  先提供一下 Android知识点——目录 的链接,然后让我们进入正题。

  实际上,这篇博客所说的内容并不是所有人都可以用到,毕竟大多数时候,我们只需要展示,而并不需要知道的宽高;有的时候我们只需要知道展示的宽高(即ImageView)的宽高,不需要知道资源的实际尺寸。

  但是需求千千万万嘛,以程序员的脑洞,怎么能想到产品的脑洞究竟有多大呢?我这里就遇到了一个需求,那就是需要在一个可缩放的上标注icon(类似地图上的marker)。这还不算完,毕竟在找到的缩放控件 PhotoView 中,我们点击到上后,是有点击点位在整个上的百分比坐标回调的。而多端通过百分比是很容易就能在中获取到相同的点位,并回显出对应的icon的(没办法,谁让我找的是方便计算百分比的呢),结果Web端优先做了这部分功能,使用的是在原图上的具体坐标。这样我百分比的计划自然就落空了,只能想办法计算出具体的点位。

  因此获取的原始尺寸就是一个必不可少的环节,我刚刚百度了一下,查到 wangke_king 的 Android获取的宽度和高度 中使用的方法是:

  我这里没有亲测过,不过应该是没有问题,但是很遗憾我们的需求是在网络上做测量,所以这个方法也无法使用,不过如果其他有类似本地需求的,不妨尝试一下。而我之前找到的解决方案为:

  首先说明,上述的方法是可以实现的尺寸测量的,只是有一个小小的问题,那就是想要计算出Drawable的宽高,需要必须等到加载完成之后,尝试了使用viewpost(),监听组件加载完成,但是并不是每次都能获取到Drawable的宽高,因此当初的解决方案是写了个两秒钟的定时器,每50毫秒测量一次,直到获取到值为止。这样的解决方案可谓是相当无脑了,而且还要消耗很多不必要的资源。

  还好皇天不负有心人啊,终于找到了通过Glide获取宽高的方式:

  这样我们就可以通过回调,在Glide将网络注入到对应的组件的时候,得到的Bitmap,然后在通过Bitmap来获取的宽高。但是需要注意的一点是,Bitmap的泛型是需要手动去设置的哦。

  另外SimpleTarget现在已经过时,暂时还没有查到。我搜索过SimpleTarget过时使用什么替换,有一些说法是使用BitmapImageViewTarget ,不过下面是实际测试结果。

链接:

百度-景色

测量结果:

信息:

如果不是我使用有误的话,BitmapImageViewTarget 是无法替换SimpleTarget ,实现测量原始宽高的功能的。

屏幕的显示机制和帧动画类似,也是一帧一帧的连环画,只不过刷新频率很高,感觉像连续的。为了显示一帧,需要经历计算和渲染两个过程,CPU 先计算出这一帧的图像数据并写入内存,然后调用 OpenGL 命令将内存中数据渲染成图像存放在 GPU Buffer 中,显示设备每隔一定时间从 Buffer 中获取图像并显示。

上述过程中的计算,对于View来说,就好比在主线程遍历 View树 以决定视图画多大(measure),画在哪(layout),画些啥(draw),计算结果存放在内存中,SurfaceFlinger 会调用 OpenGL 命令将内存中的数据渲染成图像存放在 GPU Buffer 中。每隔166ms,显示器从 Buffer 中取出帧并显示。所以自定义 View 可以通过重载onMeasure()、onLayout()、onDraw()来定义帧内容,但不能定义帧刷新频率。

SurfaceView可以突破这个限制。而且它可以将计算帧数据放到独立的线程中进行。下面是自定义SurfaceView的模版代码:

public abstract class BaseSurfaceView extends SurfaceView implements SurfaceHolderCallback {

public static final int DEFAULT_FRAME_DURATION_MILLISECOND = 50;

//用于计算帧数据的线程

private HandlerThread handlerThread;

private Handler handler;

//帧刷新频率

private int frameDuration = DEFAULT_FRAME_DURATION_MILLISECOND;

//用于绘制帧的画布

private Canvas canvas;

private boolean isAlive;

public BaseSurfaceView(Context context) {

super(context);

init();

}

protected void init() {

getHolder()addCallback(this);

//设置透明背景,否则SurfaceView背景是黑的

setBackgroundTransparent();

}

private void setBackgroundTransparent() {

getHolder()setFormat(PixelFormatTRANSLUCENT);

setZOrderOnTop(true);

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

isAlive = true;

startDrawThread();

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

stopDrawThread();

isAlive = false;

}

//停止帧绘制线程

private void stopDrawThread() {

handlerThreadquit();

handler = null;

}

//启动帧绘制线程

private void startDrawThread() {

handlerThread = new HandlerThread(“SurfaceViewThread”);

handlerThreadstart();

handler = new Handler(handlerThreadgetLooper());

handlerpost(new DrawRunnable());

}

private class DrawRunnable implements Runnable {

@Override

public void run() {

if (!isAlive) {

return;

}

try {

//1获取画布

canvas = getHolder()lockCanvas();

//2绘制一帧

onFrameDraw(canvas);

} catch (Exception e) {

eprintStackTrace();

} finally {

//3将帧数据提交

getHolder()unlockCanvasAndPost(canvas);

//4一帧绘制结束

onFrameDrawFinish();

}

//不停的将自己推送到绘制线程的消息队列以实现帧刷新

handlerpostDelayed(this, frameDuration);

}

}

protected abstract void onFrameDrawFinish();

protected abstract void onFrameDraw(Canvas canvas);

}

用HandlerThread作为独立帧绘制线程,好处是可以通过与其绑定的Handler方便地实现“每隔一段时间刷新”,而且在Surface被销毁的时候可以方便的调用HandlerThreadquit()来结束线程执行的逻辑。

DrawRunnablerun()运用模版方法模式定义了绘制算法框架,其中帧绘制逻辑的具体实现被定义成两个抽象方法,推迟到子类中实现,因为绘制的东西是多样的,对于本文来说,绘制的就是一张张,所以新建BaseSurfaceView的子类FrameSurfaceView:

逐帧解析 & 及时回收

public class FrameSurfaceView extends BaseSurfaceView {

public static final int INVALID_BITMAP_INDEX = IntegerMAX_VALUE;

private List bitmaps = new ArrayList<>();

//帧

private Bitmap frameBitmap;

//帧索引

private int bitmapIndex = INVALID_BITMAP_INDEX;

private Paint paint = new Paint();

private BitmapFactoryOptions options = new BitmapFactoryOptions();

//帧原始大小

private Rect srcRect;

//帧目标大小

private Rect dstRect = new Rect();

private int defaultWidth;

private int defaultHeight;

public void setDuration(int duration) {

int frameDuration = duration / bitmapssize();

setFrameDuration(frameDuration);

}

public void setBitmaps(List bitmaps) {

if (bitmaps == null || bitmapssize() == 0) {

return;

}

thisbitmaps = bitmaps;

//默认情况下,计算第一帧的原始大小

getBitmapDimension(bitmapsget(0));

}

private void getBitmapDimension(Integer integer) {

final BitmapFactoryOptions options = new BitmapFactoryOptions();

optionsinJustDecodeBounds = true;

BitmapFactorydecodeResource(thisgetResources(), integer, options);

defaultWidth = optionsoutWidth;

defaultHeight = optionsoutHeight;

srcRect = new Rec

第1步,在开始菜单中依次单击“管理工具”→DNS菜单项,打开dnsmgmt窗口。在左窗格中右键单击服务器名称,选择“配置DNS服务器”命令。

第2步,打开“配置DNS服务器向导”对话框,在欢迎对话框中单击“下一步”按钮。打开“选择配置 *** 作”对话框,在默认情况下适合小型网络使用的“创建正向查找区域”单选框处于选中状态。保持默认设置并单击“下一步”按钮。

小提示:上述步骤创建的正向查找区域是指将域名解析为IP地址的过程。即当用户输入某个域名时,借助于该记录可以将域名解析为IP地址,从而实现对服务器的访问。

第3步,打开“主服务器位置”对话框,选中“这台服务器维护该区域”单选框,并单击“下一步”按钮。

int[] pixels = new int[bitgetWidth()bitgetHeight()];//保存所有的像素的数组,宽×高

bitgetPixels(pixels,0,bitgetWidth(),0,0,bitgetWidth(),bitgetHeight());

for(int i = 0; i < pixelslength; i++){

int clr = pixels[i];

int red = (clr & 0x00ff0000) >> 16; //取高两位

int green = (clr & 0x0000ff00) >> 8; //取中两位

int blue = clr & 0x000000ff; //取低两位

Systemoutprintln("r="+red+",g="+green+",b="+blue);

}

其中getPixels中第三个参数要为的宽度

以上就是关于Android知识点——Glide获取图片宽高全部的内容,包括:Android知识点——Glide获取图片宽高、android获取surfaceview里面的每一帧、android 怎么获取当前屏幕的截图等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/9821580.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存