当前位置: 首页 > news >正文

网站后台编辑教程百度网站推广费用

网站后台编辑教程,百度网站推广费用,大连建设工程信息网改名为什么,网站建设用图Android控件的Outline效果的实现方式有很多种,这里介绍一下另一种使用Canvas.drawPath()方法来绘制控件轮廓Path路径的实现方案(API28及以上)。 实现效果: 属性 添加Outline相关属性,主要包括颜色和Stroke宽度&…

Android控件的Outline效果的实现方式有很多种,这里介绍一下另一种使用Canvas.drawPath()方法来绘制控件轮廓Path路径的实现方案(API28及以上)。

实现效果:
在这里插入图片描述

属性

添加Outline相关属性,主要包括颜色和Stroke宽度:

<declare-styleable name="shape_button">...<attr name="carbon_stroke" /><attr name="carbon_strokeWidth" />
</declare-styleable>

StrokeView接口

创建一个StrokeView通用接口:

/*** 外部轮廓相关*/
public interface StrokeView {ColorStateList getStroke();void setStroke(ColorStateList color);void setStroke(int color);float getStrokeWidth();void setStrokeWidth(float strokeWidth);
}

ShapeButton 实现这个StrokeView接口:

public class ShapeButton extends AppCompatButtonimplements ShadowView,ShapeModelView,RippleView,StrokeView {public ShapeButton(@NonNull Context context) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);initButton(attrs, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initButton(attrs, defStyleAttr, R.style.carbon_Button);}public ShapeButton(Context context, String text, OnClickListener listener) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);setText(text);setOnClickListener(listener);}private static int[] elevationIds = new int[]{R.styleable.shape_button_carbon_elevation,R.styleable.shape_button_carbon_elevationShadowColor,R.styleable.shape_button_carbon_elevationAmbientShadowColor,R.styleable.shape_button_carbon_elevationSpotShadowColor};private static int[] cornerCutRadiusIds = new int[]{R.styleable.shape_button_carbon_cornerRadiusTopStart,R.styleable.shape_button_carbon_cornerRadiusTopEnd,R.styleable.shape_button_carbon_cornerRadiusBottomStart,R.styleable.shape_button_carbon_cornerRadiusBottomEnd,R.styleable.shape_button_carbon_cornerRadius,R.styleable.shape_button_carbon_cornerCutTopStart,R.styleable.shape_button_carbon_cornerCutTopEnd,R.styleable.shape_button_carbon_cornerCutBottomStart,R.styleable.shape_button_carbon_cornerCutBottomEnd,R.styleable.shape_button_carbon_cornerCut};private static int[] rippleIds = new int[]{R.styleable.shape_button_carbon_rippleColor,R.styleable.shape_button_carbon_rippleStyle,R.styleable.shape_button_carbon_rippleHotspot,R.styleable.shape_button_carbon_rippleRadius};private static int[] strokeIds = new int[]{R.styleable.shape_button_carbon_stroke,R.styleable.shape_button_carbon_strokeWidth};protected TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);private void initButton(AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.shape_button, defStyleAttr, defStyleRes);Carbon.initElevation(this, a, elevationIds);Carbon.initCornerCutRadius(this,a,cornerCutRadiusIds);Carbon.initRippleDrawable(this,a,rippleIds);// 初始化Stroke相关属性Carbon.initStroke(this,a,strokeIds);a.recycle();}// -------------------------------// shadow// -------------------------------// -------------------------------// shape// -------------------------------// -------------------------------// ripple// -------------------------------// -------------------------------// stroke// -------------------------------private ColorStateList stroke;private float strokeWidth;private Paint strokePaint;// 绘制轮廓private void drawStroke(Canvas canvas) {strokePaint.setStrokeWidth(strokeWidth * 2);strokePaint.setColor(stroke.getColorForState(getDrawableState(), stroke.getDefaultColor()));// cornersMask这是之前装载控件轮廓的path对象cornersMask.setFillType(Path.FillType.WINDING);canvas.drawPath(cornersMask, strokePaint);}// 设置轮廓颜色@Overridepublic void setStroke(ColorStateList colorStateList) {stroke = colorStateList;if (stroke == null)return;if (strokePaint == null) {strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);strokePaint.setStyle(Paint.Style.STROKE);}}// 设置轮廓颜色@Overridepublic void setStroke(int color) {setStroke(ColorStateList.valueOf(color));}@Overridepublic ColorStateList getStroke() {return stroke;}// 设置轮廓线条宽度@Overridepublic void setStrokeWidth(float strokeWidth) {this.strokeWidth = strokeWidth;}@Overridepublic float getStrokeWidth() {return strokeWidth;}}

初始化Stroke属性

    public static void initStroke(StrokeView strokeView, TypedArray a, int[] ids) {int carbon_stroke = ids[0];int carbon_strokeWidth = ids[1];View view = (View) strokeView;ColorStateList color =  a.getColorStateList(carbon_stroke);if (color != null)strokeView.setStroke(color);strokeView.setStrokeWidth(a.getDimension(carbon_strokeWidth, 0));}

绘制轮廓

onDraw()方法的super.draw(canvas);后面执行drawStroke()方法:

public void drawInternal(@NonNull Canvas canvas) {super.draw(canvas);if(stroke!=null){drawStroke(canvas);}}

如何使用

<com.chinatsp.demo1.shadow.ShapeButtonandroid:id="@+id/show_dialog_btn"android:layout_width="wrap_content"android:layout_height="36dp"android:layout_margin="@dimen/carbon_padding"android:background="#ffffff"android:stateListAnimator="@null"android:text="TOM"app:carbon_cornerCut="4dp"app:carbon_elevation="30dp"app:carbon_elevationShadowColor="#40ff0000"app:carbon_rippleColor="#40ff0000"app:carbon_rippleStyle="borderless"app:carbon_rippleRadius="30dp"app:carbon_stroke="@color/carbon_green_400"app:carbon_strokeWidth="1dp"/>

完整代码:

public class ShapeButton extends AppCompatButtonimplements ShadowView,ShapeModelView,RippleView,StrokeView {public ShapeButton(@NonNull Context context) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);initButton(attrs, android.R.attr.buttonStyle, R.style.carbon_Button);}public ShapeButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initButton(attrs, defStyleAttr, R.style.carbon_Button);}public ShapeButton(Context context, String text, OnClickListener listener) {super(context);initButton(null, android.R.attr.buttonStyle, R.style.carbon_Button);setText(text);setOnClickListener(listener);}private static int[] elevationIds = new int[]{R.styleable.shape_button_carbon_elevation,R.styleable.shape_button_carbon_elevationShadowColor,R.styleable.shape_button_carbon_elevationAmbientShadowColor,R.styleable.shape_button_carbon_elevationSpotShadowColor};private static int[] cornerCutRadiusIds = new int[]{R.styleable.shape_button_carbon_cornerRadiusTopStart,R.styleable.shape_button_carbon_cornerRadiusTopEnd,R.styleable.shape_button_carbon_cornerRadiusBottomStart,R.styleable.shape_button_carbon_cornerRadiusBottomEnd,R.styleable.shape_button_carbon_cornerRadius,R.styleable.shape_button_carbon_cornerCutTopStart,R.styleable.shape_button_carbon_cornerCutTopEnd,R.styleable.shape_button_carbon_cornerCutBottomStart,R.styleable.shape_button_carbon_cornerCutBottomEnd,R.styleable.shape_button_carbon_cornerCut};private static int[] rippleIds = new int[]{R.styleable.shape_button_carbon_rippleColor,R.styleable.shape_button_carbon_rippleStyle,R.styleable.shape_button_carbon_rippleHotspot,R.styleable.shape_button_carbon_rippleRadius};private static int[] strokeIds = new int[]{R.styleable.shape_button_carbon_stroke,R.styleable.shape_button_carbon_strokeWidth};protected TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);private void initButton(AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.shape_button, defStyleAttr, defStyleRes);Carbon.initElevation(this, a, elevationIds);Carbon.initCornerCutRadius(this,a,cornerCutRadiusIds);Carbon.initRippleDrawable(this,a,rippleIds);Carbon.initStroke(this,a,strokeIds);a.recycle();}// -------------------------------// shadow// -------------------------------private float elevation = 0;private float translationZ = 0;private ColorStateList ambientShadowColor, spotShadowColor;@Overridepublic float getElevation() {return elevation;}@Overridepublic void setElevation(float elevation) {if (Carbon.IS_PIE_OR_HIGHER) {super.setElevation(elevation);super.setTranslationZ(translationZ);} else if (Carbon.IS_LOLLIPOP_OR_HIGHER) {if (ambientShadowColor == null || spotShadowColor == null) {super.setElevation(elevation);super.setTranslationZ(translationZ);} else {super.setElevation(0);super.setTranslationZ(0);}} else if (elevation != this.elevation && getParent() != null) {((View) getParent()).postInvalidate();}this.elevation = elevation;}@Overridepublic float getTranslationZ() {return translationZ;}public void setTranslationZ(float translationZ) {if (translationZ == this.translationZ)return;if (Carbon.IS_PIE_OR_HIGHER) {super.setTranslationZ(translationZ);} else if (Carbon.IS_LOLLIPOP_OR_HIGHER) {if (ambientShadowColor == null || spotShadowColor == null) {super.setTranslationZ(translationZ);} else {super.setTranslationZ(0);}} else if (translationZ != this.translationZ && getParent() != null) {((View) getParent()).postInvalidate();}this.translationZ = translationZ;}@Overridepublic ColorStateList getElevationShadowColor() {return ambientShadowColor;}@Overridepublic void setElevationShadowColor(ColorStateList shadowColor) {ambientShadowColor = spotShadowColor = shadowColor;setElevation(elevation);setTranslationZ(translationZ);}@Overridepublic void setElevationShadowColor(int color) {ambientShadowColor = spotShadowColor = ColorStateList.valueOf(color);setElevation(elevation);setTranslationZ(translationZ);}@Overridepublic void setOutlineAmbientShadowColor(ColorStateList color) {ambientShadowColor = color;if (Carbon.IS_PIE_OR_HIGHER) {super.setOutlineAmbientShadowColor(color.getColorForState(getDrawableState(), color.getDefaultColor()));} else {setElevation(elevation);setTranslationZ(translationZ);}}@Overridepublic void setOutlineAmbientShadowColor(int color) {setOutlineAmbientShadowColor(ColorStateList.valueOf(color));}@Overridepublic int getOutlineAmbientShadowColor() {return ambientShadowColor.getDefaultColor();}@Overridepublic void setOutlineSpotShadowColor(int color) {setOutlineSpotShadowColor(ColorStateList.valueOf(color));}@Overridepublic void setOutlineSpotShadowColor(ColorStateList color) {spotShadowColor = color;if (Carbon.IS_PIE_OR_HIGHER) {super.setOutlineSpotShadowColor(color.getColorForState(getDrawableState(), color.getDefaultColor()));} else {setElevation(elevation);setTranslationZ(translationZ);}}@Overridepublic int getOutlineSpotShadowColor() {return ambientShadowColor.getDefaultColor();}@Overridepublic boolean hasShadow() {return false;}@Overridepublic void drawShadow(Canvas canvas) {}@Overridepublic void draw(Canvas canvas) {boolean c = !Carbon.isShapeRect(shapeModel, boundsRect);if (Carbon.IS_PIE_OR_HIGHER) {if (spotShadowColor != null)super.setOutlineSpotShadowColor(spotShadowColor.getColorForState(getDrawableState(), spotShadowColor.getDefaultColor()));if (ambientShadowColor != null)super.setOutlineAmbientShadowColor(ambientShadowColor.getColorForState(getDrawableState(), ambientShadowColor.getDefaultColor()));}// 判断如果不是圆角矩形,需要使用轮廓Path,绘制一下Path,不然显示会很奇怪if (getWidth() > 0 && getHeight() > 0 && ((c && !Carbon.IS_LOLLIPOP_OR_HIGHER) || !shapeModel.isRoundRect(boundsRect))) {int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);drawInternal(canvas);paint.setXfermode(Carbon.CLEAR_MODE);if (c) {cornersMask.setFillType(Path.FillType.INVERSE_WINDING);canvas.drawPath(cornersMask, paint);}canvas.restoreToCount(saveCount);paint.setXfermode(null);}else{drawInternal(canvas);}}public void drawInternal(@NonNull Canvas canvas) {super.draw(canvas);if(stroke!=null){drawStroke(canvas);}if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Over)rippleDrawable.draw(canvas);}// -------------------------------// shape// -------------------------------private ShapeAppearanceModel shapeModel = new ShapeAppearanceModel();private MaterialShapeDrawable shadowDrawable = new MaterialShapeDrawable(shapeModel);@Overridepublic void setShapeModel(ShapeAppearanceModel shapeModel) {this.shapeModel = shapeModel;shadowDrawable = new MaterialShapeDrawable(shapeModel);if (getWidth() > 0 && getHeight() > 0)updateCorners();if (!Carbon.IS_LOLLIPOP_OR_HIGHER)postInvalidate();}// View的轮廓形状private RectF boundsRect = new RectF();// View的轮廓形状形成的Path路径private Path cornersMask = new Path();/*** 更新圆角*/private void updateCorners() {if (Carbon.IS_LOLLIPOP_OR_HIGHER) {// 如果不是矩形,裁剪View的轮廓if (!Carbon.isShapeRect(shapeModel, boundsRect)){setClipToOutline(true);}//该方法返回一个Outline对象,它描述了该视图的形状。setOutlineProvider(new ViewOutlineProvider() {@Overridepublic void getOutline(View view, Outline outline) {if (Carbon.isShapeRect(shapeModel, boundsRect)) {outline.setRect(0, 0, getWidth(), getHeight());} else {shadowDrawable.setBounds(0, 0, getWidth(), getHeight());shadowDrawable.setShadowCompatibilityMode(MaterialShapeDrawable.SHADOW_COMPAT_MODE_NEVER);shadowDrawable.getOutline(outline);}}});}// 拿到圆角矩形的形状boundsRect.set(shadowDrawable.getBounds());// 拿到圆角矩形的PathshadowDrawable.getPathForSize(getWidth(), getHeight(), cornersMask);}@Overridepublic ShapeAppearanceModel getShapeModel() {return this.shapeModel;}@Overridepublic void setCornerCut(float cornerCut) {shapeModel = ShapeAppearanceModel.builder().setAllCorners(new CutCornerTreatment(cornerCut)).build();setShapeModel(shapeModel);}@Overridepublic void setCornerRadius(float cornerRadius) {shapeModel = ShapeAppearanceModel.builder().setAllCorners(new RoundedCornerTreatment(cornerRadius)).build();setShapeModel(shapeModel);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);if (!changed)return;if (getWidth() == 0 || getHeight() == 0)return;updateCorners();if (rippleDrawable != null)rippleDrawable.setBounds(0, 0, getWidth(), getHeight());}// -------------------------------// ripple// -------------------------------private RippleDrawable rippleDrawable;@Overridepublic boolean dispatchTouchEvent(@NonNull MotionEvent event) {if (rippleDrawable != null && event.getAction() == MotionEvent.ACTION_DOWN)rippleDrawable.setHotspot(event.getX(),event.getY());return super.dispatchTouchEvent(event);}@Overridepublic RippleDrawable getRippleDrawable() {return rippleDrawable;}@Overridepublic void setRippleDrawable(RippleDrawable newRipple) {if (rippleDrawable != null) {rippleDrawable.setCallback(null);if (rippleDrawable.getStyle() == RippleDrawable.Style.Background)super.setBackgroundDrawable(rippleDrawable.getBackground());}if (newRipple != null) {newRipple.setCallback(this);newRipple.setBounds(0, 0, getWidth(), getHeight());newRipple.setState(getDrawableState());((Drawable) newRipple).setVisible(getVisibility() == VISIBLE, false);if (newRipple.getStyle() == RippleDrawable.Style.Background)super.setBackgroundDrawable((Drawable) newRipple);}rippleDrawable = newRipple;}@Overrideprotected void drawableStateChanged() {super.drawableStateChanged();if (rippleDrawable != null && rippleDrawable.getStyle() != RippleDrawable.Style.Background)rippleDrawable.setState(getDrawableState());}@Overrideprotected boolean verifyDrawable(@NonNull Drawable who) {return super.verifyDrawable(who) || rippleDrawable == who;}@Overridepublic void invalidateDrawable(@NonNull Drawable drawable) {super.invalidateDrawable(drawable);invalidateParentIfNeeded();}@Overridepublic void invalidate(@NonNull Rect dirty) {super.invalidate(dirty);invalidateParentIfNeeded();}@Overridepublic void invalidate(int l, int t, int r, int b) {super.invalidate(l, t, r, b);invalidateParentIfNeeded();}@Overridepublic void invalidate() {super.invalidate();invalidateParentIfNeeded();}private void invalidateParentIfNeeded() {if (getParent() == null || !(getParent() instanceof View))return;if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Borderless)((View) getParent()).invalidate();}@Overridepublic void setBackground(Drawable background) {setBackgroundDrawable(background);}@Overridepublic void setBackgroundDrawable(Drawable background) {if (background instanceof RippleDrawable) {setRippleDrawable((RippleDrawable) background);return;}if (rippleDrawable != null && rippleDrawable.getStyle() == RippleDrawable.Style.Background) {rippleDrawable.setCallback(null);rippleDrawable = null;}super.setBackgroundDrawable(background);}// -------------------------------// stroke// -------------------------------private ColorStateList stroke;private float strokeWidth;private Paint strokePaint;private void drawStroke(Canvas canvas) {strokePaint.setStrokeWidth(strokeWidth * 2);strokePaint.setColor(stroke.getColorForState(getDrawableState(), stroke.getDefaultColor()));cornersMask.setFillType(Path.FillType.WINDING);canvas.drawPath(cornersMask, strokePaint);}@Overridepublic void setStroke(ColorStateList colorStateList) {stroke = colorStateList;if (stroke == null)return;if (strokePaint == null) {strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);strokePaint.setStyle(Paint.Style.STROKE);}}@Overridepublic void setStroke(int color) {setStroke(ColorStateList.valueOf(color));}@Overridepublic ColorStateList getStroke() {return stroke;}@Overridepublic void setStrokeWidth(float strokeWidth) {this.strokeWidth = strokeWidth;}@Overridepublic float getStrokeWidth() {return strokeWidth;}}
http://www.hkea.cn/news/742584/

相关文章:

  • 怎么做盗版视频网站吗百度权重1
  • 政府网站 建设 计划品牌推广策划方案案例
  • 临沂网站建设那家好小米市场营销案例分析
  • 德化网站建设企业中层管理人员培训课程
  • 网站怎么通过流量赚钱爱站网能不能挖掘关键词
  • 网站建设课后感营销型网站有哪些平台
  • 哪个网站做生鲜配送厦门seo外包公司
  • 水电行业公司设计logo重庆seo排名扣费
  • 可信赖的南昌网站制作站长工具网站
  • 济南建站公司电话成都关键词自然排名
  • 门户网站开发公司推广网页
  • 如何做网站认证实时军事热点
  • 上海的网站建设公司哪家好企业网站建设
  • 专业b2c电商网站制作网站推广要点
  • 现在的网站用什么程序做百度云官网登录入口
  • vs做网站怎样加数据库新闻小学生摘抄
  • 广州做网站mxszpt小说排行榜
  • 有什么网站是python做的网站营销策划公司
  • 长春有什么好的网站制作公司链接购买
  • 毕设网站佛山网站建设十年乐云seo
  • 北京做网站建设的公司哪家好手机怎么创建网站
  • winforms做网站注册百度账号
  • 玉泉路网站建设营销培训课程有哪些
  • 渭南做网站费用搜索引擎排名优化是什么意思
  • 做网站开发需要学什么软件微信公众平台开发
  • 网站整体营销方案网络营销的特点是什么?
  • 国内知名的网站建设公司有哪些百度指数专业版app
  • 画画外包网站如何推广一个网站
  • 互联网公司响应式网站深圳google推广
  • 深圳网站设计哪好什么推广平台比较好