Comments (31)
@GcsSloop
用了楼主的代码,发现点击check后最后会闪一下。
调试之后发现是由于调用invalidate()时并不会堵塞主线程,是异步问题导致的。
通过在onDraw方法中打印发现绘制了最大页13之后又绘制了12,所以会闪一下。
这边简单修改了下。只改了handle里面的处理:
if (animCurrentPage < animMaxPage && animCurrentPage >= 0) {
if (animState == ANIM_NULL)
return;
if (animState == ANIM_CHECK) {
animCurrentPage++;
} else if (animState == ANIM_UNCHECK) {
animCurrentPage--;
}
//animCurrentPage为animMaxPage不需要更新,否则下面的else会导致绘制前一张图闪一下
if (animCurrentPage != animMaxPage) {
invalidate();
}
this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
} else {
if (isCheck) {
animCurrentPage = animMaxPage - 1;
} else {
animCurrentPage = -1;
}
invalidate();
animState = ANIM_NULL;
}
from androidnote.
@GcsSloop 我在按钮上已经加入了点击事件了,并且在logCat有打印当前的页码数,只是没有动画效果。所以,我现在也不知道哪里出现了问题。
from androidnote.
My Code is as follows,for your reference.(please ignore my shandong chinese english 😔)
public class CheckView extends View {
private Paint mPaint;
private static final int ANIM_NULL=0;
private static final int ANIM_CHECK=1;
private static final int ANIM_UNCHECK=2;
private int mWidth,mHeight;
private Handler mHandler;
private Bitmap okBitmap;
private int animCurrentPage=-1;
//TODO:页面不需要是13页,因该是12页,12页至13页才是正确的绘制区域
private int animMaxPage=12;
private int animDuration=500;
private int animState=ANIM_NULL;
private boolean isCheck=false;
private static final String TAG = "RightView";
public CheckView(Context context) {
super(context);
init(context,null);
}
public CheckView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
private void init(Context context, @Nullable AttributeSet attrs){
mPaint=new Paint();
mPaint.setColor(Color.YELLOW);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
okBitmap= BitmapFactory.decodeResource(context.getResources(),R.drawable.check_mark);
mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (animCurrentPage<animMaxPage&&animCurrentPage>=0){
invalidate();
if (animState==ANIM_NULL){
return;
}
if (animState==ANIM_CHECK){
animCurrentPage++;
Log.e(TAG, "handleMessage: 当前页面"+animCurrentPage );
}else if (animState==ANIM_UNCHECK){
animCurrentPage--;
}
this.sendEmptyMessageDelayed(0,animDuration/animMaxPage);
}else {
if (isCheck){
animCurrentPage=animMaxPage-1;
}else {
animCurrentPage=-1;
}
//TODO:这里不需要重绘了,当前页面减一页会导致onDraw()方法多执行一边造成页面回退,出现闪烁现象
// invalidate();
animState=ANIM_NULL;
}
}
};
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth=w;
mHeight=h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth/2,mHeight/2);
canvas.drawCircle(0,0,240,mPaint);
int sideLength = okBitmap.getHeight();
// 得到图像选区 和 实际绘制位置
Rect src = new Rect(sideLength * animCurrentPage, 0, sideLength * (animCurrentPage + 1), sideLength);
Rect dst = new Rect(-150, -150, 150, 150);
Log.e(TAG, "onDraw: 绘制区域:"+sideLength * animCurrentPage+" "+0+" "+sideLength * (animCurrentPage + 1)+" "+sideLength );
// 绘制
canvas.drawBitmap(okBitmap, src, dst, mPaint);
}
public void check(){
if (animState!=ANIM_NULL&&isCheck){
return;
}else {
animState=ANIM_CHECK;
animCurrentPage=0;
isCheck=true;
mHandler.sendEmptyMessageDelayed(0,animDuration/animMaxPage);
}
}
/**
* 取消选择
*/
public void unCheck() {
if (animState != ANIM_NULL || (!isCheck))
return;
animState = ANIM_UNCHECK;
animCurrentPage = animMaxPage - 1;
mHandler.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
isCheck = false;
}
public void setDuration(int duration){
if (duration<=0){
return;
}else {
this.animDuration=duration;
}
}
public void setBackGroundColor(int color){
mPaint.setColor(color);
}
}
我主要是解决了一下页面闪烁现象,多谢楼主大大 学习了 Master!!!(手动 抱拳O(∩_∩)O )
from androidnote.
在
public void handleMessage(Message msg)
中,应该在
this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
前面或者后面invalidate();
,不然是看不到动画的,每更新一张picture都刷新一下。
from androidnote.
挺好
from androidnote.
赞一个
from androidnote.
感谢分享!
from androidnote.
good
from androidnote.
public class CheckView extends View {
private static final int ANIM_NULL = 0; //动画状态-没有
private static final int ANIM_CHECK = 1; //动画状态-开启
private static final int ANIM_UNCHECK = 2; //动画状态-结束
private Context mContext;
private Paint mPaint;
private int mWidth, mHeight;//宽高
private Handler handler;
private Bitmap okBitmap;
private int currentPage = -1;//当前页数
private int animCurrentPage = -1; // 当前页码
private int animMaxPage = 13; // 总页数
private int animDuration = 500; // 动画时长
private int animState = ANIM_NULL; // 动画状态
private boolean isCheck = false; // 是否只选中状态
public CheckView(Context context) {
this(context, null);
}
public CheckView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* 初始化
*
* @param context
*/
private void init(Context context) {
mContext = context;
mPaint = new Paint();
mPaint.setColor(0xffFF5317);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
okBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.checkmark);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (animCurrentPage < animMaxPage && animCurrentPage >= 0) {
invalidate();
if (animState == ANIM_NULL)
return;
if (animState == ANIM_CHECK) {
animCurrentPage++;
} else if (animState == ANIM_UNCHECK) {
animCurrentPage--;
}
invalidate();
this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
Log.e("AAA", "Count=" + animCurrentPage);
} else {
if (isCheck) {
animCurrentPage = animMaxPage - 1;
} else {
animCurrentPage = -1;
}
invalidate();
animState = ANIM_NULL;
}
}
};
}
/**
* View大小确定
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
/**
* 绘制内容
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e("llx", "onDraw()--");
// 移动坐标系到画布**
canvas.translate(mWidth / 2, mHeight / 2);
// 绘制背景圆形
canvas.drawCircle(0, 0, 240, mPaint);
// 得出图像边长
int sideLength = okBitmap.getHeight();
// 得到图像选区 和 实际绘制位置
Rect src = new Rect(sideLength * animCurrentPage, 0, sideLength * (animCurrentPage + 1), sideLength);
Rect dst = new Rect(200, 200, 200, 200);
// 绘制
canvas.drawBitmap(okBitmap, src, dst, null);
}
/**
* 选择
*/
public void check() {
if (animState != ANIM_NULL || isCheck)
return;
animState = ANIM_CHECK;
animCurrentPage = 0;
handler.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
isCheck = true;
}
/**
* 取消选择
*/
public void unCheck() {
if (animState != ANIM_NULL || (!isCheck))
return;
animState = ANIM_UNCHECK;
animCurrentPage = animMaxPage - 1;
handler.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
isCheck = false;
}
/**
* 设置动画时长
*
* @param animDuration
*/
public void setAnimDuration(int animDuration) {
if (animDuration <= 0)
return;
this.animDuration = animDuration;
}
/**
* 设置背景圆形颜色
*
* @param color
*/
public void setBackgroundColor(int color) {
mPaint.setColor(color);
}
}
这是我的代码 为什么图片没有执行显示呢
from androidnote.
注意这里:
Rect dst = new Rect(200, 200, 200, 200);
from androidnote.
@GcsSloop 是这里的原因 Thanks
from androidnote.
刚看到你的信息,解决了就好。
在 2016-10-21 19:28:46,"Liulixin" [email protected] 写道:
@GcsSloop 是这里的原因 Thanks
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
from androidnote.
第一个构造方法中使用super在按钮点击事件会报空指针异常,需要改为this(context,null)就不报异常了,但仍无法显示动画啊。从始至终,一直没有动画效果。本人是一个小白,没有办法了。
public CheckView(Context context) {
super(context, null); //报异常
}
from androidnote.
如果你不是直接继承的 View,那么上层View 可能没有两个参数的构造函数,使用 super(context, null);
就可能报错。
另外,想要显示动画效果需要调用 check 活着 unCheck 方法,直接加载 View 是没有效果的。
from androidnote.
检查你的图片和绘制区域的大小是否正确。
1.先在本应该绘制图片等区域绘制一种和背景不同颜色看是否正确。
2.检查图片是否读取成功。
3.检查图片截取大小是否正确。
4.检查是否是硬件加速的问题。 #7
from androidnote.
学习了
from androidnote.
图片在那能找到?
from androidnote.
这篇文章 图片文字 里面
from androidnote.
你好,有一点不是很明白,当你选定图片的区域绘制到实际的位置的时候图片会自动按照绘制区域的大小进行缩放啊,怎么会达成你说的那种效果呢? @GcsSloop
from androidnote.
例如截取的部分是 100 x 100 的大小,但绘制区域是 100 x 200 大小,那么图片高度会放大到原来的两倍,以填充所有的区域。
from androidnote.
我有个问题,如果一个文字 比如 ‘好’ 女 是绿色 子是红色怎么实现
from androidnote.
如果是左右分的,没有交叉部分的文字,就用遮罩,绘制两次,第一次用绿色,区域只包括左边,第二次用红色,区域只包括右边。
from androidnote.
我按照上面的代码,运行怎么都没有动画效果,在activity中给button设置一个点击时间,调用checkview.check(),但是还是没有动画。
from androidnote.
@zhouminxia
1.资源文件对吗?
2. 剪裁区域和绘制区域是否修改过?
3. handler 正确执行了吗。
from androidnote.
为什么我运行的时候报错呢, 说图片资源文件长度太长
from androidnote.
换个手机测试一下吧,我也用了 博主的这个 是 完全好用的。你可以看一下。
https://github.com/linsir6/Android-Notes/blob/master/Android%E8%87%AA%E5%AE%9A%E4%B9%89View/%E8%87%AA%E5%AE%9A%E4%B9%89View%E2%80%94%E2%80%94CheckView.md
from androidnote.
赞
from androidnote.
为啥我的显示效果和你的效果不太一样
from androidnote.
主要实现功能的代码
// 指定图片绘制区域
Rect src = new Rect(sideLength * animCurrentPage, 0, sideLength * (animCurrentPage + 1), sideLength);
// 指定图片在屏幕上显示的区域
Rect dst = new Rect(-200, -200, 200, 200);
// 绘制
canvas.drawBitmap(okBitmap, src, dst, null);
from androidnote.
不知道为什么我照着楼主的onDraw里面做,图片都无法显示,我换成这样,就可以了
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null || okBitmap == null) return
canvas.translate((mWidth / 2).toFloat(), (mHeight / 2).toFloat())
// 得出图像边长
val sideLength = okBitmap!!.height
canvas.drawCircle(0f, 0f, (sideLength / 2 + 20).toFloat(), mPaint)
// 算出图片每次需要截取的长度
var right = sideLength / animMaxPage * animCurrentPage
if (right > sideLength) right = sideLength
// 算出绘制框需要显示的长度,因为是从中间点左边负的图片边长的一半加上每次变换的值
var bRight = (0 - sideLength) / 2 + (sideLength / animMaxPage * animCurrentPage)
if (bRight > sideLength / 2) bRight = sideLength / 2
// 从图片的顶部坐标0,左边坐标0,底部坐标图片的长度,右边坐标是截取的长度
val src = Rect(0, 0, right, sideLength)
// 由于已经移动到屏幕的中间点,所以显示的区域是从中间点开始,顶部的坐标是负的图片边长的一半,底部坐标也是边长的一半
// 左边坐标也是负的图片边长的一半,右边坐标是上面算出的长度
val dst = Rect((0 - sideLength) / 2, (0 - sideLength) / 2, bRight, sideLength / 2)
canvas.drawBitmap(okBitmap, src, dst, null)
}
from androidnote.
读取到了Bitmap 也能打印页数,绘制不同颜色的Rect也能出现,但就是没有动画,可以给我一个完整Demo吗?
from androidnote.
Related Issues (20)
- RemoteControl
- 请教一下, 为什么对View宽高修改了不要调用super.onMeasure HOT 2
- 关于 Canvas mCanvas = new Canvas(bitmap) ,用缓存画布,画线锯齿的问题 HOT 3
- 模糊与滤镜的先后顺序
- 安卓
- 学习git
- 贝塞尔曲线案例之绘制一个弹性的圆
- 第9篇 Matrix_Basic 中有一个错误
- 第10篇 Matrix_Method 中的折叠布局有bug
- 【招聘】Android工程师招聘!!!
- 博客有几篇打不开了
- "确定View大小(onSizeChanged)" 这一节存在误导
- Canvas之绘制基本形状
- 章节缺失:安卓自定义View进阶
- 安卓
- 安卓自定义View进阶-Canvas之绘制图形 部分有误
- 请教一下measure.getLength ()测量长度不包含path.moveto()后再lineTo的线段长度 HOT 1
- Android系统色彩模式RGB_565的问题
- camera 神奇 数值 72 HOT 1
- 大哥,网站上的效果图咋都没了呢,前几天还有。自定义view写的很好,对新手挺友好的的,膜 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from androidnote.