Android开发自定义控件实现一个球赛胜负数统计条

效果如下图所示,展示两个球队交战胜负信息

首先此控件在水平方向均分为5份,第一份和第五份留白不绘制内容

第二三四份分别绘制3列数据

垂直方向分为N份,N和输入数据的最大值有关

垂直方向下边百分之二十的空间显示文本,上边百分之八十的空间显示指定数量的横线,横线上方显示横线的数量

因为垂直方向做了N等分,因此垂直方向相当于有了一个刻度,经过计算每条横线绘制在属于自己的刻度处即可



完整代码如下:

public class GameOutcomeBar extends View {
    private Context context;
    /*y方向的刻度,数据越多,刻度值越小*/
    private int MAX_GRADE=20;
    /*记录 胜场 平局 负场 画笔颜色*/
    private int mWinColor;
    private int mDrawColor;
    private int mLoseColor;
    /*胜场 平局 负场 数量*/
    private int mWins;
    private int mDraws;
    private int mLoses;
    private TypedValue typedValue;
    /*绘制图形的画笔*/
    private Paint paintBar = new Paint();
    /*绘制文字的画笔*/
    private Paint paintText = new Paint();
    public GameOutcomeBar(Context context) {
        super(context);
        this.context=context;
        init();
    }

    public GameOutcomeBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
        init();
    }

    public GameOutcomeBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context=context;
        init();
    }



    private void init() {
        /*数据初始化*/
        mWinColor = Color.BLUE;
        mDrawColor =Color.YELLOW;
        mLoseColor =Color.GREEN;
        mWins =0;
        mDraws =0;
        mLoses =0;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /*总宽度*/
        float totalWidth =getWidth();
        /*除了下边文字以外的高度,下边文字占据的高度是总高度的百分之二十*/
        float totalBarHeight =getHeight()*0.8f;
        /*画笔大小的标准*/
        float paintSize = DensityUtil.dip2px(getContext(),100);
        /*控件整个宽度分为5列,第一列和第五列留白,第二三四列分别绘制胜场、平局和负场*/
        float columnLength = totalWidth /5;
        /*三列之间的间距*/
        float columnSpan = totalWidth /40;

        /*绘制横线的画笔设置*/
        paintBar.reset();
        paintBar.setStrokeWidth(paintSize * 1f/2 / MAX_GRADE / 3);
        paintBar.setStyle(Paint.Style.STROKE);
        paintBar.setAntiAlias(true);
        /*绘制胜场*/
        paintBar.setColor(mWinColor);
        /*循环绘制横线*/
        for (int i = 0; i< mWins; i++) {
            /*计算每一条横线的垂直坐标位置*/
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            /*合适的位置开始绘制横线*/
            canvas.drawLine(totalWidth * 1 / 5 - columnSpan,eachLineHeight ,
                    totalWidth * 2 / 5 - columnSpan, eachLineHeight,paintBar);
        }
        /*绘制文字画笔设置*/
        paintText.reset();
        paintText.setStyle(Paint.Style.STROKE);
        paintText.setAntiAlias(true);
        /*文字从中间开始绘制*/
        paintText.setTextAlign(Paint.Align.CENTER);
        typedValue=new TypedValue();
        /*设置文字画笔颜色*/
        context.getTheme().resolveAttribute(R.attr.maintextclor, typedValue,true);
        paintText.setColor(getResources().getColor(typedValue.resourceId));
        /*设置文字画笔大小*/
        paintText.setTextSize(paintSize / 5);
        /*绘制文字,在横线列的最上方绘制数字*/
        canvas.drawText("" + mWins, totalWidth * 1 / 5 - columnSpan + columnLength /2, totalBarHeight * (1f- (mWins +2f) / MAX_GRADE), paintText);
        /*更改文字画笔大小,在横线列的下方绘制文本*/
        paintText.setTextSize(paintSize / 15);
        Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
        canvas.drawText("胜场" , totalWidth * 1 / 5 - columnSpan + columnLength /2, totalBarHeight-fontMetrics.top, paintText);

        /*绘制平局*/
        paintBar.setColor(mDrawColor);
        for (int i = 0; i< mDraws; i++) {
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            canvas.drawLine(totalWidth * 2 / 5 , eachLineHeight,
                    totalWidth * 3 / 5  , eachLineHeight,paintBar);
        }
        paintText.setTextSize(paintSize / 5);
        canvas.drawText("" + mDraws, totalWidth * 2 / 5 + columnLength / 2, totalBarHeight * (1f - (mDraws +2f) / MAX_GRADE), paintText);
        paintText.setTextSize(paintSize / 15);
        fontMetrics = paintText.getFontMetrics();
        canvas.drawText("平局" , totalWidth * 2 / 5+ columnLength /2, totalBarHeight -fontMetrics.top, paintText);

        /*绘制负场*/
        paintBar.setColor(mLoseColor);
        for (int i = 0; i< mLoses; i++) {
            float eachLineHeight=totalBarHeight * (1f-(i+2f) / MAX_GRADE);
            canvas.drawLine(totalWidth * 3 / 5 + columnSpan, eachLineHeight,
                    totalWidth * 4 / 5 + columnSpan, eachLineHeight,paintBar);
        }
        paintText.setTextSize(paintSize / 5);
        canvas.drawText("" + mLoses, totalWidth * 3 / 5 + columnSpan + columnLength /2, totalBarHeight * (1f - (mLoses +2f) / MAX_GRADE), paintText);
        paintText.setTextSize(paintSize / 15);
        fontMetrics = paintText.getFontMetrics();
        canvas.drawText("负场" , totalWidth * 3 / 5 + columnSpan + columnLength /2, totalBarHeight-fontMetrics.top, paintText);
    }

    public void setWinsDrawLose(int wins,int draw, int lose) {
        if (wins<0||draw<0||lose<0) {
            throw new IllegalArgumentException("参数不能小于零");
        }
        this.mWins =wins;
        this.mDraws =draw;
        this.mLoses =lose;
        this.MAX_GRADE=Math.max(wins,Math.max(draw,lose))+15;
        this.invalidate();
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 实现统计的功能可以使用Android系统提供的传感器API,例如计步器传感器。而加入据库的功能,则需要使用Android系统提供的SQLite据库API。 下面是一个简单的实现统计并加入据库的自定义控件的示例: 1. 创建一个自定义控件类,继承自View或其子类。 ``` public class StepCounterView extends View implements SensorEventListener { private SensorManager sensorManager; private Sensor stepSensor; private int stepCount = 0; private boolean isSensorActive = false; public StepCounterView(Context context) { super(context); init(); } public StepCounterView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public StepCounterView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { sensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); stepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (stepSensor != null) { sensorManager.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_NORMAL); isSensorActive = true; } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (isSensorActive) { sensorManager.unregisterListener(this); isSensorActive = false; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制步 String text = "步:" + stepCount; Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setTextSize(50); canvas.drawText(text, 0, 50, paint); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) { stepCount = (int) event.values[0]; // 更新UI invalidate(); // 将步保存到据库中 saveToDatabase(stepCount); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } private void saveToDatabase(int stepCount) { // 创建据库 SQLiteDatabase db = getContext().openOrCreateDatabase("step.db", Context.MODE_PRIVATE, null); // 创建表 db.execSQL("CREATE TABLE IF NOT EXISTS step (id INTEGER PRIMARY KEY AUTOINCREMENT, step_count INTEGER)"); // 插入据 ContentValues values = new ContentValues(); values.put("step_count", stepCount); db.insert("step", null, values); // 关闭据库 db.close(); } } ``` 2. 在布局文件中添加自定义控件。 ``` <com.example.StepCounterView android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 3. 运行程序,即可看到实时步的显示,并且步也会被保存到名为“step.db”的据库中。 ### 回答2: 要实现Android中的自定义控件实现统计并加入据库的功能,可以按照以下步骤进行: 1. 创建一个自定义控件,继承自Android中的View类,并实现自己的界面布局和逻辑。 2. 在自定义控件中,可以使用SensorManager类来获取传感器据,如加速度传感器或计步传感器,用于实时地获取步信息。 3. 在自定义控件中,可以使用SQLiteOpenHelper类来创建一个据库,并定义据库的表结构,用于存储步信息。 4. 在自定义控件中,可以使用ContentValues类来组装步信息的据,并通过SQLiteDatabase类来插入据库中。 5. 在自定义控件中,可以使用SharedPreferences类来保存用户的步目标和历史步据,以便实现目标的设定和步统计的管理。 6. 在自定义控件中,可以使用Paint类来绘制步信息的界面,如文字、图标等,以便将统计结果显示在界面上。 7. 在使用自定义控件的Activity中,可以通过findViewById方法找到该控件,并根据需要设置控件的属性和监听器。 通过以上步骤,就可以实现Android中的自定义控件实现统计并加入据库的功能。用户可以使用该控件来实时统计,并将步信息存储到据库中,方便后续查看和管理。 ### 回答3: 要实现 Android 中的自定义控件实现统计并加入据库的功能,可以按照以下步骤进行。 首先,创建一个自定义的视图类,继承自 Android 的 View 类。在该类中,定义用于展示步的 TextView 控件,并提供一些方法用于更新步的显示。 其次,为该自定义视图类添加一些必要的属性和方法,比如记录当前步的变量、获取、设置步的方法等。 然后,为了实现统计功能,我们需要在该自定义视图类中添加与传感器相关的代码。可以使用 Android 提供的传感器 API,如 SensorManager、SensorEventListener 等。通过注册传感器监听器,并在监听器中根据步行算法来统计的变化。 接着,我们需要将统计到的步存入据库中。首先,创建一个据库类,继承自 Android 的 SQLiteOpenHelper 类。在该类中,定义用于创建和升级据库的方法,并提供一些方便操作据库的方法,比如插入据、查询据等。 在自定义视图类中,获取到步后,调用据库类的方法将步存入据库中。可以通过 ContentValues 类来组织要插入的据,并使用 SQLiteDatabase 类的 insert() 方法将据插入到据库中。 最后,在使用该自定义控件的 Activity 中,实例化据库类,并在合适的地方调用自定义视图类的方法来更新步的显示,并将获取到的步存入据库中。 通过以上步骤,我们就可以实现 Android自定义控件实现统计并加入据库的功能。同时,我们可以通过据库来保存历史步据,并在需要的时候进行查询和展示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值