android显示gif图片
Android实现可播放GIF动画的ImageView
Android实现可播放GIF动画的ImageViewAndroid的原⽣控件并不⽀持播放GIF格式的图⽚。
我们都知道,在Android中如果想要显⽰⼀张图⽚,可以借助ImageView来完成,但是如果将⼀张GIF图⽚设置到ImageView⾥,它只会显⽰这张图⽚的第⼀帧,不会产⽣任何的动画效果。
今天我们来编写⼀个⾃定义的增强型ImageView(继承ImageView),可以播放GIF格式的图⽚,暂且叫做GifImageView吧。
1.⾃定义属性<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="GifImageView"><attr name="auto_play" format="boolean"></attr></declare-styleable></resources>2.⾃定义View中获取属性值private Movie mMovie;//播放动画需要⽤到的,系统类private int mImageWidth;//动画的imageview的宽度private int mImageHeight;//动画imageview的⾼度private long mMovieStart = 0;// 播放开始private boolean isAutoPlay;//是否⾃动播放private Bitmap mStartPlay;//开始按钮private boolean isPlaying=false;//记录是否正在播放private float mScale;//图⽚的缩放⽐private int mMeasuredGifWidth;//缩放后图⽚宽private int mMeasuredGifHeight;//缩放后图⽚⾼...private void init(Context context, AttributeSet attrs) {TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.GifImageView);// 通过反射拿布局中src的资源id,所以gif⽂件需要放在布局的src中int resourceId = getResourceId(attributes, context, attrs);if (resourceId != 0) {// 说明是gif动画// 1.将resourcesId变成流// 2.⽤Move来decode解析流// 3.获得bitmap的长宽InputStream is = getResources().openRawResource(resourceId);mMovie = Movie.decodeStream(is);if (mMovie != null) {Bitmap bitmap = BitmapFactory.decodeStream(is);mImageWidth = bitmap.getWidth();mImageHeight = bitmap.getHeight();// ⽤完释放bitmap.recycle();// 获得是否允许⾃动播放,如果不允许⾃动播放,则初始化播放按钮isAutoPlay = attributes.getBoolean(R.styleable.GifImageView_auto_play, false);if (!isAutoPlay) {mStartPlay = BitmapFactory.decodeResource(getResources(),R.drawable.start_play);setOnClickListener(this);}}}//回收资源attributes.recycle();}/*** 通过反射拿布局中src的资源id** @param attrs* @param context* @param attributes*/private int getResourceId(TypedArray attributes, Context context, AttributeSet attrs) {try {Field filed = TypedArray.class.getDeclaredField("mValue");filed.setAccessible(true);TypedValue typeValue = (TypedValue) filed.get(attributes);return typeValue.resourceId;} catch (Exception e) {e.printStackTrace();return 0;}3.重写onMesure()@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (mMovie != null) {/** Calculate horizontal scaling*/float scaleW = 1f;int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);if (measureModeWidth != MeasureSpec.UNSPECIFIED) {int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);scaleW = (float) mImageWidth / (float) maximumWidth;}/** calculate vertical scaling*/float scaleH = 1f;int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec); if (measureModeHeight != MeasureSpec.UNSPECIFIED) {int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);scaleH = (float) mImageHeight / (float) maximumHeight;}/** calculate overall scale*/mScale = 1f / Math.max(scaleH, scaleW);mMeasuredGifWidth = (int) (mImageWidth * mScale);mMeasuredGifHeight = (int) (mImageHeight * mScale);setMeasuredDimension(mMeasuredGifWidth, mMeasuredGifHeight);}}4.重写onDraw()@Overrideprotected void onDraw(Canvas canvas) {if (mMovie == null) {// mMovie等于null,说明是张普通的图⽚,则直接调⽤⽗类的onDraw()⽅法 super.onDraw(canvas);} else {// mMovie不等于null,说明是张GIF图⽚if (isAutoPlay) {// 如果允许⾃动播放,就播放playMovie(canvas);invalidate();} else {// 不允许⾃动播放的话// 1.判断是否正在播放// 2.获得第⼀帧的图像// 3.然后添加播放按钮if (isPlaying) {// 如果正在播放就playmoive继续播放if (playMovie(canvas)) {isPlaying = false;}invalidate();} else {// 第⼀帧mMovie.setTime(0);canvas.save(Canvas.MATRIX_SAVE_FLAG);canvas.scale(mScale, mScale);mMovie.draw(canvas, 0, 0);// 画canvas.restore();// 绘制开始按钮int offsetW = (mMeasuredGifWidth - mStartPlay.getWidth()) / 2;int offsetH = (mMeasuredGifHeight - mStartPlay.getHeight()) / 2;canvas.drawBitmap(mStartPlay, offsetW, offsetH, null);}}/*** 播放gif动画** @param canvas*/private boolean playMovie(Canvas canvas) {// 1.获取播放的时间// 2.如果开始start=0,则认为是开始// 3.记录播放的时间// 4.设置进度// 5.画动画// 6.如果时间⼤于了播放的时间,则证明结束long now = SystemClock.uptimeMillis();if (mMovieStart == 0) {mMovieStart = now;}int duration = mMovie.duration();if (duration == 0) {duration = 1000;}//记录gif播放了多少时间int relTime = (int) ((now - mMovieStart) % duration);mMovie.setTime(relTime);// 设置时间canvas.save(Canvas.MATRIX_SAVE_FLAG);canvas.scale(mScale, mScale);mMovie.draw(canvas, 0, 0);// 画canvas.restore();if ((now - mMovieStart) >= duration) {// 结束mMovieStart = 0;return true;}return false;}5.添加点击事件@Overridepublic void onClick(View v) {if(v.getId()==getId()){isPlaying=true;invalidate();}}还有⼀点需要注意,有些4.0以上系统的⼿机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁⽤硬件加速功能,可以通过指定android:hardwareAccelerated=false来完成。
Android基础篇之在ListView中显示网络图片
Android基础篇之在ListView中显示网络图片大家知道ImageView 类虽然有一个setImageUri 方法,但不能直接接受一个由网络地址生成的uri 作为参数从而显示图片,我们只好使用其 setImageBitmap 方法,如view plaincopy to clipboardprint?1.BitmapmBitmap=null;2.3.URLurl=new URL(imageUrl);4.5.HttpURLConnectionconn=(HttpURLConnection)url.openConnection();6.7.InputStream is=conn.getInputStream();8.9.mBitmap=BitmapFactory.decodeStream(is);在SimpleAdapter中需要一个数据源,用来存储数据的,在显示图片时我们要用HashMap<>存储一个Bitmap;但仅存取了Bitmap时在ListView中是无法显示图片的,我们需要对SimpleAdapter进行处理 。
如下是对SimpleAdaptr处理的主要代码:view plaincopy to clipboardprint?1.adapter.setViewBinder(new ViewBinder(){2.3.publicboolean setViewValue(Viewview,Objectdata,4.StringtextRepresentation){5.//判断是否为我们要处理的对象6.if(view instanceof ImageView&&data instanceof Bitmap){7.ImageViewiv=(ImageView)view;8.9.iv.setImageBitmap((Bitmap)data);10.returntrue;11.}else12.returnfalse;13.}14.});看API对Android.widget.SimpleAdapter.ViewBinder的解释:This class can be used by external clients of SimpleAdapter to bind values to views. You should use this class to bind values to views that are not directly supported by SimpleAdapter or to change the way binding occurs for views supported by SimpleAdapter.你可以使用该类来处理SimpleAdapter不直接支持的数据;下面来看看完整的代码:main.xml 中就是一个ListView , list_item.xml 是为ListView中控件提供布局 ,就是一个ImageView。
Android使用glide加载gif动画设置播放次数
Android使⽤glide加载gif动画设置播放次数在使⽤glide加载gif动画,有时需要设置播放的次数,然后播放玩⼀次或者⼏次之后,需要在播放完做⼀些其他的操作,直接看代码:Glide.with(this).load(R.drawable.xiaoguo).diskCacheStrategy(DiskCacheStrategy.SOURCE).listener(new RequestListener<Integer, GlideDrawable>() {@Overridepublic boolean onException(Exception arg0, Integer arg1,Target<GlideDrawable> arg2, boolean arg3) {return false;}@Overridepublic boolean onResourceReady(GlideDrawable resource,Integer model, Target<GlideDrawable> target,boolean isFromMemoryCache, boolean isFirstResource) {// 计算动画时长GifDrawable drawable = (GifDrawable) resource;GifDecoder decoder = drawable.getDecoder();for (int i = 0; i < drawable.getFrameCount(); i++) {duration += decoder.getDelay(i);}//发送延时消息,通知动画结束handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,duration);return false;}}) //仅仅加载⼀次gif动画.into(new GlideDrawableImageViewTarget(imageview, 1));glide简单加载动画⽤法:复制代码代码如下:Glide.with(MainActivity.this).load(url).asGif().into(imageView);如果添加.asGif(),这样的话就只能加载gif⽂件,如果不加,既可以加载图⽚也可以加载.gif。
加载gif动态图的三种方式
加载gif动态图的三种⽅式准备:本地图⽚资源,GifViewGifView代码:/*** 调⽤结束就开始播放动画,如果需要⽤户指定何时播放的话,只需要把timer的开始放到合适的位置。
通过对CFDictonaryRaf 也就是gifProperties的改变,我们还可以控制动画是否循环播放以及循环多少次停⽌。
通过对index的改变也可以控制动画从某帧开始播放。
同理,同时改变index和count的话,也可以控制从某帧到某帧的播放。
注意:- (void)stopGif;之后才可以退出这个类。
否则timer不会关闭,产⽣内存泄露。
*/#import <UIKit/UIKit.h>#import <ImageIO/ImageIO.h>@interface GifView : UIView {CGImageSourceRef gif; // 保存gif动画NSDictionary *gifProperties; // 保存gif动画属性size_t index;// gif动画播放开始的帧序号size_t count;// gif动画的总帧数NSTimer *timer;// 播放gif动画所使⽤的timer}- (id)initWithFrame:(CGRect)frame filePath:(NSString *)_filePath;- (id)initWithFrame:(CGRect)frame data:(NSData *)_data;- (void)stopGif;#import"GifView.h"#import <QuartzCore/QuartzCore.h>@implementation GifView- (id)initWithFrame:(CGRect)frame filePath:(NSString *)_filePath{self = [super initWithFrame:frame];if (self) {gifProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]forKey:(NSString *)kCGImagePropertyGIFDictionary];gif = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_filePath], (CFDictionaryRef)gifProperties);count =CGImageSourceGetCount(gif);timer = [NSTimer scheduledTimerWithTimeInterval:0.12 target:self selector:@selector(play) userInfo:nil repeats:YES];[timer fire];}return self;}- (id)initWithFrame:(CGRect)frame data:(NSData *)_data{self = [super initWithFrame:frame];if (self) {gifProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]forKey:(NSString *)kCGImagePropertyGIFDictionary];// gif = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_filePath], (CFDictionaryRef)gifProperties);gif = CGImageSourceCreateWithData((CFDataRef)_data, (CFDictionaryRef)gifProperties);count =CGImageSourceGetCount(gif);timer = [NSTimer scheduledTimerWithTimeInterval:0.12 target:self selector:@selector(play) userInfo:nil repeats:YES];[timer fire];}return self;}-(void)play{index ++;index = index%count;CGImageRef ref = CGImageSourceCreateImageAtIndex(gif, index, (CFDictionaryRef)gifProperties);yer.contents = (__bridge id)ref;CFRelease(ref);}-(void)removeFromSuperview{NSLog(@"removeFromSuperview");[timer invalidate];timer = nil;[super removeFromSuperview];}- (void)dealloc {NSLog(@"dealloc");CFRelease(gif);}- (void)stopGif{[timer invalidate];timer = nil;}加载Gif的三种⽅式:(从⽹络或者本地)- (NSData *)loadDataForIndex:(NSInteger)index {NSData *data = nil;if (index == 0) {//⽹络data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"/mw690/005APVsyzy6MFOsVFfv5d&690"]];}else {//本地data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"run" ofType:@"gif"]];}return data;}1.GifView//第三⽅GifView(实现gif动画播放是通过将动画⽂件读取到CGImageSourceRef,然后⽤NSTimer来播放的。
Android如何实现动态滚动波形图(心电图)功能
Android如何实现动态滚动波形图(⼼电图)功能⽬录⼀、前⾔⼆、效果图三、功能实现四、如何使⽤⼀、前⾔最近涉及的某个医疗相关的业务,传感器数据传递上来需要实现⽰波器的效果,⼼电图的效果,⽬前交付效果还算理想,于是封装了⼀下,⽅便⾃⼰以后使⽤,也给⼤家分享⼀下⼆、效果图图⼀是⼼电图效果,图⼆是⼀个滚动的波形图三、功能实现(⼀)绘制背景⽹格为了让他看上去像⽰波器上的数据,我们先绘制⼀层⽹格背景,看上去似乎就有那么点意思了在onLayout函数中获取控件宽⾼,然后除以默认⽹格的宽⾼,得出需要绘制横线和竖线的数量/** 根据⽹格的单位长宽,获取能绘制⽹格横线和竖线的数量*/gridHorizontalNum = (int) (mHeight / GRID_WIDTH);gridVerticalNum = (int) (mWidth / GRID_WIDTH);在onDraw函数中,通过for循环,来⼀条条绘制横线和竖线/*** 绘制⽹格** @param canvas*/private void drawGrid(Canvas canvas) {/** 设置颜⾊*/mLinePaint.setColor(gridLineColor);/** 绘制横线*/for (int i = 0; i < gridHorizontalNum + 1; i++) {canvas.drawLine(0, i * GRID_WIDTH,mWidth, i * GRID_WIDTH, mLinePaint);}/** 绘制竖线*/for (int i = 0; i < gridVerticalNum + 1; i++) {canvas.drawLine(i * GRID_WIDTH, 0,i * GRID_WIDTH, mHeight, mLinePaint);}}⽹格是静态的,所以绘制起来⽐较简单(⼆)绘制折线折线的绘制有两种模式,也就是效果图上下两种效果的区别原理也⽐较简单1、⾸先和绘制⽹格⼀样,在onLayout函数中根据每段数据线条的跨度,算出当前view能绘制多少条直线同时创建⼀个浮点类型的数组,⽤于保存每次传进来的数据/** 根据线条长度,最多能绘制多少个数据点*/row = (int) (mWidth / WAVE_LINE_WIDTH);dataArray = new float[row + 10];2、来看数据的保存⽅式⼼电图效果的保存⽅式是创建了⼀个索引,每次绘制后⾃增,索引达到数组的最⼤值时,赋值为0也就实现了循环的效果普通的滚动效果的,就是删除第⼀个,新增的数据添加⾄数组的末尾/*** 添加新的数据*/public void showLine(float line) {if (draw_index >= row) {draw_index = 0;}switch (drawMode){case 0:/** 常规模式数据添加⾄最后⼀位*/dataArray[row - 1] = line;break;case 1:/** 循环模式数据添加⾄当前绘制的位*/dataArray[draw_index] = line;break;}postInvalidate();}3、绘制折线的流程默认最⼤值为20,以view⾼度的⼀半处为0,下⽅是-20,上⽅是+20x没什么好说的,就是i*单位宽度y则为⾼度的⼀半减去数组中数据占view⼀半⾼度的⽐重将所有的点坐标传⼊Path类中,最后使⽤Canvas的drawPath函数就可以绘制出想要有的效果了 /*** 取数组中的指定⼀段数据来绘制折线* @param start 起始数据位* @param end 结束数据位* */private void drawPathFromDatas(Canvas canvas, int start, int end){mPath.reset();mPath.moveTo(start * WAVE_LINE_WIDTH, mHeight / 2);for (int i = start; i < end; i++) {nowX = i * WAVE_LINE_WIDTH;float dataValue = dataArray[i];/** 判断数据为正数还是负数超过最⼤值的数据按最⼤值来绘制*/if (dataValue > 0) {if (dataValue > MAX_VALUE) {dataValue = MAX_VALUE;}} else {if (dataValue < -MAX_VALUE) {dataValue = -MAX_VALUE;}}nowY = mHeight / 2 - dataValue * (mHeight / (MAX_VALUE * 2));mPath.lineTo(nowX, nowY);}canvas.drawPath(mPath, mWavePaint);}四、如何使⽤(⼀)添加库allprojects {repositories {...maven { url 'https://jitpack.io' }}}(⼆)布局⽂件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android" xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="波形图1"android:textColor="#000000"android:textSize="24sp" /><com.giftedcat.wavelib.view.WaveViewandroid:id="@+id/wave_view1"android:layout_width="match_parent"android:layout_height="1dp"android:layout_weight="1"app:draw_mode="loop"app:max_value="30"app:wave_background="#000000"app:wave_line_color="#ffff00"app:wave_line_width="20" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="波形图2"android:textColor="#000000"android:textSize="24sp" /><com.giftedcat.wavelib.view.WaveViewandroid:id="@+id/wave_view2"android:layout_width="match_parent"android:layout_height="1dp"android:layout_weight="1"app:draw_mode="normal"app:grid_visible="false"app:wave_line_stroke_width="5" /></LinearLayout>xml中可使⽤的参数<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="WaveView"><!--最⼤值默认为20,数据为-20 ~ 20--><attr name="max_value" format="integer" /><!--波形图折线单位宽度,通过修改该参数,控制横坐标的单位--><attr name="wave_line_width" format="integer" /><!--波形图折线的线宽--><attr name="wave_line_stroke_width" format="integer" /><!--波形图折线的颜⾊--><attr name="wave_line_color" format="string" /><!--背景⽹格图的颜⾊--><attr name="grid_line_color" format="string" /><!--背景颜⾊,默认为⿊--><attr name="wave_background" format="string"/><!--背景⽹格是否可见--><attr name="grid_visible" format="boolean" /><!--波形图绘制模式,常规和循环--><attr name="draw_mode" format="enum"><enum name="normal" value="0" /><enum name="loop" value="1" /></attr></declare-styleable></resources>(三)向波形图中添加数据data = new Random().nextFloat()*(20f)-10f;waveShowView.showLine(data);//取得是-10到10间的浮点数源码地址:到这⾥就结束啦.以上就是Android如何实现动态滚动波形图(⼼电图)功能的详细内容,更多关于Android 实现动态滚动波形图(⼼电图)功能的资料请关注其它相关⽂章!。
如何在android程序中显示图片
我们做Android 程序的时候,有时候需要显示图片在界面上,这里我们将实现一个将图片展示到手机屏幕,并让其不停的浮动的效果!首先我们要先准备一张图片,在这里我准备了一张图片,如下:将此图片放到文件夹"res->drawable-*dpi"下,记得,三个文件夹都要放,因为系统会根据不同的分辨率去取不同的图片,如果有的没放,在某些分辨率下,会找不到资源。
将此图片重命名为“pic.png”,在R.java里的drawable类里会生成一个pic的常量。
图片要显示,就是要容器可以让其显示,因为所有的Android 的UI组件都是继承自View,View也实现了Drawable接口,所以在此,我们也重新定义一个View让其用来显示我们的这张图片,并让这张图片浮动。
我们创建一个在包“org.leo.bitmap”下的,类名为“MovingPictureView”的类,该类继承自android.view.View。
此类目前代码大致如下:public class MovingPictureView extends View {public MovingPictureView(Context context) {super(context);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}}我们要重载他的“onDraw”方法,这个方法就是Android框架展现View的时候用来绘制显示内容那个的方法。
在此我们将他的所有方法体都删除掉(上面代码红色部分删掉),完全将其重写。
首先我们要创建一个图片对象,在Android里,所有位图图片都是使用Bitmap类来封装的,我们就先声明一个代表我们刚才图片的一个Bitmap对象,可通过以下方式声明:Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.pic);其中的“getResources()”方法,是有View提供的,可以根据此方法获得我们所有的资源,将来有机会再细说!有了bitmap对象,下一步就是将图片画到我们自己的View上了,看上面的“onDraw”方法,其中的参数是“Canvas”对象,其实就是提供了一个画板,有了画板我们就能画任何我们想画的东西了。
android中打开相机、打开相册进行图片的获取示例
android中打开相机、打开相册进⾏图⽚的获取⽰例这⾥介绍在Android中实现相机调取、拍照⽚、获取照⽚、存储新路径等已经打开相册、选择照⽚等功能⾸先看⼀下界⾯,很简单配置读取内存卡和调⽤照相头的功能<!-- 使⽤⽹络权限 --><uses-permission android:name="android.permission.INTERNET"/><!-- 写sd卡的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- 读sd卡权限 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />下⾯是代码的主题public class TakePhotos extends Activity implementsandroid.view.View.OnClickListener {Button takePhoto;Bitmap photo;String picPath;Button capture;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(yout.activity_photo);takePhoto = (Button) findViewById(R.id.button1);capture = (Button) findViewById(R.id.capture);takePhoto.setOnClickListener(this);capture.setOnClickListener(this);}@Overridepublic void onClick(View viewid) {switch (viewid.getId()) {case R.id.button1: {// 打开相机String state = Environment.getExternalStorageState();// 获取内存卡可⽤状态if (state.equals(Environment.MEDIA_MOUNTED)) {// 内存卡状态可⽤Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");startActivityForResult(intent, 1);} else {// 不可⽤Toast.makeText(TakePhotos.this, "内存不可⽤", Toast.LENGTH_LONG).show();}break;}case R.id.capture: {// 打开相册// 打开本地相册Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);// 设定结果返回startActivityForResult(i, 2);break;}default:break;}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);if (data != null) {switch (requestCode) {// 两种⽅式获取拍好的图⽚if (data.getData() != null || data.getExtras() != null) { // 防⽌没有返回结果Uri uri = data.getData();if (uri != null) {this.photo = BitmapFactory.decodeFile(uri.getPath()); // 拿到图⽚}if (photo == null) {Bundle bundle = data.getExtras();if (bundle != null) {photo = (Bitmap) bundle.get("data");FileOutputStream fileOutputStream = null;try {// 获取 SD 卡根⽬录⽣成图⽚并String saveDir = Environment.getExternalStorageDirectory()+ "/dhj_Photos";// 新建⽬录File dir = new File(saveDir);if (!dir.exists())dir.mkdir();// ⽣成⽂件名SimpleDateFormat t = new SimpleDateFormat( "yyyyMMddssSSS");String filename = "MT" + (t.format(new Date()))+ ".jpg";// 新建⽂件File file = new File(saveDir, filename);// 打开⽂件输出流fileOutputStream = new FileOutputStream(file);// ⽣成图⽚⽂件press(pressFormat.JPEG,100, fileOutputStream);// 相⽚的完整路径this.picPath = file.getPath();ImageView imageView = (ImageView) findViewById(R.id.imageView1); imageView.setImageBitmap(this.photo);} catch (Exception e) {e.printStackTrace();} finally {if (fileOutputStream != null) {try {fileOutputStream.close();} catch (Exception e) {e.printStackTrace();}}}Toast.makeText(getApplicationContext(), "获取到了",Toast.LENGTH_SHORT).show();} else {Toast.makeText(getApplicationContext(), "找不到图⽚",Toast.LENGTH_SHORT).show();}}}break;case 2: {//打开相册并选择照⽚,这个⽅式选择单张// 获取返回的数据,这⾥是android⾃定义的Uri地址Uri selectedImage = data.getData();String[] filePathColumn = { MediaStore.Images.Media.DATA };// 获取选择照⽚的数据视图Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);cursor.moveToFirst();// 从数据视图中获取已选择图⽚的路径int columnIndex = cursor.getColumnIndex(filePathColumn[0]);String picturePath = cursor.getString(columnIndex);cursor.close();// 将图⽚显⽰到界⾯上ImageView imageView = (ImageView) findViewById(R.id.imageView1); imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath)); break;}default:}}}}注释的很详细,⾃⼰分析吧。
修改安卓系统开机画面
Android系统开机动画包括两部分:开机显示的ANDROID 文字;ANDROID发光动画。
这篇文章说的开机动画是第一种,下面开始正文!1. 制作当前屏幕像素的图片(模拟器默认为320*480)使用PS制作一张320*480的图片,保存时选―保存为Web 所用格式‖,然后在弹开的窗口上,―预设‖项选择―PNG-24‖,保存为android_logo.png注:好像只支持png-24,其他格式生成的rle文件显示不正常,有兴趣大家可以再验证一下。
2. 将图片转换为raw格式使用linux下的ImageMagick自带的convert命令,进行raw格式转换,命令为:convert -depth 8 android_logo.png rgb:android_logo.raw注:ubuntu 10.04 默认已经安装ImgageMagick工具,如果当前系统没有安装,可以执行下面的命令安装:sudo apt-get install imagemagick3. 将raw格式转化为rle文件需要用到android编译后的rgb2565工具,在android/out/host/linux-x86/bin目录下(android为当前源码所在目录),转换命令如下:rgb2565 -rle < android_logo.raw > initlogo.rle到目前为止,启动需要显示的图像已经做好了,就是initlogo.rle,注意文件名必须是这个,如果想改文件名,需要修改android/system/core/init/init.h中的宏:#define INIT_IMAGE_FILE "/initlogo.rle"====================================================================== ======================下面需要将initlogo.rle加入的android文件系统中4. 找到ramdisk.img文件(android/out/target/product/generic/ramdisk.img),将文件名改为ramdisk.img.gz,然后使用下面的命令解压:gunzip ramdisk.img.gz解压后得到ramdisk.img,可能有人要问,怎么文件名又改回去了?其实不然,使用file ramdisk.img查看一下就知道了:解压前:ramdisk.img: gzip compressed data, from Unix解压后:ramdisk.img: ASCII cpio archive (SVR4 with no CRC)跑题了,还是说正事儿。
黑马程序员:Android 中的动画—帧动画
黑马程序员:Android 中的动画—帧动画Android 3.0以前,Android只支持两种动画模式,tween animation 和 frame animation,在Android 3.0 中又引入了一个新的动画系统:property animation。
Frame Animation(帧动画):创建一个Drawable 序列,这些 Drawable 可以按照指定的时间间隔,一个一个的显示,也就是顺序播放事先做好的图像。
Tween Animation(渐变动画也叫补间动画):通过对特定的对象做图像变换如平移、缩放、旋转、淡出/淡入等产生动画效果。
帧动画创建一个 Drawable 序列,这些 Drawable 可以按照指定的时间间隔一个一个的显示,也就是顺序播放事先准备好的图像,跟放胶片电影类似。
下面通过一个案例来演示帧动画的使用。
步骤:1.将准备好的图片资源放到 Android 工程的 res/drawable-hdpi 目录中。
2.在项目的 res 目录下创建文件夹 drawable,然后在文件夹下面定义动画 XML 文件,文件名称可以自定义(也可以使用 AnimationDrawable类,采用代码方式定义动画效果),这里给改xml 文件起名为frame_anim.xml,见文件 1-7。
【文件 1-7】frame_anim.xml1<?xml version="1.0"encoding="utf-8"?>2<animation-listxmlns:android="/apk/res/android"3android:oneshot="true">4<item android:drawable="@drawable/a1"android:duration="200"></item>5<item android:drawable="@drawable/a2"android:duration="200"></item> 6<!-----------------更多 item 不再展示--------------------->7</animation-list>3.打开创建好的 xml 文件,在里面添加根节点<animation-list>,可以在此根节点中设置属性” android:oneshot”来控制动画只播放一次,否则系统将默认持续播放。
Android中的动画(XML方式)实践(逐帧动画与补间动画)
Android中的动画(XML方式)实践(逐帧动画与补间动画)属性动画。
逐帧动画:基于单元格的动画,每一帧显示一个不同的drawable。
一帧一帧的顺序播放。
补间动画:补间动画应用于view,通过对其位置,大小,旋转和透明度的改变,让view动起来。
属性动画:属性动画几乎可以让应用程序中任何对象动起来。
所有补间动画的内容,都可以通过属性动画实现。
下面逐一介绍:注:这篇文章偏重于以xml方式实现相应动画效果。
逐帧动画逐帧动画(Frame-by-frame Animations)从字面上理解就是一帧一帧的播放图片,类似卡通动画。
目标:实现如下图效果:loading步骤:1.在res/drawable目录下新建loading_frame.xml文件:loading_frame.xml根节点是animation-list,内部由一到多个<item>节点组成oneshot属性表示是否只播放一次(true:一次;false:循环播放).item节点声明是一个动画帧,其中 android:drawable属性定义要显示的图像,android:druation代表此帧持续的时间,毫秒为单位。
注:在AndroidStudio中强制规定带animation-list节点xml文件必须放在res/drawable文件下(eclipse(ADT)貌似支持任意放res/drawable和res/anim)。
在androidStudio中若放在res/anim下会报错:错误提示:1错误提示:22.新建页面布局activity_frame.xml:如上图布局很简单上面一个imageview,下面两个button,都水平居中(相对于parent)。
3.新建FrameActivityframeActivity主要逻辑代码当然为了避免animationDrawable带来的内存泄露,建议在onDestroy方法中做如下操作:onDestroy注意:帧数比较多的动画不建议用逐帧动画实现,其一会显得卡顿,其二容易引起OOM。
MIUI V5 动态图标教程
MIUI V5新增动态图标,基于百变框架,和百变锁屏使用相同语法,所以有很高的灵活度,主题制作者可以轻松做出各种各样的动态图标。
每个动态图标是一个文件夹,和静态png图标同样的名字,没有后缀名,文件夹里面是manifest.xml和图片资源。
动态图标文件夹放在主题包的Icons模块下的fancy_icons目录下。
Icons| __ fancy_icons|__ com.android.calendar <--注意这个必须是文件夹!下面以日历图标为例:根节点Icon属性useVariableUpdater请参考1<?xml version="1.0" encoding="utf-8"?>2<!-- calendar -->3<Icon version="1" frameRate="0" width="136" height="136" screenWidth="720"useVariableUpdater="DateTime.Hour">4<Group pivotX="68" pivotY="68">5<Image x="68" y="68" align="center" alignV="center" src="calendar_icon.png"srcid="#date" />6</Group>7</Icon>复制代码附件中的示例图标是旧格式,后缀名为mfi,现在不再使用,请用zip软件直接解压后查看。
使用Lottie库在Android中实现动画
使用Lottie库在Android中实现动画在Android应用程序开发中,动画是提升用户体验和吸引用户的重要元素之一。
为了实现流畅且高品质的动画效果,开发者常常需要借助第三方库。
其中,Lottie库是一种颇受欢迎的选择,它允许开发者使用Adobe After Effects创建的动画并在Android应用中实现。
本文将介绍如何在Android中使用Lottie库实现动画效果。
一、概述Lottie是由Airbnb开发的开源动画库,它允许开发者将Adobe After Effects创建的动画导出为JSON格式,并在Android、iOS和Web等平台上进行渲染和播放。
其主要特点包括:1. 支持复杂的矢量动画,包括形状、路径、渐变、遮罩等效果;2. 动画文件体积小,加载速度快;3. 支持动画的播放、暂停、重复播放等交互操作;4. 提供可视化编辑器,方便开发者对动画进行预览和调整。
二、准备工作在开始之前,我们需要进行一些准备工作:1. 下载Lottie库:从Lottie的GitHub仓库中下载最新版本的Lottie 库,并将其导入到Android项目中。
2. 导入JSON动画文件:使用Adobe After Effects创建动画,并导出为JSON格式文件。
将该文件添加到Android项目的assets目录中。
三、集成Lottie库接下来,我们将介绍如何在Android项目中集成Lottie库,并实现动画效果。
1. 在build.gradle文件中添加Lottie库的依赖:```groovyimplementation 'com.airbnb.android:lottie:3.7.2'```2. 在布局文件中添加LottieView组件:```xml<com.airbnb.lottie.LottieAnimationViewandroid:id="@+id/animation_view"android:layout_width="match_parent"android:layout_height="match_parent"app:lottie_rawRes="@raw/animation_file" />```其中,`lottie_rawRes`属性指定了动画文件的资源ID。
android手把手开发一个图片浏览器
android手把手开发一个图片浏览器这次我给大家讲解一个Android图片浏览器的应用。
AndroidAndroid是基于Linux内核的软件平台和操作系统,早期由Google开发,后由开放手机联盟Open Handset Alliance)开发。
它采用了软件堆层(software stack,又名以软件叠层)的架构,主要分为三部分。
低层以Linux内核工作为基础,只提供基本功能;其他的应用软件则由各公司自行开发,以Java作为编写程序的一部分。
另外,为了推广此技术,Google和其它几十个手机公司建立了开放手机联盟。
Android在未公开之前常被传闻为Google电话或gPhone。
大多传闻认为Google开发的是自己的手机电话产品,而不是一套软件平台。
到了2010年1月,Google开始发表自家品牌手机电话的Nexus One。
目前最新版本为Android2.1。
下图是它的结构:简单来讲,Android就是一个开源的手机软件开发工具。
我主要给大家讲应用方面,大家如果有兴趣,可以了解相关基本知识。
要开发一个Android应用,首先得搭建Android开发环境:下载并安装Android sdk(Software Development Kit, 即软件开发工具包)。
由于Android 开发是集成在Eclipse中,需下载并安装ADT (Eclipse集成Android sdk插件)。
搭建环境会用一个专门的章节为大家详细讲解,这里我就不再赘述。
Android开发环境搭好后,我们先启动Eclipse创建一个Android的应用程序,然后在左上角单击File,New,Android Project,如下图所示:如果在图中Java Project找不到Android Project:在左上角单击File,New,Other:在弹出框中Android文件件中选中Android Project,然后单击Next进入下一步:弹出一个列表框:下面对这个列表的一些重要属性进行讲解:1.应用程序名称以及内容栏:2.工具栏:采用的编译工具即Android模拟器:3.属性栏:即应用程序中的相关属性:Android 这就是我们刚才创建的一个Android应用程序如下图:在这里面,我们最关心的是界面(main.xml)与后台(Test1.java):单击main.xml:我们先看看中间视图:这是一个页面编辑器模式:在左下角点击main.xml切换到界面编码模式:这就是刚才页面视图的源码:下面让我们看看后台(Test1.java)源码:单击Test1.java:以下将此类程序称之为activity(活动),该activity运行时会自动调用onCreate方法:而上图中onCreate方法是启动res文件夹下的layout下的main.xml界面。
什么是 GIF 文件?如何打开、编辑和转换 GIF 文件
什么是GIF文件?如何打开、编辑和转换GIF 文件在本文中•如何打开GIF 文件•如何转换GIF 文件•如何创建GIF 和下载免费GIF•有关GIF 文件的更多信息•额外:GIF 格式的历史一个文件与GIF文件的扩展名是一个图形交换格式文件。
尽管GIF 文件不包含音频数据,但它们经常被视为在线共享视频剪辑的一种方式。
网站也经常使用GIF 文件来显示动画对象,如按钮或标题图像。
由于GIF 文件以无损格式保存,因此与GIF 压缩一起使用时图像质量不会降低。
如何打开GIF 文件在您查看下面提到的程序之前,首先要确定您所追求的是什么。
您想要一个可以像视频或图像查看器一样播放GIF 的程序,还是可以让您编辑GIF 的程序?在几乎所有操作系统上,大多数网络浏览器(Chrome、Firefox、Internet Explorer 等)都可以毫无问题地打开在线GIF —您的计算机上不需要任何其他程序。
使用打开菜单或可能通过拖放到浏览器窗口中打开本地GIF 。
但是,对于Adobe Photoshop等其他应用程序,虽然该软件在技术上可以像打开其他图形一样打开GIF,但它并没有像您期望的那样真正显示GIF。
相反,它会在Photoshop 中将GIF 的每一帧作为单独的图层打开。
虽然这对于编辑GIF 非常有用,但对于在Web 浏览器中轻松播放/查看它却不是那么好。
除了基本的Web 浏览器之外,Windows 中的默认图形查看器(称为Microsoft Windows 照片)可能是在该操作系统中打开它们的最简单方法。
可以打开GIF 文件的其他一些适用于Windows 的程序包括Adobe 的Photoshop Elements 和Illustrator 程序、CorelDRAW、Corel PaintShop Pro、ACD Systems 的Canvas和ACDSee、Laughingbird 的The Logo Creator、Nuance 的PaperPort 和OmniPage Ultimate 以及Roxio Creator NXT Pro。
android 动画的实现原理
android 动画的实现原理Android动画的实现原理是通过改变视图的属性值来创建视觉效果。
在Android中,动画可以通过三种方式实现:补间动画、帧动画和属性动画。
1. 补间动画:补间动画是指通过指定开始和结束状态,系统会自动完成状态之间的过渡动画。
常用的补间动画包括平移动画、缩放动画、旋转动画和淡入淡出动画。
补间动画是通过对目标视图的transform属性进行变换来实现的,通过对动画的属性值进行插值计算,系统会将中间状态渐变地应用到目标视图上,从而实现动画效果。
2. 帧动画:帧动画是指将连续的图片资源按照一定时间间隔依次播放,从而形成动画效果。
帧动画是通过逐帧显示不同的图片资源来实现的。
在Android中,帧动画可以通过逐个资源文件的方式创建,也可以通过在XML文件中定义动画资源实现。
3. 属性动画:属性动画是Android3.0引入的一种动画机制,相较于补间动画和帧动画,属性动画更加强大和灵活。
属性动画通过修改目标视图的属性值来实现动画效果。
在属性动画中,可以通过指定目标视图的属性名称和起始值以及结束值,系统会自动根据这些信息来计算出中间过渡值,并将其应用到目标视图上。
属性动画可以实现更加复杂和精细的动画效果,例如借助关键帧来定义关键状态,或者通过设置动画插值器来控制动画的速度曲线。
总的来说,Android动画的实现原理是通过改变视图的属性值来实现动画效果。
不同的动画类型有不同的实现方式,包括补间动画、帧动画和属性动画。
补间动画是通过对目标视图的属性进行变换来实现的,帧动画是逐帧显示不同的图片资源,而属性动画是通过修改目标视图的属性值来实现动画效果。
Android实现图片反转、翻转、旋转、放大和缩小
Android实现图⽚反转、翻转、旋转、放⼤和缩⼩**********************************************************************android 实现图⽚的翻转**********************************************************************Resources res = this.getContext().getResources();img = BitmapFactory.decodeResource(res, R.drawable.aa);Matrix matrix = new Matrix();matrix.postRotate(180); /*翻转180度*/int width = img.getWidth();int height = img.getHeight();img_a = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);然后可以直接把img_a draw到画布上,canvas.drawBitmap(img_a, 10, 10, p);Matrix 是⼀个处理翻转、缩放等图像效果的重要类,Matrix.postScale 可设置缩放⽐例,默认为1**********************************************************************android 实现图⽚的旋转**********************************************************************public class ex04_22 extends Activity{private ImageView mImageView;private Button btn1,btn2;private TextView mTextView;private AbsoluteLayout layout1;private int ScaleTimes=1,ScaleAngle=1;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);mImageView=(ImageView)findViewById(R.id.myImageView);final Bitmap bmp=BitmapFactory.decodeResource(this.getResources(),R.drawable.ex04_22_1);final int widthOrig=bmp.getWidth();final int heightOrig=bmp.getHeight();mImageView.setImageBitmap(bmp);btn1=(Button)findViewById(R.id.myButton1);btn1.setOnClickListener(new OnClickListener(){public void onClick(View v){ScaleAngle--;if(ScaleAngle<-60){ScaleAngle=-60;}int newWidth=widthOrig*ScaleTimes;int newHeight=heightOrig*ScaleTimes;float scaleWidth=((float)newWidth)/widthOrig;float scaleHeight=((float)newHeight)/heightOrig;Matrix matrix=new Matrix();matrix.postScale(scaleWidth, scaleHeight);matrix.setRotate(5*ScaleAngle);Bitmap resizeBitmap=Bitmap.createBitmap(bmp, 0, 0, widthOrig, heightOrig, matrix, true);BitmapDrawable myNewBitmapDrawable=new BitmapDrawable(resizeBitmap);mImageView.setImageDrawable(myNewBitmapDrawable);}});btn2=(Button)findViewById(R.id.myButton2);btn2.setOnClickListener(new OnClickListener(){public void onClick(View v){ScaleAngle++;if(ScaleAngle>60){ScaleAngle=60;}int newWidth=widthOrig*ScaleTimes;int newHeight=heightOrig*ScaleTimes;float scaleWidth=((float)newWidth)/widthOrig;float scaleHeight=((float)newHeight)/heightOrig;Matrix matrix=new Matrix();matrix.postScale(scaleWidth, scaleHeight);matrix.setRotate(5*ScaleAngle);Bitmap resizeBitmap=Bitmap.createBitmap(bmp, 0, 0, widthOrig, heightOrig, matrix, true);BitmapDrawable myNewBitmapDrawable=new BitmapDrawable(resizeBitmap);mImageView.setImageDrawable(myNewBitmapDrawable);}});}**********************************************************************实现画⾯淡⼊淡出效果可以⽤:setAlpha(alpha);alpha从255,逐渐递减!**********************************************************************如何实现屏幕的滚动效果,这⾥有两个关键点,⼀个是实现OnGestureListener,以便在触摸事件发⽣的时候,被回调。
Android加载GIF图最佳实践方案
Android加载GIF图最佳实践⽅案起因最近在项⽬中遇到需要在界⾯上显⽰⼀个本地的 GIF 图。
按照惯例我直接⽤了 Glide 框架来实现。
我⽤的 Glide版本为 4.0.0-RC1 ,具体的实现代码如下:Glide.with( this ).asGif().load( R.drawable.yiba_location ).into( location_image ) ;运⾏的效果很卡顿,我怀疑是不是⽅法没有⽤对,调了压缩模式,还是卡顿;调了缓存模式,还是卡顿。
看了⼀下我的 gif 图,⼤⼩还是 800K ,是不是图⽚太⼤了,换了⼀张 100K 的 gif 图,这次显⽰的效果很好,gif 图播放的很流畅。
⾄此,得出结论:Glide 框架⾃⾝的原因,播放⼤尺⼨的 Gif 图的效果不是很理想。
⽅案Glide 不⾏,那么就要另想其他⽅案,就去 github 上找⼀下。
排名第⼀的 android-gif-drawable 库 start 有 4.8K ,这个应该不错,试试吧。
引⽤:compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.7'直接把布局⽂件中的 ImageView 替换为 GifImageView<pl.droidsonroids.gif.GifImageViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/yiba_location "/>运⾏起来看看,果然很好啊,播放的很流畅,果断采⽤此⽅案。
探寻其他的属性:GifImageView gifImageView = (GifImageView) findViewById(R.id.gifImageView);GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable();通过 GifImageView 对象获取到 GifDrawable 对象。
android动态壁纸实现原理
Android动态壁纸(Live Wallpaper)是一种在设备的主屏幕上提供动画或互动效果的背景。
实现Android动态壁纸的原理涉及使用特定的API和开发技术。
以下是实现Android动态壁纸的基本原理:使用WallpaperService:Android动态壁纸是通过继承WallpaperService类实现的。
WallpaperService是一个抽象类,用于提供后台服务,处理壁纸的生命周期和绘制逻辑。
创建壁纸引擎(Wallpaper Engine):在WallpaperService中,你需要创建一个壁纸引擎,继承自Engine类。
壁纸引擎负责处理与动态壁纸相关的逻辑,包括绘制、处理用户输入等。
实现SurfaceView或GLSurfaceView:为了在壁纸上进行绘制,你需要创建一个SurfaceView 或GLSurfaceView。
SurfaceView是基于2D绘制,而GLSurfaceView则是基于OpenGL ES进行3D绘制。
你需要根据你的需求选择合适的视图。
处理生命周期方法:在壁纸引擎中,你需要实现一些生命周期方法,如onCreate()、onSurfaceCreated()、onSurfaceChanged()和onDraw()等。
这些方法用于初始化、处理Surface 的创建和变化,以及绘制壁纸内容。
注册壁纸:在AndroidManifest.xml文件中注册你的壁纸服务。
这样系统就能够识别你的应用程序作为一个动态壁纸提供者。
以下是一个简单的伪代码示例,演示了动态壁纸的基本结构:public class MyWallpaperService extends WallpaperService {@Overridepublic Engine onCreateEngine() {return new MyWallpaperEngine();}private class MyWallpaperEngine extends Engine {private SurfaceView surfaceView;@Overridepublic void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);// 初始化壁纸逻辑surfaceView = new SurfaceView(getApplicationContext());// 设置SurfaceView的持有者setSurfaceHolder(surfaceHolder);}@Overridepublic void onSurfaceCreated(SurfaceHolder holder) {super.onSurfaceCreated(holder);// 处理Surface创建逻辑}@Overridepublic void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height);// 处理Surface变化逻辑}@Overridepublic void onDraw(Canvas canvas) {// 在这里绘制壁纸内容}}}需要注意的是,实际的实现可能涉及更多的细节和复杂性,具体取决于你的动态壁纸的需求。
android livephoto 原理
android livephoto 原理
Android LivePhoto原理
Android LivePhoto是一种可以在照片中添加动态元素的特殊效果。
它使得照片
可以捕捉到更多的细节和动态,并通过与用户的交互来展示出这些动态。
实现Android LivePhoto的原理如下:
1. 动态图片采集: Android LivePhoto通过相机或者其他方式采集到瞬间连续的
图片帧。
这些帧可以是连续的视频帧,也可以是一系列连续拍摄的照片。
2. 图像处理: 采集到的图片帧会经过一系列的图像处理算法,包括图像增强、
降噪等。
这些算法可以提高图片的质量,并为后续的处理做准备。
3. 动态元素提取: 在图像处理之后,Android LivePhoto会根据用户的需求和选择,从连续的图片帧中提取出需要的动态元素。
这些元素可以是移动的物体、变化的背景等。
4. 动态元素合成: 提取到的动态元素会经过图像合成算法与原始照片进行融合。
这样,动态元素就会以一种平滑的方式与静态照片相结合。
5. 动态展示: 最后,生成的LivePhoto可以在支持该格式的设备上进行播放。
用户可以通过点击或滑动来触发动态元素的展示。
总结一下,Android LivePhoto的原理是通过采集连续的图片帧,提取动态元素
并与原始照片进行合成,最终实现动态展示。
它为用户提供了一种在照片中添加动态元素的方式,使得照片更富有生命力和趣味性。
gif格式的数据结构及显示流程
gif格式的数据结构及显示流程GIF(Graphics Interchange Format)是一种常见的图像文件格式,广泛应用于网站、应用程序和电子邮件等多种场景。
本文将介绍GIF格式的数据结构及其显示流程,以帮助读者更好地理解和应用GIF图像。
一、GIF格式的数据结构GIF格式的文件由一个个数据块组成,每个数据块都有特定的含义和功能。
下面是GIF格式的数据结构的主要组成部分:1. 文件头(File Header):GIF文件的起始部分,通常由6个字节组成。
其中包含文件的标识符("GIF89a"或"GIF87a")、图像的宽度和高度等基本信息。
2. 逻辑屏幕描述符(Logical Screen Descriptor):紧随文件头之后的数据块。
主要记录了图像的宽度和高度、全局颜色表等信息。
3. 全局颜色表(Global Color Table):位于逻辑屏幕描述符之后,包含一系列颜色信息。
GIF图像中的像素可以使用全局颜色表中的索引值表示具体的颜色,这样可以大大减小图像文件的大小。
4. 图像描述符(Image Descriptor):每个图像块的描述符,包含图像的位置、宽度和高度,以及局部颜色表的信息。
5. 图像数据(Image Data):图像块的实际像素数据,通过一系列的编码算法进行压缩。
GIF格式采用了一种称为LZW压缩算法的方法,可以有效地减小文件的大小。
6. 图形控制扩展块(Graphic Control Extension):可选的块,用于设置图像显示的一些特殊效果,例如透明度和循环播放等。
7. 应用扩展块(Application Extension):可选的块,用于定义图像的特殊应用场景,例如动画或渐变效果等。
8. 注释块(Comment Extension):可选的块,用于添加注释信息,方便图像的维护和理解。
二、GIF图像的显示流程在了解了GIF格式的数据结构后,我们来看一下GIF图像的显示流程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
R.styleable.GifView); //这里用到了attrs.xml里面定义的GifView
int taCount = ta.length(); //获得属性的个数
gifMovie.setTime(relTime); //设置播放时间点
gifMovie.draw(canvas, getWidth() - gifMovie.width(), //播放(即绘画)
getHeight() - gifMovie.height());
for (int i=0;i<taCount;i++){ //处理所有属性,由于我只定义了一个src属性,所以就只处理src属性
if (R.styleable.GifView_src == ta.getIndex(i)) {
int id = ta.getResourceId(R.styleable.GifView_src, 0); //这里的参数是前面的GifView + _ + src链接起来
即gif为自己定义的namespace,com.gif.demo对应于自己的包名,即activity对应的包名
最后在activity里面setContentView(yout.main)就ok了为的)
android里面有一个Movie类,可以使用它来播放gif动画(此类位于android.graphics包下)
Movie具体怎么播放在后面讲解
既然播放gif动画图片的方法找到了,那如果我想在xml文件中动态加入*.gif文件的话,就需要自定义一个控件
android显示gif图片
由于android所带的控件里面没有能够显示gif图片的
今天闲来无事,就来网上查查资料,打算搞一个能显示gif图片的自定义控件
网上的解决方法大致有三种
第一:先将gif图片分拆为N帧(由美工/软件完成),然后逐次播放;
第二:利用java代码将图片分拆为N帧;
前面两种的思路是一样的,第二种网上已经有朋友做出jar包出来了,感兴趣的朋友可以去下来看看
if (0 != id) {
setSrc(id); //对应的函数,即在xml里面设置了src,相应的处理就会在setSrc函数里面进行
}
}
}
ta.recycle();
}
下面是setSrc函数:
public void setSrc(int id){
android:layout_width="wrap_content"
android:layout_height="wrap_content"
gif:src="@drawable/lion"
/>
</LinearLayout>
其中xmlns:gif="/apk/res/com.gif.demo"
xmlns:gif="/apk/res/com.gif.demo"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
long now = android.os.SystemClock.uptimeMillis(); //获得当前时间
if (lStartTime == 0) { // first time
lStartTime = now;
}
if (gifMovie != null) {
gifMovie = Movie.decodeStream(getResources().openRawResource(id)); //gifMovie为Movie类型
}
接下来是view的onDraw函数,这也是绘画动画的关键
public void onDraw(Canvas canvas){
invalidate();
}
}
下面在main.xml文件里面加入自定义的GifView控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="/apk/res/android"
(或者说自己写一个类,继承view/ImageView),我这里继承的View。
现在问题出现了,ImageView里面设置图片用的是src或者background属性,那我们自定义的就不能使用这两个属性了,所以需要自己自定义属性。
ok,现在思路定下来了,为了显示gif图片,我们需要用到Movie类和自定义控件(包括自定义属性)
int dur = gifMovie.duration(); //获得gif文件的动画周期
if (dur == 0) {
dur = 1000;
}
int relTime = (int)((now - lStartTime) % dur);
</declare-styleable>
这里我只增加了一个属性,就是设置src文件。
属性设置好了,那怎么将这个src属性与java代码对应起来呢,这个就需要到构造函数里面处理了
public GifView(Context context, AttributeSet attrs){
super(context, attrs);
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<com.gif.demo.GifView
首先,我们来自定义控件属性:
在res/values里面建立xml文件,习惯性命名为attrs.xml(可以命名为其他名字)
在attrs.xml里面增加属性如下:
<declare-styleable name="GifView">
<attr name="src" format="integer" />