Giter VIP home page Giter VIP logo

Comments (31)

zhanzengyu avatar zhanzengyu commented on May 26, 2024 2

@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.

 avatar commented on May 26, 2024 1

@GcsSloop 我在按钮上已经加入了点击事件了,并且在logCat有打印当前的页码数,只是没有动画效果。所以,我现在也不知道哪里出现了问题。

from androidnote.

longjianghong avatar longjianghong commented on May 26, 2024 1

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.

hunao0221 avatar hunao0221 commented on May 26, 2024

 public void handleMessage(Message msg)

中,应该在

  this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);

前面或者后面invalidate();,不然是看不到动画的,每更新一张picture都刷新一下。

from androidnote.

bqq1986 avatar bqq1986 commented on May 26, 2024

挺好

from androidnote.

wonbin2011 avatar wonbin2011 commented on May 26, 2024

赞一个

from androidnote.

flyzend avatar flyzend commented on May 26, 2024

感谢分享!

from androidnote.

liqiang861220 avatar liqiang861220 commented on May 26, 2024

good

from androidnote.

liulixin1 avatar liulixin1 commented on May 26, 2024

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.

GcsSloop avatar GcsSloop commented on May 26, 2024

注意这里:

Rect dst = new Rect(200, 200, 200, 200);

from androidnote.

liulixin1 avatar liulixin1 commented on May 26, 2024

@GcsSloop 是这里的原因 Thanks

from androidnote.

liqiang861220 avatar liqiang861220 commented on May 26, 2024

刚看到你的信息,解决了就好。

在 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.

 avatar commented on May 26, 2024

第一个构造方法中使用super在按钮点击事件会报空指针异常,需要改为this(context,null)就不报异常了,但仍无法显示动画啊。从始至终,一直没有动画效果。本人是一个小白,没有办法了。
public CheckView(Context context) {
super(context, null); //报异常
}

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

如果你不是直接继承的 View,那么上层View 可能没有两个参数的构造函数,使用 super(context, null); 就可能报错。
另外,想要显示动画效果需要调用 check 活着 unCheck 方法,直接加载 View 是没有效果的。

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

检查你的图片和绘制区域的大小是否正确。

1.先在本应该绘制图片等区域绘制一种和背景不同颜色看是否正确。
2.检查图片是否读取成功。
3.检查图片截取大小是否正确。
4.检查是否是硬件加速的问题。 #7

from androidnote.

newcaoguo avatar newcaoguo commented on May 26, 2024

学习了

from androidnote.

MLLWF avatar MLLWF commented on May 26, 2024

图片在那能找到?

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

这篇文章 图片文字 里面

from androidnote.

MLLWF avatar MLLWF commented on May 26, 2024

你好,有一点不是很明白,当你选定图片的区域绘制到实际的位置的时候图片会自动按照绘制区域的大小进行缩放啊,怎么会达成你说的那种效果呢? @GcsSloop

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

例如截取的部分是 100 x 100 的大小,但绘制区域是 100 x 200 大小,那么图片高度会放大到原来的两倍,以填充所有的区域。

from androidnote.

ZhouKanZ avatar ZhouKanZ commented on May 26, 2024

我有个问题,如果一个文字 比如 ‘好’ 女 是绿色 子是红色怎么实现

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

如果是左右分的,没有交叉部分的文字,就用遮罩,绘制两次,第一次用绿色,区域只包括左边,第二次用红色,区域只包括右边。

from androidnote.

zhouminxia avatar zhouminxia commented on May 26, 2024

我按照上面的代码,运行怎么都没有动画效果,在activity中给button设置一个点击时间,调用checkview.check(),但是还是没有动画。

from androidnote.

GcsSloop avatar GcsSloop commented on May 26, 2024

@zhouminxia
1.资源文件对吗?
2. 剪裁区域和绘制区域是否修改过?
3. handler 正确执行了吗。

from androidnote.

BINBINXIAO avatar BINBINXIAO commented on May 26, 2024

为什么我运行的时候报错呢, 说图片资源文件长度太长

from androidnote.

linsir6 avatar linsir6 commented on May 26, 2024

换个手机测试一下吧,我也用了 博主的这个 是 完全好用的。你可以看一下。
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.

xqgdmg avatar xqgdmg commented on May 26, 2024

from androidnote.

huo2016 avatar huo2016 commented on May 26, 2024

为啥我的显示效果和你的效果不太一样

from androidnote.

zstartw avatar zstartw commented on May 26, 2024

主要实现功能的代码

 // 指定图片绘制区域
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.

lodgkk avatar lodgkk commented on May 26, 2024

不知道为什么我照着楼主的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.

PaulX1029 avatar PaulX1029 commented on May 26, 2024

读取到了Bitmap 也能打印页数,绘制不同颜色的Rect也能出现,但就是没有动画,可以给我一个完整Demo吗?

from androidnote.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.