
先很负责任的说一下,这个内容也是百度来的,但是很不负责任的是,当初只记录解决方案,忘了记录是查看的哪篇博客了,这里先对不知道借鉴的谁表示感谢。无法分享链接,就厚着脸皮把(转)字去掉了,请大家谅解。
先提供一下 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 怎么获取当前屏幕的截图等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)