滚轮选择时间控件-选择数值-选择字符串

滚轮选择控件

android自带的选择时间控件有点丑,往往产品和设计都比较嫌弃,希望做成ios一样的滚轮选择,下面是我在NumberPicker的基础上自定义的选择控件,效果如下:
这里写图片描述

原理

  • 基于NumberPicker实现
  • 动态填充数值
  • 联动
  • 接口监听回调

实现滚轮效果有github上mark比较多的WheelView,但是阅读源码发现数据是一次性填入的,选择时间的话,填入10年就是10*365=3650条数据,也就是new出三千多个TextView,想想都觉得恐怖,肯定是不行的,于是便想到用NumberPicker,动态填充数据,一次只设置5个数据,当选中变化时,重新设置数据填充,所以关键在于填充的数据的计算。

设置数据部分逻辑代码:

    /**
     * 更新左侧控件
     * 日期:选择年控件
     * 时间:选择月份和日期控件
     *
     * @param timeMillis
     */
    private void updateLeftValue(long timeMillis) {
        SimpleDateFormat sdf;
        String str[] = new String[DATA_SIZE];
        if (mCurrentType == TYPE_PICK_DATE) {
            sdf = new SimpleDateFormat("yyyy");
            for (int i = 0; i < DATA_SIZE; i++) {
                Calendar cal = Calendar.getInstance();
                cal.setTimeInMillis(timeMillis);
                cal.add(Calendar.YEAR, (i - DATA_SIZE / 2));
                str[i] = sdf.format(cal.getTimeInMillis());
            }
        } else {
            sdf = new SimpleDateFormat("MM-dd EEE");
            for (int i = 0; i < DATA_SIZE; i++) {
                Calendar cal = Calendar.getInstance();
                cal.setTimeInMillis(timeMillis);
                cal.add(Calendar.DAY_OF_MONTH, (i - DATA_SIZE / 2));
                str[i] = sdf.format(cal.getTimeInMillis());
            }
        }
        mNpLeft.setDisplayedValues(str);
        mNpLeft.setValue(DATA_SIZE / 2);
        mNpLeft.postInvalidate();
    }

对滚轮的监听,并重新设置填充数据:

    @Override
    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(mTimeMillis);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int offset = newVal - oldVal;
        if (picker == mNpLeft) {
            if (mCurrentType == TYPE_PICK_DATE) {
                calendar.add(Calendar.YEAR, offset);
            } else {
                calendar.add(Calendar.DAY_OF_MONTH, offset);
            }
            updateLeftValue(calendar.getTimeInMillis());
            mTimeMillis = calendar.getTimeInMillis();
        } else if (picker == mNpMiddle) {
            if (mCurrentType == TYPE_PICK_DATE) {
                calendar.add(Calendar.MONTH, offset);
                if (calendar.get(Calendar.YEAR) != year) {
                    calendar.set(Calendar.YEAR, year);
                }
            } else {
                calendar.add(Calendar.HOUR_OF_DAY, offset);
                if (calendar.get(Calendar.DAY_OF_MONTH) != day) {
                    calendar.set(Calendar.DAY_OF_MONTH, day);
                }
                if (calendar.get(Calendar.MONTH) != month) {
                    calendar.set(Calendar.MONTH, month);
                }
                if (calendar.get(Calendar.YEAR) != year) {
                    calendar.set(Calendar.YEAR, year);
                }
            }
            updateMiddleValue(calendar.getTimeInMillis());
            updateRightValue(calendar.getTimeInMillis());
            mTimeMillis = calendar.getTimeInMillis();
        } else if (picker == mNpRight) {
            if (mCurrentType == TYPE_PICK_DATE) {
                int days = getMaxDayOfMonth(year, month + 1);
                if(day == 1 && offset < 0){
                    calendar.set(Calendar.DAY_OF_MONTH,days);
                }else if(day == days && offset > 0){
                    calendar.set(Calendar.DAY_OF_MONTH,1);
                }else{
                    calendar.add(Calendar.DAY_OF_MONTH, offset);
                }

                if (calendar.get(Calendar.MONTH) != month) {
                    calendar.set(Calendar.MONTH, month);
                }
                if (calendar.get(Calendar.YEAR) != year) {
                    calendar.set(Calendar.YEAR, year);
                }
                Log.e(TAG,"time:::"+test.format(calendar.getTimeInMillis()));
            } else {
                calendar.add(Calendar.MINUTE, offset);
                if (calendar.get(Calendar.HOUR_OF_DAY) != hour) {
                    calendar.set(Calendar.HOUR_OF_DAY, hour);
                }
                if (calendar.get(Calendar.DAY_OF_MONTH) != day) {
                    calendar.set(Calendar.DAY_OF_MONTH, day);
                }
                if (calendar.get(Calendar.MONTH) != month) {
                    calendar.set(Calendar.MONTH, month);
                }
                if (calendar.get(Calendar.YEAR) != year) {
                    calendar.set(Calendar.YEAR, year);
                }
            }
            updateRightValue(calendar.getTimeInMillis());
            mTimeMillis = calendar.getTimeInMillis();
        }
        /**
         * 向外部发送当前选中时间
         */
        if (mOnSelectedChangeListener != null) {
            mOnSelectedChangeListener.onSelected(this,mTimeMillis);
        }
        Log.e(TAG, "selected time:" + test.format(mTimeMillis));
    }

选择数值和字符串

同样的,使用NumberPicker进行封装,动态填充数值从而实现滚动变换的效果。

  • 考虑到通用性,传入的是Object类型的数组,在控件里进行判断。
  • 可以选择一列数值、两列数值、三列数值,字符串同理。每一列数值可以设置它的单位、标题等,默认是隐藏,需要自己设置。
  • 可以设置步长step

完整代码如下:

package com.example.moore.picktimeview.widget;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;

/**
 * Created by Moore on 2016/10/21.
 */

public class PickValueView extends LinearLayout implements NumberPicker.OnValueChangeListener {
    private Context mContext;
    /**
     * 组件 标题、单位、滚轮
     */
    private TextView mTitleLeft, mTitleMiddle, mTitleRight;
    private TextView mUnitLeft, mUnitMiddle, mUnitRight;
    private MyNumberPicker mNpLeft, mNpMiddle, mNpRight;
    /**
     * 数据个数  1列 or 2列 or 3列
     */
    private int mViewCount = 1;
    /**
     * 一组数据长度
     */
    private final int DATA_SIZE = 3;

    /**
     * 需要设置的值与默认值
     */
    private Object[] mLeftValues;
    private Object[] mMiddleValues;
    private Object[] mRightValues;
    private Object mDefaultLeftValue;
    private Object mDefaultMiddleValue;
    private Object mDefaultRightValue;
    /**
     * 当前正在显示的值
     */
    private Object[] mShowingLeft = new Object[DATA_SIZE];
    private Object[] mShowingMiddle = new Object[DATA_SIZE];
    private Object[] mShowingRight = new Object[DATA_SIZE];

    /**
     * 步长
     */
    private int mLeftStep = 5;
    private int mMiddleStep = 1;
    private int mRightStep = 1;
    /**
     * 回调接口对象
     */
    private onSelectedChangeListener mSelectedChangeListener;

    public PickValueView(Context context) {
        super(context);
        this.mContext = context;
        generateView();
    }

    public PickValueView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        generateView();
    }

    public PickValueView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        generateView();
    }

    /**
     * 生成视图
     */
    private void generateView() {
        //标题
        LinearLayout titleLayout = new LinearLayout(mContext);
        LayoutParams titleParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        titleParams.setMargins(0, 0, 0, dip2px(12));
        titleLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        titleLayout.setOrientation(HORIZONTAL);
        mTitleLeft = new TextView(mContext);
        mTitleMiddle = new TextView(mContext);
        mTitleRight = new TextView(mContext);

        LayoutParams params = new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
        TextView[] titles = new TextView[]{mTitleLeft, mTitleMiddle, mTitleRight};
        for (int i = 0; i < titles.length; i++) {
            titles[i].setLayoutParams(params);
            titles[i].setGravity(Gravity.CENTER);
            titles[i].setTextColor(Color.parseColor("#3434EE"));
        }
        titleLayout.addView(mTitleLeft);
        titleLayout.addView(mTitleMiddle);
        titleLayout.addView(mTitleRight);
        //内容
        LinearLayout contentLayout = new LinearLayout(mContext);
        contentLayout.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        contentLayout.setOrientation(HORIZONTAL);
        contentLayout.setGravity(Gravity.CENTER);
        mNpLeft = new MyNumberPicker(mContext);
        mNpMiddle = new MyNumberPicker(mContext);
        mNpRight = new MyNumberPicker(mContext);
        mUnitLeft = new TextView(mContext);
        mUnitMiddle = new TextView(mContext);
        mUnitRight = new TextView(mContext);

        MyNumberPicker[] nps = new MyNumberPicker[]{mNpLeft, mNpMiddle, mNpRight};
        for (int i = 0; i < nps.length; i++) {
            nps[i].setLayoutParams(params);
            nps[i].setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
            nps[i].setOnValueChangedListener(this);
        }

        contentLayout.addView(mNpLeft);
        contentLayout.addView(mUnitLeft);
        contentLayout.addView(mNpMiddle);
        contentLayout.addView(mUnitMiddle);
        contentLayout.addView(mNpRight);
        contentLayout.addView(mUnitRight);

        this.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        this.setOrientation(VERTICAL);
        this.addView(titleLayout);
        this.addView(contentLayout);
    }

    /**
     * 初始化数据和值
     */
    private void initViewAndPicker() {
        if (mViewCount == 1) {
            this.mNpMiddle.setVisibility(GONE);
            this.mNpRight.setVisibility(GONE);
            this.mUnitMiddle.setVisibility(GONE);
            this.mUnitRight.setVisibility(GONE);
        } else if (mViewCount == 2) {
            this.mNpRight.setVisibility(GONE);
            this.mUnitRight.setVisibility(GONE);
        }

        //初始化数组值
        if (mLeftValues != null && mLeftValues.length != 0) {
            if (mLeftValues.length < DATA_SIZE) {
                for (int i = 0; i < mLeftValues.length; i++) {
                    mShowingLeft[i] = mLeftValues[i];
                }
                for (int i = mLeftValues.length; i < DATA_SIZE; i++) {
                    mShowingLeft[i] = -9999;
                }
            } else {
                for (int i = 0; i < DATA_SIZE; i++) {
                    mShowingLeft[i] = mLeftValues[i];
                }
            }
            mNpLeft.setMinValue(0);
            mNpLeft.setMaxValue(DATA_SIZE - 1);
            if (mDefaultLeftValue != null)
                updateLeftView(mDefaultLeftValue);
            else
                updateLeftView(mShowingLeft[0]);
        }
        /**
         * 中间控件
         */
        if (mViewCount == 2 || mViewCount == 3) {
            if (mMiddleValues != null && mMiddleValues.length != 0) {
                if (mMiddleValues.length < DATA_SIZE) {
                    for (int i = 0; i < mMiddleValues.length; i++) {
                        mShowingMiddle[i] = mMiddleValues[i];
                    }
                    for (int i = mMiddleValues.length; i < DATA_SIZE; i++) {
                        mShowingMiddle[i] = -9999;
                    }
                } else {
                    for (int i = 0; i < DATA_SIZE; i++) {
                        mShowingMiddle[i] = mMiddleValues[i];
                    }
                }
                mNpMiddle.setMinValue(0);
                mNpMiddle.setMaxValue(DATA_SIZE - 1);
                if (mDefaultMiddleValue != null)
                    updateMiddleView(mDefaultMiddleValue);
                else
                    updateMiddleView(mShowingMiddle[0]);
            }
        }

        /**
         * 右侧控件
         */
        if (mViewCount == 3) {
            if (mRightValues != null && mRightValues.length != 0) {
                if (mRightValues.length < DATA_SIZE) {
                    for (int i = 0; i < mRightValues.length; i++) {
                        mShowingRight[i] = mRightValues[i];
                    }
                    for (int i = mRightValues.length; i < DATA_SIZE; i++) {
                        mShowingRight[i] = -9999;
                    }
                } else {
                    for (int i = 0; i < DATA_SIZE; i++) {
                        mShowingRight[i] = mRightValues[i];
                    }
                }
                mNpRight.setMinValue(0);
                mNpRight.setMaxValue(DATA_SIZE - 1);
                if (mDefaultRightValue != null)
                    updateRightView(mDefaultRightValue);
                else
                    updateRightView(mShowingRight[0]);
            }
        }


    }

    private void updateLeftView(Object value) {
        updateValue(value, 0);
    }

    private void updateMiddleView(Object value) {
        updateValue(value, 1);
    }

    private void updateRightView(Object value) {
        updateValue(value, 2);
    }

    /**
     * 更新滚轮视图
     *
     * @param value
     * @param index
     */
    private void updateValue(Object value, int index) {
        String showStr[] = new String[DATA_SIZE];
        MyNumberPicker picker;
        Object[] showingValue;
        Object[] values;
        int step;
        if (index == 0) {
            picker = mNpLeft;
            showingValue = mShowingLeft;
            values = mLeftValues;
            step = mLeftStep;
        } else if (index == 1) {
            picker = mNpMiddle;
            showingValue = mShowingMiddle;
            values = mMiddleValues;
            step = mMiddleStep;
        } else {
            picker = mNpRight;
            showingValue = mShowingRight;
            values = mRightValues;
            step = mRightStep;
        }

        if (values instanceof Integer[]) {
            for (int i = 0; i < DATA_SIZE; i++) {
                showingValue[i] = (int) value - step * (DATA_SIZE / 2 - i);
                int offset = (int) values[values.length - 1] - (int) values[0] + step;
                if ((int) showingValue[i] < (int) values[0]) {
                    showingValue[i] = (int) showingValue[i] + offset;
                }
                if ((int) showingValue[i] > (int) values[values.length - 1]) {
                    showingValue[i] = (int) showingValue[i] - offset;
                }
                showStr[i] = "" + showingValue[i];
            }
        } else {
            int strIndex = 0;
            for (int i = 0; i < values.length; i++) {
                if (values[i].equals(value)) {
                    strIndex = i;
                    break;
                }
            }
            for (int i = 0; i < DATA_SIZE; i++) {
                int temp = strIndex - (DATA_SIZE / 2 - i);
                if (temp < 0) {
                    temp += values.length;
                }
                if (temp >= values.length) {
                    temp -= values.length;
                }
                showingValue[i] = values[temp];
                showStr[i] = (String) values[temp];
            }
        }
        picker.setDisplayedValues(showStr);
        picker.setValue(DATA_SIZE / 2);
        picker.postInvalidate();
    }


    @Override
    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        if (picker == mNpLeft) {
            updateLeftView(mShowingLeft[newVal]);
        } else if (picker == mNpMiddle) {
            updateMiddleView(mShowingMiddle[newVal]);
        } else if (picker == mNpRight) {
            updateRightView(mShowingRight[newVal]);
        }
        if (mSelectedChangeListener != null) {
            mSelectedChangeListener.onSelected(this, mShowingLeft[DATA_SIZE / 2], mShowingMiddle[DATA_SIZE / 2], mShowingRight[DATA_SIZE / 2]);
        }
    }

    /**
     * 设置数据--单列数据
     *
     * @param leftValues
     * @param mDefaultLeftValue
     */
    public void setValueData(Object[] leftValues, Object mDefaultLeftValue) {
        this.mViewCount = 1;
        this.mLeftValues = leftValues;
        this.mDefaultLeftValue = mDefaultLeftValue;

        initViewAndPicker();
    }

    /**
     * 设置数据--两列数据
     *
     * @param leftValues
     * @param mDefaultLeftValue
     * @param middleValues
     * @param defaultMiddleValue
     */
    public void setValueData(Object[] leftValues, Object mDefaultLeftValue, Object[] middleValues, Object defaultMiddleValue) {
        this.mViewCount = 2;
        this.mLeftValues = leftValues;
        this.mDefaultLeftValue = mDefaultLeftValue;

        this.mMiddleValues = middleValues;
        this.mDefaultMiddleValue = defaultMiddleValue;

        initViewAndPicker();
    }

    /**
     * 设置数据--三列数据
     *
     * @param leftValues
     * @param mDefaultLeftValue
     * @param middleValues
     * @param defaultMiddleValue
     * @param rightValues
     * @param defaultRightValue
     */
    public void setValueData(Object[] leftValues, Object mDefaultLeftValue, Object[] middleValues, Object defaultMiddleValue, Object[] rightValues, Object defaultRightValue) {
        this.mViewCount = 3;
        this.mLeftValues = leftValues;
        this.mDefaultLeftValue = mDefaultLeftValue;

        this.mMiddleValues = middleValues;
        this.mDefaultMiddleValue = defaultMiddleValue;

        this.mRightValues = rightValues;
        this.mDefaultRightValue = defaultRightValue;

        initViewAndPicker();
    }

    /**
     * 设置左边数据步长
     *
     * @param step
     */
    public void setLeftStep(int step) {
        this.mLeftStep = step;
        initViewAndPicker();
    }

    /**
     * 设置中间数据步长
     *
     * @param step
     */
    public void setMiddleStep(int step) {
        this.mMiddleStep = step;
        initViewAndPicker();
    }

    /**
     * 设置右边数据步长
     *
     * @param step
     */
    public void setRightStep(int step) {
        this.mRightStep = step;
        initViewAndPicker();
    }

    /**
     * 设置标题
     *
     * @param left
     * @param middle
     * @param right
     */
    public void setTitle(String left, String middle, String right) {
        if (left != null) {
            mTitleLeft.setVisibility(VISIBLE);
            mTitleLeft.setText(left);
        } else {
            mTitleLeft.setVisibility(GONE);
        }
        if (middle != null) {
            mTitleMiddle.setVisibility(VISIBLE);
            mTitleMiddle.setText(middle);
        } else {
            mTitleMiddle.setVisibility(GONE);
        }
        if (right != null) {
            mTitleRight.setVisibility(VISIBLE);
            mTitleRight.setText(right);
        } else {
            mTitleRight.setVisibility(GONE);
        }
        this.postInvalidate();
    }

    public void setUnitLeft(String unitLeft) {
        setUnit(unitLeft, 0);
    }

    public void setmUnitMiddle(String unitMiddle) {
        setUnit(unitMiddle, 1);
    }

    public void setUnitRight(String unitRight) {
        setUnit(unitRight, 2);
    }

    private void setUnit(String unit, int index) {
        TextView tvUnit;
        if (index == 0) {
            tvUnit = mUnitLeft;
        } else if (index == 1) {
            tvUnit = mUnitMiddle;
        } else {
            tvUnit = mUnitRight;
        }
        if (unit != null) {
            tvUnit.setText(unit);
        } else {
            tvUnit.setText(" ");
        }
        initViewAndPicker();
    }

    /**
     * 设置回调
     *
     * @param listener
     */
    public void setOnSelectedChangeListener(onSelectedChangeListener listener) {
        this.mSelectedChangeListener = listener;
    }

    /**
     * dp转px
     *
     * @param dp
     * @return
     */
    private int dip2px(int dp) {
        float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (scale * dp + 0.5f);
    }

    /**
     * 回调接口
     */
    public interface onSelectedChangeListener {
        void onSelected(PickValueView view, Object leftValue, Object middleValue, Object rightValue);
    }
}

关于NumberPicker

默认的NumberPicker往往字体颜色、分割线颜色等都是跟随系统,不能改变,考虑到可能比较丑或者有其他需求,所以自定义的NumberPicker,通过反射的方式更改里面的一些属性,代码如下:

package com.example.moore.picktimeview.widget;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.NumberPicker;

import java.lang.reflect.Field;

/**
 * Created by Moore on 2016/10/20.
 */

public class MyNumberPicker extends NumberPicker {
    private static int mTextSize = 16;
    private static int mTextColor = 0x000000;
    private static int mDividerColor = 0xFFFF00;

    public MyNumberPicker(Context context) {
        super(context);
        setNumberPickerDividerColor();
    }

    public MyNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        setNumberPickerDividerColor();
    }

    public MyNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setNumberPickerDividerColor();
    }

    @Override
    public void addView(View child) {
        super.addView(child);
        updateView(child);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        updateView(child);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        super.addView(child, params);
        updateView(child);
    }

    private void updateView(View view) {
        if (view instanceof EditText) {
//            ((EditText) view).setTextSize(mTextSize);
            ((EditText) view).setTextSize(17);
//            ((EditText) view).setTextColor(mTextColor);
            ((EditText) view).setTextColor(Color.parseColor("#6495ED"));
        }
    }

    private void setNumberPickerDividerColor() {
        Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        /**
         * 设置分割线颜色
         */
        for (Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
//                    pf.set(this, new ColorDrawable(mDividerColor));
                    pf.set(this, new ColorDrawable(Color.parseColor("#C4C4C4")));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        /**
         * 设置分割线高度
         */
        for (Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDividerHeight")) {
                pf.setAccessible(true);
                try {
                    pf.set(this, 2);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        for (Field pf : pickerFields) {
            if (pf.getName().equals("mSelectorElementHeight")) {
                pf.setAccessible(true);
                try {
                    pf.set(this, 2);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }

    public void setDividerColor(int color) {
        this.mDividerColor = color;
//        this.postInvalidate();
    }

    public void setTextColor(int color) {
        this.mTextColor = color;
//        this.postInvalidate();
    }

    public void setTextSize(int textSize) {
        this.mTextSize = textSize;
//        this.postInvalidate();
    }
}

完整Demo可前往github查看与下载,地址:https://github.com/lizebinbin/PickTimeView.git 谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值