滑动解锁 android Canvas自定义控件中硬件加速引起的canvas.clipPath问题
来源:互联网 发布:xmind mac怎么安装 编辑:程序博客网 时间:2024/06/05 13:21
我们知道,android中的图形都是矩形的。
要绘制一个如下的椭圆形控件(圆形图像,圆角listview,圆角按钮),我们需要裁剪画布
在4.4一下的设备上 使用canvas.clipPath裁剪画布以使得控件中绘制的内容能被不规则化
//裁剪画布
mContentRect.set(0, 0, getWidth(), getHeight());mPath.addRoundRect(mContentRect, r/2,r/2, Path.Direction.CCW);
canvas.clipPath(mPath,android.graphics.Region.Op.REPLACE);
//绘制其他控件元素,灯泡 文字 背景
但是 在部分真是设备中,它的效果缺是这样的
裁剪失效,有没有?
问题在于canvas默认开启了硬件加速
硬件加速具体的介绍见官方文档
http://developer.android.com/guide/topics/graphics/hardware-accel.html
下面是硬件加速不支持的API和SDK等级对照表
API level< 16161718CanvasdrawBitmapMesh() (colors array)✗✗✗✓drawPicture()✗✗✗✗drawPosText()✗✓✓✓drawTextOnPath()✗✓✓✓drawVertices()✗✗✗✗setDrawFilter()✗✓✓✓clipPath()✗✗✗✓clipRegion()✗✗✗✓clipRect(Region.Op.XOR)✗✗✗✓clipRect(Region.Op.Difference)✗✗✗✓clipRect(Region.Op.ReverseDifference)✗✗✗✓clipRect() with rotation/perspective✗✗✗✓PaintsetAntiAlias() (for text)✗✗✗✓setAntiAlias() (for lines)✗✓✓✓setFilterBitmap()✗✗✓✓setLinearText()✗✗✗✗setMaskFilter()✗✗✗✗setPathEffect() (for lines)✗✗✗✗setRasterizer()✗✗✗✗setShadowLayer() (other than text)✗✗✗✗setStrokeCap() (for lines)✗✗✗✓setStrokeCap() (for points)✗✗✗✗setSubpixelText()✗✗✗✗XfermodeAvoidXfermode✗✗✗✗PixelXorXfermode✗✗✗✗PorterDuff.Mode.DARKEN (framebuffer)✗✗✗✗PorterDuff.Mode.LIGHTEN (framebuffer)✗✗✗✗PorterDuff.Mode.OVERLAY (framebuffer)✗✗✗✗ShaderComposeShader inside ComposeShader✗✗✗✗Same type shaders inside ComposeShader✗✗✗✗Local matrix on ComposeShader✗✗✗✓
clipPath 赫然就在其中
解决的办法的有2个;
1:依照上面的表不在不支持的设备上使用这个API,
2:对这个自定义的view 禁用硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
例子中的自定义控件完整代码如下
/** * slide to control */public class SlideControllerView extends RelativeLayout {private static final int STATE_DRAGGING = 1;private String mExampleString;private int mExampleColor = Color.RED;private float mExampleDimension = 0;private Drawable mExampleDrawable;private TextPaint mTextPaint;private Paint mMaskPaint;private float mTextWidth;private float mTextHeight;private Path mPath;private Drawable mDrawable_button;private Drawable mDrawable_background_button;int COLOR_BLUE_LIGHT = 0xff3094ff;private ScrollerCompat mScroller;public SlideControllerView(Context context) {super(context);init(null, 0);}public SlideControllerView(Context context, AttributeSet attrs) {super(context, attrs);init(attrs, 0);}public SlideControllerView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(attrs, defStyle);}private void init(AttributeSet attrs, int defStyle) {// Load attributesfinal TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.SlideControllerView, defStyle, 0);mExampleString = a.getString(R.styleable.SlideControllerView_exampleString);mExampleColor = a.getColor(R.styleable.SlideControllerView_exampleColor, mExampleColor);// Use getDimensionPixelSize or getDimensionPixelOffset when dealing// with// values that should fall on pixel boundaries.mExampleDimension = a.getDimension(R.styleable.SlideControllerView_exampleDimension,mExampleDimension);if (a.hasValue(R.styleable.SlideControllerView_exampleDrawable)) {mExampleDrawable = a.getDrawable(R.styleable.SlideControllerView_exampleDrawable);mExampleDrawable.setCallback(this);}if (a.hasValue(R.styleable.SlideControllerView_button)) {mDrawable_button = a.getDrawable(R.styleable.SlideControllerView_button);mDrawable_button.setCallback(this);}if (a.hasValue(R.styleable.SlideControllerView_background_button)) {mDrawable_background_button = a.getDrawable(R.styleable.SlideControllerView_background_button);mDrawable_background_button.setCallback(this);}a.recycle();// Set up a default TextPaint objectmTextPaint = new TextPaint();mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);mTextPaint.setTextAlign(Paint.Align.LEFT);// Set up a default TextPaint objectmMaskPaint = new Paint();mMaskPaint.setFlags(Paint.ANTI_ALIAS_FLAG);mMaskPaint.setAntiAlias(true);mMaskPaint.setDither(true);mMaskPaint.setColor(0xcccccc);mPath = new Path();paint_state = new Paint();mScroller = ScrollerCompat.create(getContext(), sInterpolator);// Update TextPaint and text measurements from attributesinvalidateTextPaintAndMeasurements();setLayerType(View.LAYER_TYPE_SOFTWARE, null);}/** * Interpolator defining the animation curve for mScroller */private static final Interpolator sInterpolator = new Interpolator() {public float getInterpolation(float t) {t -= 1.0f;return t * t * t * t * t + 1.0f;}};int r = 0;RectF mleft = new RectF();RectF mcenter = new RectF();RectF mright = new RectF();RectF mContentRect = new RectF();private LinearGradient shader_stateFouse;private Paint paint_state;private int mDragState;@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mPath.reset();mContentRect.set(0, 0, getWidth(), getHeight());mPath.addRoundRect(mContentRect, r/2,r/2, Path.Direction.CCW);}@Overridepublic boolean onTouchEvent(MotionEvent event) {return handerTouchEvent(event);}private boolean handerTouchEvent(MotionEvent ev) {final int action = MotionEventCompat.getActionMasked(ev);System.out.println("handerTouchEvent");switch (action) {case MotionEvent.ACTION_DOWN: {cancel();final float x = ev.getX();final float y = ev.getY();saveInitialMotion(x, y);saveLastMotion(x, y);mDragState = STATE_DRAGGING;break;}case MotionEvent.ACTION_MOVE: {if (mDragState == STATE_DRAGGING) {float x = ev.getX();final float y = ev.getY();if (x > getWidth() - r) {x = getWidth() - r;}if (x - getPaddingLeft() <= 0) {x = getPaddingLeft();}saveLastMotion(x, y);invalidate();} else {}break;}case MotionEvent.ACTION_UP: {if (mDragState == STATE_DRAGGING) {}reslease();break;}case MotionEvent.ACTION_CANCEL: {cancel();break;}}return true;}private void reslease() {if (isClickable()) {if (x_last > getWidth() / 2) {mScroller.startScroll((int) x_last, (int) y_last,(int) getWidth() - r - (int) x_last, 0);invalidate();} else {mScroller.startScroll((int) x_last, (int) y_last,getPaddingLeft() - (int) x_last, 0);invalidate();}}}private void cancel() {if (isClickable()) {mScroller.abortAnimation();}}@Overridepublic void computeScroll() {super.computeScroll();// 先判断mScroller滚动是否完成if (mScroller.computeScrollOffset()) {// 这里调用View的scrollTo()完成实际的滚动x_last = mScroller.getCurrX();y_last = mScroller.getCurrY();// 必须调用该方法,否则不一定能看到滚动效果invalidate();}}private float x_down;private float y_down;private void saveInitialMotion(float x, float y) {x_down = x;y_down = y;}private float x_last;private float y_last;private void saveLastMotion(float x, float y) {x_last = x;y_last = y;}private void invalidateTextPaintAndMeasurements() {mTextPaint.setTextSize(mExampleDimension);mTextPaint.setColor(mExampleColor);mTextWidth = mTextPaint.measureText(mExampleString);Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();mTextHeight = fontMetrics.bottom;}@Overrideprotected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);onDraw(canvas);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// clip canvas,r = getHeight();// mPath.reset();// mPath.moveTo(r, 0);// mleft.set(0, 0, r, r);// mPath.arcTo(mleft, 90, 180);// mcenter.set(r / 2, 0, getWidth() - r / 2, r);// mPath.addRect(mcenter, Path.Direction.CW);// mPath.lineTo(getWidth() - r / 2, 0);// mright.set(getWidth() - r, 0, getWidth(), r);// mPath.arcTo(mright, 270, 180);// boolean clip = canvas.clipPath(mPath,// android.graphics.Region.Op.REPLACE);// System.out.println(clip);canvas.clipPath(mPath,android.graphics.Region.Op.REPLACE);System.out.println(r);// clip draw state,if (shader_stateFouse == null) {shader_stateFouse = new LinearGradient(0, 0, getWidth(),getHeight(), 0xffcccccc, COLOR_BLUE_LIGHT,Shader.TileMode.CLAMP);paint_state.setShader(shader_stateFouse);}paint_state.setAlpha((int) (0xff * (x_last / getWidth())));canvas.drawRect(0, 0, getWidth(), getHeight(), paint_state);// TODO: consider storing these as member variables to reduce// allocations per draw cycle.int paddingLeft = getPaddingLeft();int paddingTop = getPaddingTop();int paddingRight = getPaddingRight();int paddingBottom = getPaddingBottom();int contentWidth = getWidth() - paddingLeft - paddingRight;int contentHeight = getHeight() - paddingTop - paddingBottom;// Draw the text.canvas.drawText(mExampleString, paddingLeft+ (contentWidth - mTextWidth) / 2, paddingTop+ (contentHeight + mTextHeight) / 2, mTextPaint);// Draw the example drawable on top of the text.// if (mExampleDrawable != null) {// mExampleDrawable.setBounds(paddingLeft, paddingTop, paddingLeft// + contentWidth, paddingTop + contentHeight);// mExampleDrawable.draw(canvas);// }if (mDrawable_background_button != null) {mDrawable_background_button.getIntrinsicWidth();mDrawable_background_button.setBounds((int) x_last + paddingLeft,getHeight() / 2 - r / 2 + paddingTop, r + (int) x_last- paddingRight, getHeight() / 2 + getHeight() / 2- paddingBottom);// mDrawable_button.setBounds((int)x_last, 0,(int)x_last+r,// getHeight());mDrawable_background_button.draw(canvas);}if (mDrawable_button != null) {mDrawable_button.getIntrinsicWidth();mDrawable_button.setBounds((int) x_last + r / 2- mDrawable_button.getIntrinsicWidth() / 2,getHeight() / 2- mDrawable_button.getIntrinsicHeight() / 2,(int) x_last + r / 2+ mDrawable_button.getIntrinsicWidth() / 2,getHeight() / 2+ mDrawable_button.getIntrinsicHeight() / 2);// mDrawable_button.setBounds((int)x_last, 0,(int)x_last+r,// getHeight());mDrawable_button.draw(canvas);}}/** * Gets the example string attribute value. * * @return The example string attribute value. */public String getExampleString() {return mExampleString;}/** * Sets the view's example string attribute value. In the example view, this * string is the text to draw. * * @param exampleString * The example string attribute value to use. */public void setExampleString(String exampleString) {mExampleString = exampleString;invalidateTextPaintAndMeasurements();}/** * Gets the example color attribute value. * * @return The example color attribute value. */public int getExampleColor() {return mExampleColor;}/** * Sets the view's example color attribute value. In the example view, this * color is the font color. * * @param exampleColor * The example color attribute value to use. */public void setExampleColor(int exampleColor) {mExampleColor = exampleColor;invalidateTextPaintAndMeasurements();}/** * Gets the example dimension attribute value. * * @return The example dimension attribute value. */public float getExampleDimension() {return mExampleDimension;}/** * Sets the view's example dimension attribute value. In the example view, * this dimension is the font size. * * @param exampleDimension * The example dimension attribute value to use. */public void setExampleDimension(float exampleDimension) {mExampleDimension = exampleDimension;invalidateTextPaintAndMeasurements();}/** * Gets the example drawable attribute value. * * @return The example drawable attribute value. */public Drawable getExampleDrawable() {return mExampleDrawable;}/** * Sets the view's example drawable attribute value. In the example view, * this drawable is drawn above the text. * * @param exampleDrawable * The example drawable attribute value to use. */public void setExampleDrawable(Drawable exampleDrawable) {mExampleDrawable = exampleDrawable;}}
0 0
- 滑动解锁 android Canvas自定义控件中硬件加速引起的canvas.clipPath问题
- Android canvas clipPath 问题
- Android canvas.clipPath无效
- 彻底解决 Canvas 引起的 java.lang.unsupported operation exception, android.view.GLES20Canvas.clipPath(GLES20
- 彻底解决 Canvas 引起的 java.lang.unsupported operation exception, android.view.GLES20Canvas.clipPath(GLES20
- canvas.clipPath canvas.clipRect() 无效的原因
- Android 自定义控件canvas
- android自定义控件canvas.drawText()的坐标问题
- Android 4.1.1 bug? Canvas的clipPath实现圆形图片
- Canvas中clipRect、clipPath和clipRegion 剪切区域的API
- Andrdoid自定义View之canvas.clipPath(path);
- android中自定义画布Canvas的实现
- 硬件加速引起的问题
- android中canvas.drawArc的弧度问题
- Android自定义控件之滑动解锁
- Android自定义控件之滑动解锁
- 工作日志记录:Android自定义控件中使用的canvas裁剪的相关参数记录:
- 使用canvas.clipPath来裁剪时部分机型出现问题
- JD(3)
- 字符串 格式化 方法
- [linux]监控性能命令
- jsp判断本月有几个周五
- [hackerrank]Weekly Challenges - Week 11
- 滑动解锁 android Canvas自定义控件中硬件加速引起的canvas.clipPath问题
- c 管道读取
- 一份完整游戏大纲你要写些什么
- 不需要密码的登录
- 使用RMAN工具复制数据库
- centos 6.5 安装jdk tar.gz操作步骤
- SAP ABAP编程 SY-REPID与SY-CPROG的区别
- QPushButton设置背景图片的方法
- C#Excel数据转换成DataTable