Android 天气APP(十三)仿微信弹窗(右上角加号点击弹窗效果)、自定义背景图片、UI优化调整(1)

本文介绍了如何在Android天气应用中实现仿微信右上角加号点击弹窗效果,以及自定义背景图片和UI优化调整。详细讲解了涉及的代码逻辑,包括绘制不同状态的背景、按钮、指示器等,并提供了相关学习资源推荐。
摘要由CSDN通过智能技术生成

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

paint.setStrokeWidth(borderWidth);

paint.setStyle(Paint.Style.FILL);

//绘制白色背景

paint.setColor(background);

drawRoundRect(canvas,

left, top, right, bottom,

viewRadius, paint);

//绘制关闭状态的边框

paint.setStyle(Paint.Style.STROKE);

paint.setColor(uncheckColor);

drawRoundRect(canvas,

left, top, right, bottom,

viewRadius, paint);

//绘制小圆圈

if(showIndicator){

drawUncheckIndicator(canvas);

}

//绘制开启背景色

float des = viewState.radius * .5f;//[0-backgroundRadius*0.5f]

paint.setStyle(Paint.Style.STROKE);

paint.setColor(viewState.checkStateColor);

paint.setStrokeWidth(borderWidth + des * 2f);

drawRoundRect(canvas,

left + des, top + des, right - des, bottom - des,

viewRadius, paint);

//绘制按钮左边绿色长条遮挡

paint.setStyle(Paint.Style.FILL);

paint.setStrokeWidth(1);

drawArc(canvas,

left, top,

left + 2 * viewRadius, top + 2 * viewRadius,

90, 180, paint);

canvas.drawRect(

left + viewRadius, top,

viewState.buttonX, top + 2 * viewRadius,

paint);

//绘制小线条

if(showIndicator){

drawCheckedIndicator(canvas);

}

//绘制按钮

drawButton(canvas, viewState.buttonX, centerY);

}

/**

  • 绘制选中状态指示器

  • @param canvas

*/

protected void drawCheckedIndicator(Canvas canvas) {

drawCheckedIndicator(canvas,

viewState.checkedLineColor,

checkLineWidth,

left + viewRadius - checkedLineOffsetX, centerY - checkLineLength,

left + viewRadius - checkedLineOffsetY, centerY + checkLineLength,

paint);

}

/**

  • 绘制选中状态指示器

  • @param canvas

  • @param color

  • @param lineWidth

  • @param sx

  • @param sy

  • @param ex

  • @param ey

  • @param paint

*/

protected void drawCheckedIndicator(Canvas canvas,

int color,

float lineWidth,

float sx, float sy, float ex, float ey,

Paint paint) {

paint.setStyle(Paint.Style.STROKE);

paint.setColor(color);

paint.setStrokeWidth(lineWidth);

canvas.drawLine(

sx, sy, ex, ey,

paint);

}

/**

  • 绘制关闭状态指示器

  • @param canvas

*/

private void drawUncheckIndicator(Canvas canvas) {

drawUncheckIndicator(canvas,

uncheckCircleColor,

uncheckCircleWidth,

right - uncheckCircleOffsetX, centerY,

uncheckCircleRadius,

paint);

}

/**

  • 绘制关闭状态指示器

  • @param canvas

  • @param color

  • @param lineWidth

  • @param centerX

  • @param centerY

  • @param radius

  • @param paint

*/

protected void drawUncheckIndicator(Canvas canvas,

int color,

float lineWidth,

float centerX, float centerY,

float radius,

Paint paint) {

paint.setStyle(Paint.Style.STROKE);

paint.setColor(color);

paint.setStrokeWidth(lineWidth);

canvas.drawCircle(centerX, centerY, radius, paint);

}

/**

  • @param canvas

  • @param left

  • @param top

  • @param right

  • @param bottom

  • @param startAngle

  • @param sweepAngle

  • @param paint

*/

private void drawArc(Canvas canvas,

float left, float top,

float right, float bottom,

float startAngle, float sweepAngle,

Paint paint){

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

canvas.drawArc(left, top, right, bottom,

startAngle, sweepAngle, true, paint);

}else{

rect.set(left, top, right, bottom);

canvas.drawArc(rect,

startAngle, sweepAngle, true, paint);

}

}

/**

  • @param canvas

  • @param left

  • @param top

  • @param right

  • @param bottom

  • @param backgroundRadius

  • @param paint

*/

private void drawRoundRect(Canvas canvas,

float left, float top,

float right, float bottom,

float backgroundRadius,

Paint paint){

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

canvas.drawRoundRect(left, top, right, bottom,

backgroundRadius, backgroundRadius, paint);

}else{

rect.set(left, top, right, bottom);

canvas.drawRoundRect(rect,

backgroundRadius, backgroundRadius, paint);

}

}

/**

  • @param canvas

  • @param x px

  • @param y px

*/

private void drawButton(Canvas canvas, float x, float y) {

canvas.drawCircle(x, y, buttonRadius, buttonPaint);

paint.setStyle(Paint.Style.STROKE);

paint.setStrokeWidth(1);

paint.setColor(0XffDDDDDD);

canvas.drawCircle(x, y, buttonRadius, paint);

}

@Override

public void setChecked(boolean checked) {

if(checked == isChecked()){

postInvalidate();

return;

}

toggle(enableEffect, false);

}

@Override

public boolean isChecked() {

return isChecked;

}

@Override

public void toggle() {

toggle(true);

}

/**

  • 切换状态

  • @param animate

*/

public void toggle(boolean animate) {

toggle(animate, true);

}

private void toggle(boolean animate, boolean broadcast) {

if(!isEnabled()){return;}

if(isEventBroadcast){

throw new RuntimeException(“should NOT switch the state in method: [onCheckedChanged]!”);

}

if(!isUiInited){

isChecked = !isChecked;

if(broadcast){

broadcastEvent();

}

return;

}

if(valueAnimator.isRunning()){

valueAnimator.cancel();

}

if(!enableEffect || !animate){

isChecked = !isChecked;

if(isChecked()){

setCheckedViewState(viewState);

}else{

setUncheckViewState(viewState);

}

postInvalidate();

if(broadcast){

broadcastEvent();

}

return;

}

animateState = ANIMATE_STATE_SWITCH;

beforeState.copy(viewState);

if(isChecked()){

//切换到unchecked

setUncheckViewState(afterState);

}else{

setCheckedViewState(afterState);

}

valueAnimator.start();

}

/**

*/

private void broadcastEvent() {

if(onCheckedChangeListener != null){

isEventBroadcast = true;

onCheckedChangeListener.onCheckedChanged(this, isChecked());

}

isEventBroadcast = false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

if(!isEnabled()){return false;}

int actionMasked = event.getActionMasked();

switch (actionMasked){

case MotionEvent.ACTION_DOWN:{

isTouchingDown = true;

touchDownTime = System.currentTimeMillis();

//取消准备进入拖动状态

removeCallbacks(postPendingDrag);

//预设100ms进入拖动状态

postDelayed(postPendingDrag, 100);

break;

}

case MotionEvent.ACTION_MOVE:{

float eventX = event.getX();

if(isPendingDragState()){

//在准备进入拖动状态过程中,可以拖动按钮位置

float fraction = eventX / getWidth();

fraction = Math.max(0f, Math.min(1f, fraction));

viewState.buttonX = buttonMinX

  • (buttonMaxX - buttonMinX)
  • fraction;

}else if(isDragState()){

//拖动按钮位置,同时改变对应的背景颜色

float fraction = eventX / getWidth();

fraction = Math.max(0f, Math.min(1f, fraction));

viewState.buttonX = buttonMinX

  • (buttonMaxX - buttonMinX)
  • fraction;

viewState.checkStateColor = (int) argbEvaluator.evaluate(

fraction,

uncheckColor,

checkedColor

);

postInvalidate();

}

break;

}

case MotionEvent.ACTION_UP:{

isTouchingDown = false;

//取消准备进入拖动状态

removeCallbacks(postPendingDrag);

if(System.currentTimeMillis() - touchDownTime <= 300){

//点击时间小于300ms,认为是点击操作

toggle();

}else if(isDragState()){

//在拖动状态,计算按钮位置,设置是否切换状态

float eventX = event.getX();

float fraction = eventX / getWidth();

fraction = Math.max(0f, Math.min(1f, fraction));

boolean newCheck = fraction > .5f;

if(newCheck == isChecked()){

pendingCancelDragState();

}else{

isChecked = newCheck;

pendingSettleState();

}

}else if(isPendingDragState()){

//在准备进入拖动状态过程中,取消之,复位

pendingCancelDragState();

}

break;

}

case MotionEvent.ACTION_CANCEL:{

isTouchingDown = false;

removeCallbacks(postPendingDrag);

if(isPendingDragState()

|| isDragState()){

//复位

pendingCancelDragState();

}

break;

}

}

return true;

}

/**

  • 是否在动画状态

  • @return

*/

private boolean isInAnimating(){

return animateState != ANIMATE_STATE_NONE;

}

/**

  • 是否在进入拖动或离开拖动状态

  • @return

*/

private boolean isPendingDragState(){

return animateState == ANIMATE_STATE_PENDING_DRAG

|| animateState == ANIMATE_STATE_PENDING_RESET;

}

/**

  • 是否在手指拖动状态

  • @return

*/

private boolean isDragState(){

return animateState == ANIMATE_STATE_DRAGING;

}

/**

  • 设置是否启用阴影效果

  • @param shadowEffect true.启用

*/

public void setShadowEffect(boolean shadowEffect) {

if(this.shadowEffect == shadowEffect){return;}

this.shadowEffect = shadowEffect;

if(this.shadowEffect){

buttonPaint.setShadowLayer(

shadowRadius,

0, shadowOffset,

shadowColor);

}else{

buttonPaint.setShadowLayer(

0,

0, 0,

0);

}

}

public void setEnableEffect(boolean enable){

this.enableEffect = enable;

}

/**

  • 开始进入拖动状态

*/

private void pendingDragState() {

if(isInAnimating()){return;}

if(!isTouchingDown){return;}

if(valueAnimator.isRunning()){

valueAnimator.cancel();

}

animateState = ANIMATE_STATE_PENDING_DRAG;

beforeState.copy(viewState);

afterState.copy(viewState);

if(isChecked()){

afterState.checkStateColor = checkedColor;

afterState.buttonX = buttonMaxX;

afterState.checkedLineColor = checkedColor;

}else{

afterState.checkStateColor = uncheckColor;

afterState.buttonX = buttonMinX;

afterState.radius = viewRadius;

}

valueAnimator.start();

}

/**

  • 取消拖动状态

*/

private void pendingCancelDragState() {

if(isDragState() || isPendingDragState()){

if(valueAnimator.isRunning()){

valueAnimator.cancel();

}

animateState = ANIMATE_STATE_PENDING_RESET;

beforeState.copy(viewState);

if(isChecked()){

setCheckedViewState(afterState);

}else{

setUncheckViewState(afterState);<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值