jQuery鼠标指针特效

BottomDotTextView--底部有个小圆点

BottomDotTextView

package com.android.myapplication.demo5;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.WindowManager;
import android.view.animation.BounceInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;

import com.android.myapplication.demo6.utils.UiUtils;

import androidx.annotation.Nullable;
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;


@SuppressLint("AppCompatCustomView")
public class BottomRopTextView extends TextView {
    private static final int DEFAULT_CIRCLE_RADIUS = 2;
    private static final int DEFAULT_CIRCLE_COLOR = Color.RED;
    private static final int DEFAULT_TEXT_COLOR = Color.WHITE;//Color.WHITE
    private static final int DEFAULT_TOP_GAP = 8;
    private static final int DEFAULT_CLOCK_VIEW_WIDTH = 150;
    private static final String DEFAULT_TEXT_VALUE = "开关";


    private int mScaleViewWidth;
    private int mScaleViewHeight;
    private int mScaleViewGap;
    private int mScaleViewRadius;
    private int mCirCleColor;

    private int mDigitalTimeTextStartX;
    private int mDigitalTimeTextStartY;
    private int mScaleTextSize;
    private int mScaleTextColor;
    private String mScaleText;


    private Paint mPaint;
    private Rect textRect;//控制文本范围
    private Rect mClockViewRect;//边框

    /**
     * 是否显示
     */
    private boolean isShowDot = false;
    private boolean refreshIImmediately = true;

    public BottomRopTextView(Context context) {
        this(context, null);
    }

    public BottomRopTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BottomRopTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mScaleViewGap = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                DEFAULT_TOP_GAP, getResources().getDisplayMetrics());
        mScaleViewRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                DEFAULT_CIRCLE_RADIUS, getResources().getDisplayMetrics());

        mScaleTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                20, getResources().getDisplayMetrics());

        mScaleViewWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,DEFAULT_CLOCK_VIEW_WIDTH,
                getResources().getDisplayMetrics());

        mScaleText = DEFAULT_TEXT_VALUE;
        mScaleTextColor = DEFAULT_TEXT_COLOR;
        mCirCleColor = DEFAULT_CIRCLE_COLOR;

        //init
        textRect = new Rect();
        mClockViewRect = new Rect();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(mScaleTextColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(mScaleTextSize);

    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int len = w > h ? h : w;
        mClockViewRect.set(0, 0, len, len);
        mClockViewRect.offset((w - len) / 2, (h - len) / 2);
        int mClockViewCenterX = mClockViewRect.centerX();
        int mClockViewCenterY = mClockViewRect.centerY();
        mDigitalTimeTextStartX = mClockViewCenterX - textRect.left - textRect.width() / 2;
        mDigitalTimeTextStartY = mClockViewCenterY - textRect.top - textRect.height() / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //拿到Text的宽高
        mPaint.getTextBounds(mScaleText, 0, mScaleText.length(), textRect);
        canvas.drawText(mScaleText, mDigitalTimeTextStartX, mDigitalTimeTextStartY, mPaint);
        canvas.save();

        // 控制小球绘制的位置
        float x = (textRect.width() + getPaddingRight() + getPaddingLeft()) / 2;
        float circleX = mDigitalTimeTextStartX + x;
        float circleY = mDigitalTimeTextStartY + mScaleViewGap;
        //是否绘制小球
        if (isShowDot) {
            canvas.drawCircle(circleX,circleY,mScaleViewRadius, mPaint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthSpecMode != MeasureSpec.EXACTLY) {
            widthMeasureSpec = mScaleViewWidth;
        }
        if (heightSpecMode != MeasureSpec.EXACTLY) {

        }
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }
    private  ValueAnimator valueAnimator;
    public void performAnimation(){
        cancelAnimation();
        valueAnimator = ValueAnimator.ofInt(0, mScaleViewRadius);
        valueAnimator.setDuration(300);
        valueAnimator.setInterpolator(new BounceInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mScaleViewRadius = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.start();
    }

    public void cancelAnimation() {
        if (valueAnimator != null) {
            valueAnimator.removeAllUpdateListeners();
            valueAnimator.removeAllListeners();
            valueAnimator.cancel();
            valueAnimator = null;
        }
    }

    public void isRefreshIImmediately() {
        //invalidate();
        //postInvalidate();
    }

    public void isShowDot(boolean isShow){
        isShowDot = isShow;
        //invalidate();
    }

    public void setCirCleColor(int cirCleColor) {
        mCirCleColor = cirCleColor;
    }

    public void setDefaultTextColor(int textColor){
        mScaleTextColor = textColor;
    }

    public void setDefaultCircleRadius(int circleRadius){
        mScaleViewRadius = circleRadius;
    }

    public void setDefaultCircleGap(int circleGap){
        mScaleViewGap = circleGap;
    }

    public void setDefaultTextValue(String textValue){
        mScaleText = textValue;
    }

}

半成品--失败

public class DotTextView extends TextView {
    private static final int DEFAULT_CIRCLE_COLOR = Color.RED;
    private static final int DEFAULT_CIRCLE_RADIUS = 2;
    private static final int DEFAULT_TOP_GAP = 8;


    private int cirCleColor;
    private int circleRadius;
    private int textToCircle_Y;

    private Rect textRect;
    private Paint mPaint;
    private boolean isDebug;
    private Paint debugPaint = new Paint();

    public DotTextView(Context context) {
        this(context, null);
    }

    public DotTextView(Context context, @Nullable AttributeSet attrs) {

        this(context, attrs, 0);
    }

    public DotTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        textToCircle_Y = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TOP_GAP,
                getResources().getDisplayMetrics());
        circleRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_CIRCLE_RADIUS,
                getResources().getDisplayMetrics());
        cirCleColor = DEFAULT_CIRCLE_COLOR;

        //init
        textRect = new Rect();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(cirCleColor);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        final Layout textLayout = getLayout();
        final float contentTextLeftX = textLayout.getPrimaryHorizontal(0);  //文字x起点
        final float contentTextRightX = contentTextLeftX + textLayout.getLineWidth(0);//文字x终点

        // 获取View本身文本的Paint对象,再得到文本的Rect对象
        getPaint().getTextBounds(getText().toString(), 0, getText().length(), textRect);

        final float circleX;
        final float circleY;
        final int Width = textRect.centerX();
        final int Height = textRect.centerY();


        //getTotalPaddingStart() ,getTotalPaddingStart(),getPaddingTop() padding 的值


        circleX = contentTextRightX / 2 + getTotalPaddingStart();
        circleY = getTotalPaddingTop() + getLineHeight() * textLayout.getLineCount() + textToCircle_Y;

        Log.d("tww", "left" + contentTextLeftX);
        Log.d("tww", "right" + contentTextRightX);
        Log.d("tww", "circleX" + circleX);
        /*
        * left0.0
         <com.android.myapplication.demo7.DotTextView
          android:layout_width="200dp"
          android:layout_height="60dp"
          android:gravity="center_vertical"
          android:text="开关"
          android:textSize="25sp"
          android:paddingLeft="100dp"
          />
        *
        * */

        canvas.drawCircle(circleX, circleY, circleRadius, mPaint); // 画圆点


        if (isDebug) {
            debugPaint.setColor(Color.GRAY);
            final int textWidth = textRect.width();
            final int textHeight = textRect.height();

            final String textAttr = String.format("[(文字总宽度=%s, 高度=%s, 行数=%s)]", textWidth, textHeight, textLayout.getLineCount());
            canvas.drawText(textAttr, 0, textHeight, debugPaint);

            final String viewAttr = String.format("[(DotTextView宽度=%s, 高度=%s)]", getWidth(), getHeight());
            canvas.drawText(viewAttr, 0, textHeight * 2, debugPaint);

            final String appAttr = String.format("[(每行文字高度(包含文字间距)=%s)]", getLineHeight());
            canvas.drawText(appAttr, 0, textHeight * 3, debugPaint);

            final String drawableAttr = String.format("[(左图标间距=%s,右图标间距=%s,上图标间距=%s,下图标间距=%s)]", getCompoundPaddingStart(), getCompoundPaddingEnd(), getCompoundPaddingTop(), getCompoundPaddingBottom());
            canvas.drawText(drawableAttr, 0, textHeight * 4, debugPaint);
        }
    }

    /*
    *  switch (dotGravity) {
            case LEFT_TOP:
                circleX = contentTextLeftX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + dotOffsetY;
                break;
            case RIGHT_TOP:
                circleX = contentTextRightX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + dotOffsetY;
                break;
            case LEFT_BOTTOM:
                circleX = contentTextLeftX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + getLineHeight() * textLayout.getLineCount() + dotOffsetY; // 总内间距 + 每行文字高度 * 文字行数 + 圆点上边距
                break;
            case RIGHT_BOTTOM:
                circleX = contentTextRightX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + getLineHeight() * textLayout.getLineCount() + dotOffsetY;  // 同 LEFT_BOTTOM
                break;
            case LEFT_CENTER:
                circleX = contentTextLeftX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + (getLineHeight() * textLayout.getLineCount()) / 2 + dotOffsetY;
                break;
            case RIGHT_CENTER:
                circleX = contentTextRightX + dotOffsetX + getTotalPaddingStart();
                circleY = getTotalPaddingTop() + (getLineHeight() * textLayout.getLineCount()) / 2 + dotOffsetY;
                break;
            case LEFT_DRAWABLE_CENTER:
                if (getCompoundDrawables()[0] == null) {
                    circleX = contentTextLeftX + dotOffsetX + getTotalPaddingStart();
                } else {
                    circleX = contentTextLeftX + dotOffsetX;
                }
                circleY = getTotalPaddingTop() + (getLineHeight() * textLayout.getLineCount()) / 2 + dotOffsetY;
                break;
            case RIGHT_DRAWABLE_CENTER:
                if (getCompoundDrawables()[2] == null) {
                    circleX = contentTextRightX + dotOffsetX + getTotalPaddingStart();
                } else {
                    circleX = contentTextRightX + dotOffsetX + getTotalPaddingEnd() + getTotalPaddingStart();
                }
                circleY = getTotalPaddingTop() + (getLineHeight() * textLayout.getLineCount()) / 2 + dotOffsetY;
                break;
            default:
                circleX = 0;
                circleY = 0;
                break;
        }
    *
    * */
}

组合控件-MulDotTextView

点击查看代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:minHeight="48dp"
    android:layout_height="48dp"
    >

    <TextView
        android:id="@+id/tab_item"
        android:text="开关"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:gravity="center"

        />

    <ImageView
        android:id="@+id/iv_bottom"
        android:layout_width="3dp"
        android:layout_height="3dp"
        android:layout_marginTop="-10dp"
        android:src="@drawable/small_circle"
        android:layout_below="@id/tab_item"
        android:layout_centerInParent="true"
        />

</RelativeLayout>
//--------------分割线
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    >
    <solid android:color="@color/white"/>
    <size android:width="5dp" android:height="5dp"/>
</shape>
//-------------
public class MulDotTextView extends RelativeLayout {
    private TextView mTabTextView;
    private ImageView mDotView;

    public MulDotTextView(Context context) {
        this(context, null);
    }

    public MulDotTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MulDotTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        layoutInflater.inflate(R.layout.tab_dot_textview, this);

        mTabTextView = findViewById(R.id.tab_item);
        mDotView = findViewById(R.id.iv_bottom);
    }


    public void outAnimator() {
        ObjectAnimator outAnimator = ObjectAnimator.ofFloat(mDotView, "alpha", 1f, 0);

        DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();

        ObjectAnimator translationAnimator = outAnimator.ofFloat(mDotView, "translationX", 0, 20f);

        AnimatorSet animatorSet = new AnimatorSet();

        animatorSet.setDuration(1500);
        animatorSet.setInterpolator(decelerateInterpolator);
        animatorSet.playTogether(translationAnimator,outAnimator);
        animatorSet.start();
    }


    public void inAnimator() {
        ObjectAnimator inAnimator = ObjectAnimator.ofFloat(mDotView, "alpha", 0, 1f);
        DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();

        ObjectAnimator translationAnimator = inAnimator.ofFloat(mDotView, "translationX", -20f, 0);
        AnimatorSet animatorSet = new AnimatorSet();

        animatorSet.setDuration(1500);
        animatorSet.setInterpolator(decelerateInterpolator);
        animatorSet.playTogether(translationAnimator,inAnimator);
        animatorSet.start();
    }


    public interface getNewAnimators {
        void inAnimator();
        void outAnimator();
    }
}
//-----------判断viewPager左滑还是右滑
//记录上一次滑动的positionOffsetPixels值
    int lastValue = -1;
    boolean isLeft = true;

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //Log.d("tww","positionOffset"+positionOffset);
                //Log.d("tww","positionOffsetPixels"+positionOffsetPixels);
                if(positionOffset != 0){
                    if(lastValue >= positionOffsetPixels){
                        //右滑
                        isLeft = false;
                    }else if(lastValue < positionOffsetPixels){
                        //左滑
                        isLeft = true;
                    }
                }
                //--> positionOffsetPixels ↑          <--positionOffsetPixels ↓
                lastValue = positionOffsetPixels;
            }

            @Override
            public void onPageSelected(int position) {
                if (isLeft){
                    m1.inAnimator();
                    m2.outAnimator();
                    Log.d("tww","--->left");
                }else {
                    m2.inAnimator();
                    m1.outAnimator();
                    Log.d("tww","--->right");
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }
posted @ 2022-01-13 15:14  僵小七  阅读(56)  评论(0编辑  收藏  举报