android:自定义温度计View

自定义一个View,实现温度计的功能
看完鸿洋大大的博客其中一篇关于 自定义view的文章http://blog.csdn.net/lmj623565791/article/details/24252901,受益良多决定自己一试,并记录下自己的心得。关于编写自定义View的步骤,请大家阅读鸿洋大大的文章,在这里我就不再累述。

一、我们需要自定义温度计的属性,比如将温度计放入布局之后温度计和内包含液体的颜色,温度计的高低等等。在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="liquid_color" format="color"/>
    <attr name="crust_color" format="color"/>
    <attr name="crust_width" format="dimension"/>
    <attr name="crust_height" format="dimension"/>
    <attr name="init_temperature" format="dimension"/>

    <declare-styleable name="MyThermometer">
        <attr name="liquid_color"/>
        <attr name="crust_color"/>
        <attr name="crust_width"/>
        <attr name="crust_height"/>
        <attr name="init_temperature"/>
    </declare-styleable>
</resources>

liquid_color : 温度计里液体的颜色
crust_color : 温度计外壳的颜色
crust_width : 温度计外壳的宽度
crust_height : 温度计外壳的高度
init_temperature : 温度计的初始温度

二、然后我们新建一个类继承View,用以实现我们的温度计。自定义组件重点是实现View类的onDraw()和onMeasure()方法,前者用于绘制组件的外观,后者用与控制组件本身的大小,这里我的组件不需太多要求,就让他全屏覆盖,所以我在放置组件时把大小都设置成了match_parent,没有往onMeasure()填充代码。
package com.thermometer.curio.thermometer;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

/**
 * Created by Curio on 2016/8/20.
 */
public class MyThermometer extends View {

    private int mCrustColor;
    private int mLiquidColor;
    private float mCrustWidth;
    private float mCrustHeight;
    private float mInitTemperature;

    /**
     * 定义温度计感温泡的位置
     */

    float circleX;
    float circleY;
    //创建画笔
    Paint p;

    Paint lp;
    public MyThermometer(Context context){
        this(context,null);
    }

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

    /**
     * 获取自定义属性
     * @param context
     * @param attrs
     * @param defStyle
     */
    public MyThermometer(Context context,AttributeSet attrs,int defStyle){
        super(context,attrs,defStyle);

        //获取自定义属性
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyThermometer, defStyle, 0);
        int n = typedArray.getIndexCount();
        for(int i = 0; i < n ; i++){
            int attr = typedArray.getIndex(i);

            switch(attr){
                //设置默认颜色为蓝色
                case R.styleable.MyThermometer_liquid_color : mLiquidColor = typedArray.getColor(attr, Color.BLUE) ;break;
                //设置默认颜色为黑色
                case R.styleable.MyThermometer_crust_color : mCrustColor = typedArray.getColor(attr,Color.BLACK);break;
                //设置温度计默认宽
                case R.styleable.MyThermometer_crust_width : mCrustWidth =typedArray.getDimensionPixelOffset(attr,
                        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics())) ;break;
                //设置温度计默认高
                case R.styleable.MyThermometer_crust_height : mCrustHeight = typedArray.getDimensionPixelOffset(attr,
                        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, getResources().getDisplayMetrics()));break;
                //设置温度计默认温度
                case R.styleable.MyThermometer_init_temperature : mInitTemperature = typedArray.getDimensionPixelOffset(attr,
                        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));break;
            }
        }
        typedArray.recycle();
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }

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




        /**
         * 先画温度计外壳
         */
        p = new Paint();
        p.setStyle(Paint.Style.STROKE);
        p.setColor(mCrustColor);
       // p.setColor(Color.BLUE);
        p.setAntiAlias(true);
        p.setStrokeWidth(5);

        //温度计的位置
        circleX = canvas.getWidth()/2;
        circleY = canvas.getHeight()-canvas.getHeight()/4;
        float mRadius = mCrustWidth/2;
        canvas.drawCircle(circleX, circleY, mRadius,p);

//        p.setColor(Color.YELLOW);
//        canvas.drawRect(0, 0, circleX, circleY, p);

        canvas.drawRect(circleX - mRadius * 0.5f, circleY - mRadius * 0.86f - mCrustHeight, circleX + mRadius * 0.5f, circleY - mRadius ,p);

        /**
         * 画温度计里的液体
         */
        lp = new Paint();

        lp.setStyle(Paint.Style.FILL);
        lp.setColor(mLiquidColor);
        lp.setAntiAlias(true);

        float mLRadius = mRadius-15;
        canvas.drawCircle(circleX, circleY, mLRadius, lp);
        //canvas.drawRect(circleX - mLRadius * 0.5f, circleY - mLRadius * 0.86f - 400, circleX + mLRadius * 0.5f, circleY - mLRadius *0.86f+0,lp);
        lp.setStrokeWidth(mLRadius);
        canvas.drawLine(circleX, circleY, circleX, circleY-100-mInitTemperature*10,lp);
    }

    public void setTemperature(float mTemperature){


        mInitTemperature = mTemperature;
        postInvalidate();

    }
}

三、这样之后我们可以在布局文件中调用此组件了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background2"
    tools:context="com.thermometer.curio.thermometer.MainActivity">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:layout_width="50dp"
            android:layout_height="30dp"
            android:id="@+id/input"
            android:lines="1"
            android:maxLength="2"
            android:inputType="number"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/post"
            android:text="℃更新温度"/>
    </LinearLayout>

   <com.thermometer.curio.thermometer.MyThermometer
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/temperature"
       custom:liquid_color="@color/white"
       custom:crust_color="@color/white"
       custom:crust_width="50dp"
       custom:crust_height="400dp"
       custom:init_temperature="0dp"/>

</RelativeLayout>

“一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package”


这是鸿洋在引用组件时写下的,但是自己写的时候发现这样在屏幕上绘制的组件显示不出来,屏幕一片空白。
后来发现这里要修改一下,android的自定义控件现在已经不需要写包名了,要写成res-auto。于是该改成这样
xmlns:custom="http://schemas.android.com/apk/res-auto"



四、我的MainActivity也贴在这里吧,供参考
package com.thermometer.curio.thermometer;

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);



        //去掉窗口标题
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        //全屏显示
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);

        final EditText mInput =(EditText)findViewById(R.id.input);
        final Button mPost = (Button)findViewById(R.id.post);
        final MyThermometer myThermometer =(MyThermometer)findViewById(R.id.temperature);

        mPost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View source) {
                if(mInput != null ){
                    String f = mInput.getText().toString();
                    if(!f.equals("")){
                        myThermometer.setTemperature(Float.parseFloat(f));
                    }

                } else{
                    myThermometer.setTemperature(1f);
                }
            }
        });

    }
}
代码上传至远程仓库,欢迎互相学习交流,提出修改建议,最终版本在mater分支和curiousx分支上,请不要下载master分支:https://git.coding.net/CuriousXeon/MyThermometerView.git



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值