学习android从零开始(20)(自定义控件)

来源:互联网 发布:剑灵捏脸数据女 编辑:程序博客网 时间:2024/06/06 00:27
自定义控件自定义控件基本步骤

继承View 重写 三个构造

public class MyView extends View {

       privatePaint mPaint;

       publicMyView(Context context, AttributeSet attrs, int defStyle) {

      }

       publicMyView(Context context, AttributeSet attrs) {

      }

       publicMyView(Context context) {

      }

这三个构造是自动匹配调用

重写onDraw

onDraw方法给我们提过canvas(画布) 我们自己要生成画笔(Paint)以及给画笔设置颜色和字体大小

@Override

    protected void onDraw(Canvas canvas) {

        // TODO Auto-generated method stub

        super.onDraw(canvas);

        Paint mPaint = new Paint();

        mPaint.setTextSize(dimension);

        mPaint.setColor(color);

        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);

         

        canvas.drawText("我被画出来了", 50, 100, mPaint);

    }

在布局xml里面我们只需要全类名使用即可

<com.cym.custom.MyView  // 全类名使用即可

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

         />

如果想要给自定义控件添加自定义属性

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

  xmlns:myView="http://schemas.android.com/apk/res/com.cym.custom"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    androidrientation="vertical" >

    <com.cym.custom.MyView

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        myView:color="@color/white"

        myView:fontsize="@dimen/fontsize"

         />

我们就要为自定义属性写xml

Attrs.xml

<?xmlversion="1.0"encoding="utf-8"?>

<resources>

<declare-styleablename="myView">  标识名

    <attrname="color"format="color"/>  制定名字及属性格式

    <attrname="fontsize"format="dimension"/> 制定名字及属性格式

    </declare-styleable>

</resources>

选择属性项

Colors.xml

<?xmlversion="1.0"encoding="utf-8"?>

<resources>

<colorname="white">#ffffffff</color> 制定相应属性内容

   

</resources>

Domenson.xml

<?xmlversion="1.0"encoding="utf-8"?>

<resources>

    <dimenname="fontsize">100dp</dimen> 制定相应属性内容

   

</resources>

获得自定义属性内容

public MyView(Context context, AttributeSet attrs) {

        super(context, attrs);

        mPaint = new Paint();

从属性布局文件拿到所有布局属性

        TypedArray array =context.obtainStyledAttributes(attrs, R.styleable.myView);

根据不同的属性资源ID拿取相应的值

float dimension =array.getDimension(R.styleable.myView_fontsize,10);

int color =array.getColor(R.styleable.myView_color,Color.RED);

        mPaint.setTextSize(dimension);

        mPaint.setColor(color);

        array.recycle();

    }

自定义音量条

public class MyView extends View{

    private Paint paint// 画笔

    private Context context// 上下文

    private AudioManager am// 音量管理器

    private int musicMax// 最大音量

    private Bitmap bitmap// 绿色图片

    private Bitmap bitmap1// 灰色图片

    //图片宽高

    private int bitmapWidth;

    private int bitmapHeight;

    // 控件宽高

    private int w;

    private int h;

    public MyView(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

        paint = new Paint();

        this.context = context;

        init();

        // TODO Auto-generated constructor stub

    }

    public MyView(Context context, AttributeSet attrs) {

        super(context, attrs);

        paint = new Paint();

        this.context = context;

        init();

        // TODO Auto-generated constructor stub

    }

    public MyView(Context context) {

        super(context);

        paint = new Paint();

        this.context = context;

        init();

        // TODO Auto-generated constructor stub

    }

    @Override

    protected void onDraw(Canvas canvas) {

        // TODO Auto-generated method stub

        super.onDraw(canvas);

        // 当前音量

        int index = am.getStreamVolume(AudioManager.STREAM_MUSIC);

        int reverseIndex = musicMax - index;

        //画灰色的格子

        for(int i = 0;i<reverseIndex;i++){

            canvas.drawBitmap(

                    bitmap1,

                    null,

                    new Rect(0, 10*i, bitmapWidthbitmapHeight+10*i),

                    paint);

        }

        

        for(int i =reverseIndex;i!=musicMax;i++){

            canvas.drawBitmap(

                    bitmap,

                    null,

                    new Rect(0, 10*i, bitmapWidthbitmapHeight+10*i),

                    paint);

        }

        

    }

    // 定义一个初始化方法

    private void init(){

        // 得到音量管理器

              am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

        // 得到最大音量

        musicMax = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.sound_line);

        bitmap1 = BitmapFactory.decodeResource(getResources(),R.drawable.sound_line1);

        bitmapWidth = bitmap.getWidth();

        bitmapHeight = bitmap.getHeight();

    }

    // 对要绘制的控件进行测量 调用两次

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        // TODO Auto-generated method stub

        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

         w = resolveSize(w, widthMeasureSpec);

         h = resolveSize(h, heightMeasureSpec);

         // 设置数据

         setMeasuredDimension(wh);

    }

    //当布局被加载完成的时候,会调用一个方法

    @Override

    protected void onFinishInflate() {

        // TODO Auto-generated method stub

        super.onFinishInflate();

        w = bitmapWidth;

        h = bitmapHeight * 15 + 5 * 14;

    }

    // 触摸事件

    @Override

    public boolean onTouchEvent(MotionEventevent) {

        // TODO Auto-generated method stub

        float y = event.getY();

        int index = (int)y/9;

         

        int contol_index = 15 -index;

   

        if(contol_index > -1&& contol_index <= 15){

            am.setStreamVolume(AudioManager.STREAM_MUSIC, contol_index, AudioManager.FLAG_PLAY_SOUND);

            // 控件重绘

            invalidate();

        }

        return true;

        

    }

}

课后问题

为什么要自定义控件?

因为系统提供的控件无法满足我们的需求,所以要使用自定义控件.

自定义控件的步骤

重写三个构造,重写onDraw(绘制)方法,如果要自定义属性的话,要写配置属性xml,属性选择项xml,使用时在布局文件里面声明引用,才可以使用自定义属性。

如果业务稍微复杂还重写到

onFinishInflate(布局加载后调用该方法)

onMeasure(对绘制控件进行测量)

以及频繁修改视图则会用到

Invalidate()控件重绘

0 0