1. android如何在imageview控件上绘制点
android:scaleType:
android:scaleType是控制图片如何resized/moved来匹对ImageView的size。
ImageView.ScaleType / android:scaleType值的意义区别:
CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽 FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
FIT_XY / fitXY 把图片?不按比例扩大/缩小到View的大小显示
MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。 ** 要注意一点,
Drawable文件夹里面的图片命名是不能大写的
2. android ImageView控件,图片如何铺满整个控件
android imageView有一个属性就是scaleType扩大类型,使用fitXy值就可以实现铺满整个空间,操作如下:在ImageView里加上android:scaleType="fitXy"。x0dx0a 默认还有其他很多类型:scaleType=“matrix” 是保持原图大小、从左上角的点开始,以矩阵形式绘图。x0dx0ax0dx0ascaleType=“fitXY” 是将原图进行横方向(即XY方向)的拉伸后绘制的。x0dx0ax0dx0ascaleType=“fitStart” 是将原图沿左上角的点(即matrix方式绘图开始的点),按比例缩放原图绘制而成的。
3. android 如何重写imageview 让图片有圆角效果
android 自定义圆角ImageView以及锯齿的处理
看到很多人开发过程中要使用圆角图片时,解决方法有:
1.重新绘制一张图片
2.通过布局来配置
3.通过重写View来实现
其中1,2在这里就不讲了,重点讲讲方法三的实现。
实现一:通过截取画布一个圆形区域与图片的相交部分进行绘制,缺点:锯齿明显,设置Paint,Canvas抗锯齿无效。
package com.open.circleimageview.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.View;
public class CircleImageViewA extends View {
public CircleImageViewA(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CircleImageViewA(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleImageViewA(Context context) {
super(context);
}
private Bitmap bitmap;
private Rect bitmapRect=new Rect();
private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
private Paint paint = new Paint();
{
paint.setStyle(Paint.Style.STROKE);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了
}
private Path mPath=new Path();
public void setImageBitmap(Bitmap bitmap)
{
this.bitmap=bitmap;
}
@Override
protected void onDraw(Canvas canvas) {
if(null==bitmap)
{
return;
}
bitmapRect.set(0, 0, getWidth(), getHeight());
canvas.save();
canvas.setDrawFilter(pdf);
mPath.reset();
canvas.clipPath(mPath); // makes the clip empty
mPath.addCircle(getWidth()/2, getWidth()/2, getHeight()/2, Path.Direction.CCW);
canvas.clipPath(mPath, Region.Op.REPLACE);
canvas.drawBitmap(bitmap, null, bitmapRect, paint);
canvas.restore();
}
}
实现二:通过PorterDuffXfermode 方式(注意要设置硬件加速,否则部分机子无效),优点:锯齿基本没有
package com.open.circleimageview.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
public class CircleImageViewB extends View {
public CircleImageViewB(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CircleImageViewB(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CircleImageViewB(Context context) {
super(context);
init();
}
private Bitmap bitmap;
private Rect bitmapRect=new Rect();
private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
private Paint paint = new Paint();
{
paint.setStyle(Paint.Style.STROKE);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了
}
private Bitmap mDstB=null;
private PorterDuffXfermode xfermode=new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY);
private void init()
{
try {
if(android.os.Build.VERSION.SDK_INT>=11)
{
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setImageBitmap(Bitmap bitmap)
{
this.bitmap=bitmap;
}
private Bitmap makeDst(int w, int h)
{
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.parseColor("#ffffffff"));
c.drawOval(new RectF(0, 0, w, h), p);
return bm;
}
@Override
protected void onDraw(Canvas canvas) {
if(null==bitmap)
{
return;
}
if(null==mDstB)
{
mDstB=makeDst(getWidth(), getHeight());
}
bitmapRect.set(0, 0, getWidth(), getHeight());
canvas.save();
canvas.setDrawFilter(pdf);
canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(xfermode);
canvas.drawBitmap(bitmap, null, bitmapRect, paint);
paint.setXfermode(null);
canvas.restore();
}
}
4. android imageview怎么画动图
1、Fragment 添加一层 点击设置可见与否 2、也可以设置2张图片 点击做切换 实现效果
5. android如何实现一个圆形imageview应该怎么做
android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap,然后进行裁剪圆形的bitmap,然后在onDraw()进行绘制圆形图片输出。
6. android开发在ImageView控件上绘制点的问题
写一个继承自ImageView的类 ,重写其OnTouch()和OnDraw()类,前一个获取触空点,后一个画出在这个点 。
7. Android如何做到随着ImageView的移动画出移动轨迹
运行效果是这样的(文字说明):
首次进入程序,手指点击屏幕上的任意位置,图片会随之移动。
布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/FrameLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#f0f0f0" >
<com.sgw.move.MoveImageView
android:id="@+id/ImageView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon" >
</com.sgw.move.MoveImageView>
</FrameLayout>
实现代码
public class MoveImageView extends ImageView {
public MoveImageView(Context context) {
super(context);
}
public MoveImageView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
}
public MoveImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setLocation(int x, int y) {
this.setFrame(x, y - this.getHeight(), x + this.getWidth(), y);
}
// 移动
public boolean autoMouse(MotionEvent event) {
boolean rb = false;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
this.setLocation((int) event.getX(), (int) event.getY());
rb = true;
break;
}
return rb;
}
}
public class TestImageViewMove extends Activity {
private MoveImageView moveImageView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
moveImageView = (MoveImageView) this.findViewById(R.id.ImageView01);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
moveImageView.autoMouse(event);
return false;
}
}
以上内容给大家介绍了基于Android实现随手指移动的ImageView的相关知识,希望本文分享对大家有所帮助。
8. Android开发之ImageView播放GIF动画实例
Android开发之ImageView播放GIF动画实例
Android的原生控件并不支持播放GIF格式的图片,如果想在Android中显示一张GIF动态图片,可以利用 ImageView控件来完成,但是放进去之后,你会发现,ImageView它只会显示这张图片的第一帧,不会产生任何的动画效果。我们必须通过自定义控件的方式来实现ImageView播放GIF 图片的功能。
首先我们来编写一个PowerImageView控件,让它既能支持ImageView控件原生的所有功能,同时还可以播放GIF动态图片。
先新建一个项目PowerImageViewTest,这里使用Android 4.0+Eclipse。
由于是要自定义控件,会需要一些自定义的控件属性,因此我们需要在values目录下新建一个attrs.xml的文件,在这个文件中添加项目需要的自定义属性。
这里我们目前暂时只需要一个自动播放auto_play属性,XML文件代码如下:
<?xml version="1.0" encoding="utf-8"?>
这个文件完成之后,下面我们来开始编写主类PowerImageView类,由于PowerImageView类需要支持ImageView的所有功能,我们必须要让PowerImageView继承自ImageView,代码如下:
public class PowerImageView extends ImageView implements OnClickListener {
/**
* 播放GIF动画的关键类
*/
private Movie mMovie;
/**
* 开始播放按钮图片
*/
private Bitmap mStartButton;
/**
* 记录动画开始的时间
*/
private long mMovieStart;
/**
* GIF图片的宽度
*/
private int mImageWidth;
/**
* GIF图片的高度
*/
private int mImageHeight;
/**
* 图片是否正在播放
*/
private boolean isPlaying;
/**
* 是否允许自动播放
*/
private boolean isAutoPlay;
/**
* PowerImageView构造函数。
*
* @param context
*/
public PowerImageView(Context context) {
super(context);
}
/**
* PowerImageView构造函数。
*
* @param context
*/
public PowerImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* PowerImageView构造函数,在这里完成所有必要的初始化操作。
*
* @param context
*/
public PowerImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PowerImageView);
int resourceId = getResourceId(a, context, attrs);
if (resourceId != 0) {
// 当资源id不等于0时,就去获取该资源的流
InputStream is = getResources().openRawResource(resourceId);
// 使用Movie类对流进行解码
mMovie = Movie.decodeStream(is);
if (mMovie != null) {
// 如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
isAutoPlay = a.getBoolean(R.styleable.PowerImageView_auto_play, false);
Bitmap bitmap = BitmapFactory.decodeStream(is);
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
bitmap.recycle();
if (!isAutoPlay) {
// 当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
mStartButton = BitmapFactory.decodeResource(getResources(),R.drawable.start_play);
setOnClickListener(this);
}
}
}
}
@Override
public void onClick(View v) {
if (v.getId() == getId()) {
// 当用户点击图片时,开始播放GIF动画
isPlaying = true;
invalidate();
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mMovie == null) {
// mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
super.onDraw(canvas);
} else {
// mMovie不等于null,说明是张GIF图片
if (isAutoPlay) {
// 如果允许自动播放,就调用playMovie()方法播放GIF动画
playMovie(canvas);
invalidate();
} else {
// 不允许自动播放时,判断当前图片是否正在播放
if (isPlaying) {
// 正在播放就继续调用playMovie()方法,一直到动画播放结束为止
if (playMovie(canvas)) {
isPlaying = false;
}
invalidate();
} else {
// 还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮
mMovie.setTime(0);
mMovie.draw(canvas, 0, 0);
int offsetW = (mImageWidth - mStartButton.getWidth()) / 2;
int offsetH = (mImageHeight - mStartButton.getHeight()) / 2;
canvas.drawBitmap(mStartButton, offsetW, offsetH, null);
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mMovie != null) {
// 如果是GIF图片则重写设定PowerImageView的大小
setMeasuredDimension(mImageWidth, mImageHeight);
}
}
/**
* 开始播放GIF动画,播放完成返回true,未完成返回false。
*
* @param canvas
* @return 播放完成返回true,未完成返回false。
*/
private boolean playMovie(Canvas canvas) {
long now = SystemClock.uptimeMillis();
if (mMovieStart == 0) {
mMovieStart = now;
}
int ration = mMovie.ration();
if (ration == 0) {
ration = 1000;
}
int relTime = (int) ((now - mMovieStart) % ration);
mMovie.setTime(relTime);
mMovie.draw(canvas, 0, 0);
if ((now - mMovieStart) >= ration) {
mMovieStart = 0;
return true;
}
return false;
}
/**
* 通过Java反射,获取到src指定图片资源所对应的id。
*
* @param a
* @param context
* @param attrs
* @return 返回布局文件中指定图片资源所对应的id,没有指定任何图片资源就返回0。
*/
private int getResourceId(TypedArray a, Context context, AttributeSet attrs) {
try {
Field field = TypedArray.class.getDeclaredField("mValue");
field.setAccessible(true);
TypedValue typedValueObject = (TypedValue) field.get(a);
return typedValueObject.resourceId;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (a != null) {
a.recycle();
}
}
return 0;
}
}
这个类的代码注释已经非常详细了,我再来简单地解释一下。可以看到,我们重写了ImageView中所有的构建函数,使得 PowerImageView的用法可以和ImageView完全相同。在构造函数中,则是对所有必要的数据进行了初始化操作。首先,我们调用了 getResourceId()方法去获取图片资源对应的id值,在getResourceId()方法内部是通过Java的反射机制来进行获取的。得到了图片资源的id后,我们将它转换成InputStream,然后传入到Movie.decodeStream()方法中以解码出Movie对象。如果得到的Movie对象等于null,说明这是一张普通的图片资源,就不再进行任何特殊处理,因为父类ImageView都帮我们处理好了。如果得到的 Movie对象不等于null,则说明这是一张GIF图片,接着就要去获取是否允许自动播放、图片的宽高等属性的值。如果不允许自动播放,还要给播放按钮 注册点击事件,默认是不允许自动播放的。
接下来会进入到onMeasure()方法中。在这个方法中我们进行判断,如果这是一张GIF图片,则需要将PowerImageView的宽高重定义,使得控件的大小刚好可以放得下这张GIF图片。
再往后就会进入到onDraw()方法中。在这个方法里同样先判断当前是一张普通的图片还是GIF图片,如果是普通的图片就直接调用 super.onDraw()方法交给ImageView去处理就好了。如果是GIF图片,则先判断该图是否允许自动播放,允许的话就调用 playMovie()方法去播放GIF图片就好,不允许的话则会先在PowerImageView中绘制该GIF图片的第一帧,并在图片上绘制一个播放 按钮,当用户点击了播放按钮时,再去调用playMovie()方法去播放GIF图片。
下面我们来看看playMovie()方法中是怎样播放GIF图片的吧。可以看到,首先会对动画开始的时间做下记录,然后对动画持续的时间做下记 录,接着使用当前的时间减去动画开始的时间,得到的时间就是此时PowerImageView应该显示的那一帧,然后借助Movie对象将这一帧绘制到屏 幕上即可。之后每次调用playMovie()方法都会绘制一帧图片,连贯起来也就形成了GIF动画。注意,这个方法是有返回值的,如果当前时间减去动画 开始时间大于了动画持续时间,那就说明动画播放完成了,返回true,否则返回false。
完成了PowerImageView的编写,下面我们就来看一看如何使用它吧,其实非常简单,打开或新建activity_main.xml,代码如下所示:
<relativelayout p=""
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/anim"
/>
可以看到,PowerImageView的用法和ImageView几乎完全一样,使用android:src属性来指定一张图片即可,这里指定的anim就是一张GIF图片。然后我们让PowerImageView在布局里居中显示MainActivity中的代码都是自动生成的,这里就不再贴出来了。在AndroidManifest.xml中还有一点需要注意,有些4.0 以上系统的手机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁用硬件加速功能,可以通过指定android:hardwareAccelerated属性来完成,代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest p=""
package="com.example.powerimageviewtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk p=""
android:minSdkVersion="14"
android:targetSdkVersion="17" />
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="false"
>
android:name="com.example.powerimageviewtest.MainActivity"
android:label="@string/app_name" >
现在可以来运行一下代码了,一打开程序你就会看到GIF图片的第一帧,点击图片之后就可以播放GIF动画了。
然后我们还可以通过修改activity_main.xml中的代码,给它加上允许自动播放的属性,代码如下所示:
<relativelayout p=""
xmlns:attr="http://schemas.android.com/apk/res/com.example.powerimageviewtest"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/anim"
attr:auto_play="true"
/>
这里使用了刚才我们自定义的属性,通过attr:auto_play来启用和禁用自动播放功能。现在将auto_play属性指定成true后,PowerImageView上就不会再显示一个播放按钮,而是会循环地自动播放动画。不仅如此,PowerImageView还继承了ImageView原生的所有功能,只要指定的不是GIF图 片,PowerImageView表现的结果就和ImageView完全一致,现在我们来放一张普通的PNG图片,修改 activity_main.xml中的代码,如下所示:
<relativelayout p=""
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.powerimageviewtest.powerimageview p=""
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/myphoto"
/>
这里在src属性里面指定了一张名字为myphoto的PNG图片,图片在布局正中央显示出来了,正是普通ImageView所具备的功能。我们还可以在PowerImageView中指定android:scaleType等属性,用法和原生的ImageView完全一样。
9. 图文讲解Android ImageView的ScaleType,帮你彻底搞明白
一般来说,要把一张图片显示在ImageView上,有下面几个问题需要考虑:
在真实的产品环境中,一个ImageView的大小往往都是有限制的,至少长或宽有一条边是有限制的,所以,在ImageView上显示图片还需要考虑:
第二个问题,还可以细化成:
怎么样,简单的一个显示图片操作,就有这么多细节需要考虑。下面的章节,我们就抓住上面几点,通过实际的例子帮你理解ScaleType的各个属性值。
首先看下实际效果:
一句话总结FIT_XY:就是以不按原比例伸缩为代价,强制让图片充满ImageView ,同时图片所有的部分也会完整显示出来(虽然可能变形)。但是,因为其不按原比例伸缩的特点,真实的产品中不太常用,因为图片被拉伸变形往往是不可以接受的。(上面例子中的美女已经被拉伸的不成样子了)
还是先看下例子:
这个属性值的名称虽然是CENTER,但是和一般意义上的“居中”有很大不同。 这个属性值即不会保证填满ImageView,也不保证图片会完整显示。 当实际图片比ImageView小的时候,就是“居中显示”。当图片比ImageView大,就把图片中间的部分显示在ImageView里,其他的裁剪掉不显示。(上面第二组图尤其明显)
先看例子:
FIT_CENTER更接近于大家理解的“居中显示”,也是平时用的最多的一个值。 首先,这个属性会保证图片完整显示,不管图片和ImageView的大小关系。而且伸缩的时候是按照比例做的,所以图片质量也可以得到保证。 唯一的问题是,FIT_CENTER不保证会填满ImageView。对于大多数场景,这个也足够了。
FIT_START,FIT_END和FIT_CENTER差不多,就不详细介绍了。
先看例子:
CENTER_CROP,是个非常重要的值,但是很多同学对它并不是很了解。首先,这个属性值的名字很奇怪,很难猜出来其真实的含义;其次,它的官方介绍简直又臭又长,让人一头雾水:
其实,CENTER_CROP的特点总结起来很简单: 以可能裁切掉部分图片为代价,让图片充满ImageView。
可以和FIT_XY做下对比, CENTER_CROP和FIT_XY是唯二的可以保证填满ImageView的值 。所不同的是,FIT_XY是以不保持原始比例伸缩为代价(但是保证原图全部显示出来);而CENTER_CROP是以不能显示完整原图为代价(但是保证原图的原始比例)。
二者都会按原始比例伸缩图片,所不同的是, CENTER_CROP将图片伸缩到填满ImageView为止,FIT_CENTER伸缩到图片完整并居中显示为止。
下面两个动图可以让你看得更清楚:
先看例子:
CENTER_INSIDE又是一个奇怪的值,原文的解释也是让人看不懂:
其实总结起来很简单: 当原图大于ImageView的时候,相当于FIT_CENTER。当原图小于等于ImageView的时候,相当于CENTER。
看下例子
MATRIX的效果比较简单: 不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理。 不保证填满ImageView,也不保证图片完全显示。和CENTER有点类似。反正我在项目中是没有用过这个值。
下面的表格总结了下各个属性值的特点,注意,表格中为“是”并不是说一定会发生,只是说明有这种可能。
最后再给大家出一道思考题,看看大家的掌握情况:
相信通过学习本文章,聪明的你很快就能找到答案。
10. android中用ImageView插入了一副图片,如何在它上面画某个已知坐标的点呢
是不是要在ImageView上面画图?如果是的话,你可以先处理图片,再显示图,或者把图设置成背景,然后用canvas来画。