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

转载请注明本文出自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()控件重绘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值