ym——Android从零开始(21)(自定义控件)(新)

来源:互联网 发布:iphone离线看书软件 编辑:程序博客网 时间:2024/05/16 08:06

转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持!


前言

在开发中,很多UI设计出来的样式我们原生控件无法满足自身的要求,所以我们就需要自定义一个控件,接下来我们来学习一下如何自定义一个控件吧。

自定义控件

自定义控件基本步骤

继承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, bitmapWidth, bitmapHeight+10*i),                    paint);        }                for(int i =reverseIndex;i!=musicMax;i++){            canvas.drawBitmap(                    bitmap,                    null,                    new Rect(0, 10*i, bitmapWidth, bitmapHeight+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(w, h);    }    //当布局被加载完成的时候,会调用一个方法    @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()控件重绘

1 0