自定义View

来源:互联网 发布:淘宝刷单一单的价格 编辑:程序博客网 时间:2024/06/06 16:33
自定义View之前要掌握的东西
一、Android绘图三大API1.Canvas类
(1)功能:Canvas代表了"依附"于指定View的画布,通过Canvas类的成员方法能够实现绘制各种图形。绘制一个图形由四部分组成:Bitmap、Canvas、Path/Rect/text等、Paint,其中Bitmap为绘制图形存放的像素位图,Canvas用于提供绘制图像方法、Paint为画笔、Path/Rect/text等分别为绘制图形的(轨迹/矩形/文本)
(2)构造方法Canvas() :构造空的canvas对象Canvas(Bitmap bitmap) :构造一个Canvas对象,并指定其bitmap
(3)常用方法
booleanclipRegion(Region region):剪切指定区域voiddrawBitmap(Bitmap bitmap, float left, float top, Paint paint):在指定点(x,y)使用指定的画笔paint绘制位图voiddrawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint):在指定点(x,y)绘制从源位图中"挖取"的一块voiddrawCircle(float cx, float cy, float radius, Paint paint):绘制原点为(cx,cy),半径为radius的圆voiddrawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制一条起点为(startX,startY),终点为(stopX,stopY)直线voiddrawLines(float[] pts, int offset, int count, Paint paint):绘制多条直线,其中pts为一个浮点型数组提供绘制一条直接所需的数据(4个/条),count为绘制直线的条数voiddrawOval(RectF oval, Paint paint):绘制一个椭圆,oval为绘制椭圆的矩形边界voiddrawPath(Path path, Paint paint):沿着路径path绘制图形voiddrawPoint(float x, float y, Paint paint):绘制一个点(x,y)voiddrawPoints(float[] pts, int offset, int count, Paint paint):绘制pts数组中的多个点(2个值/点)voiddrawRect(float left, float top, float right, float bottom, Paint paint):绘制一个矩形,其参数为距离屏幕边界的距离(边界为0)voiddrawRoundRect(RectF rect, float rx, float ry, Paint paint):使用指定的画笔绘制圆角矩形,其中rect为矩形边界、rx/ry分别为以矩形顶点为(0,0)相对位置圆的x半径、y半径voiddrawText(String text, float x, float y, Paint paint):以(x,y)为原点,使用指定画笔绘制文本voiddrawTextOnPath(String text, Path path, float x, float y, Paint paint):以(x,y)为原点,使用指定的画笔沿着指定路径绘制文本intgetHeight():返回当前图层的高度intgetWidth():返回当前绘图层的宽度voidrotate(float degrees):对Canvas执行旋转变换;voidsetBitmap(Bitmap bitmap):指定Canvas(画布)的位图Bitmapvoidtranslate(float dx, float dy):相对于当前位置移动Canvas。向右移动dx距离(dx为负数即向左移动);向下移动dy距离(dy为负数即向上移动)voidskew(float sx,float sy):对Canvas执行倾斜变换

2.Paint类


(1)功能:Paint代表了Canvas上的画笔,Paint类主要用于设置绘制风格,包括画笔的颜色、画笔笔触粗细、填充风格等。
(2)构造方法Paint() :使用默认设置构造一个Paint对象Paint(int flags) :使用指定flags构造一个Paint对象Paint(Paint paint) :使用已有画笔的设置构造一个新的Paint对象
(3)常用方法
voidreset():恢复画笔到默认配置voidsetARGB(int a, int r, int g, int b):设置画笔透明度和颜色,其参数分别代表透明度、红色、绿色、蓝色voidsetAlpha(int a):设置画笔的透明度voidsetAntiAlias(boolean aa):设置是否抗锯齿voidsetColor(int color):设置画笔的颜色voidsetFlags(int flags):设置画笔的flags(HINTING_OFF、HINTING_ON等)voidsetHinting(int mode):设置画笔的提示模式PathEffectsetPathEffect(PathEffect effect):设置绘制路径时的路径效果(ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect)RasterizersetRasterizer(Rasterizer rasterizer)ShadersetShader(Shader shader):设置画笔的填充效果(BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient)voidsetShadowLayer(float radius, float dx, float dy, int color):设置阴影效果voidsetStrokeJoin(Paint.Join join):设置画笔转弯处的连接风格(BEVEL-直线、MITER -锐角、ROUND-圆弧 )voidsetStrokeWidth(float width):设置画笔宽度voidsetStyle(Paint.Style style):设置Paint的填充风格(FILL-、FILL_AND_STROKE、STROKE )voidsetTextAlign(Paint.Align align):设置绘制文本时的文字对齐方式(CENTER -居中、LEFT-靠左、RIGHT -靠右:以(x,y)为中心)voidsetTextSize(float textSize):设置绘制文本的文字大小3.Path类
(1)功能:Android提供的Path类预先在View上将N个点连成一条"路径",然后调用Canvas的drawPath(path,paint)方法即可沿着路径绘制图形。另外,Android还提供了PathEffect来定义绘制路径图形效果,其包含ComposePathEffect、CornerPathEffect、DashPathEffect、DiscretePathEffect、PathDashPathEffect、SumPathEffect六种效果
(2)构造方法Path():构造一个Path对象Path(Path src) :从另一个Path对象构造一个新的Path对象
(3)常用方法
booleanisEmpty():判定Path对象是否为空(即不包含直线或曲线),如果为空返回truevoidlineTo(float x, float y):增加一条从上一点到当前点(x,y)的直线voidmoveTo(float x, float y):设置下一个轮廓的开始点(x,y)voidrLineTo(float dx, float dy):以坐标为参照增加一条从上一点到当前点(x,y)的直线voidrMoveTo(float dx, float dy):以坐标为参照设置下一个轮廓的开始点(x,y)voidreset():删除Path对象的所有直线和曲线voidset(Path src):将当前Path对象的内容替换为对象src所包含的内容voidsetFillType(Path.FillType ft):设置路径的填充类型voidsetLastPoint(float dx, float dy):设置路径的最后一个点的坐标为(x,y)voidtransform(Matrix matrix):通过matrix转换该路径中的点void 
close() :释放资源


1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure
4、重写onDraw

1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
format是值该属性的取值类型:
      reference    :     资源id
      color           :     颜色值
      boolean      :     布尔值
     dimension    :       尺寸值
     float             :     浮点值
     integer         :     整形值
     string           :     字符串
     fraction        :     百分数
     enum           :     枚举值
     flag              :     位或运算

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--圆-->
    <attr name="rotateBack" format="color"/>
    <declare-styleable name="RotateView">
        <attr name="rotateBack" />
    </declare-styleable>
</resources>


//这是是获取值的
public RotateView(Context contextAttributeSet attrs, int defStyleAttr) {
    super(contextattrsdefStyleAttr);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrsR.styleable.RotateView,defStyleAttr,0);
    int n  = a.getIndexCount();
    for (int i = i < n i++ )
    {
     int attr = a.getIndex(i);
        switch (attr){
            case R.styleable.RotateView_rotateBack:
                rotateBack = a.getColor(attr,Color.BLUE);
                Log.d(TAG ,"颜色值---------->"+rotateBack);
                break;
        }
    }
    a.recycle();
    init();
}

初始PaInt
 /**
     * 初始化
     */
    public void init(){
        mPaint new Paint();
        //样式填充分3种  Paint.Style.FILL    :填充内部 Paint.Style.FILL_AND_STROKE  :填充内部和描边 Paint.Style.STROKE  :仅描边
        mPaint.setStyle(Paint.Style.FILL);
        //颜色
       mPaint.setColor(rotateBack);
        //锯齿功能
        mPaint.setAntiAlias(true);
        //画笔宽度
        mPaint.setStrokeWidth(4);
        //设置阴影
//        mPaint.setShadowLayer(160,305,305,Color.GREEN);
        mWidth 200;
        mHigth 200;
            rotate(true);
    }


mPaint.setStyle(Paint.Style.FILL);
Paint.Style.FILL    :填充内部
Paint.Style.FILL_AND_STROKE  :填充内部和描边
Paint.Style.STROKE  :仅描边


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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:gravity="center"
    android:layout_height="match_parent"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:weightSum="1">

    <com.example.jiangtao.testevent.custom_view.CustomTitleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:titleText = "2342"
        android:layout_gravity="center"
        android:id="@+id/custom_title_view"
        android:padding="20dp"
        custom:mTitleTextColor="#000000"
        android:layout_centerInParent="true"
        custom:titleTextSize="50sp"
         />
</LinearLayout>


系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。

所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:


重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpecheightMeasureSpec);
    // 重写onMeasure的目的是处理warp_content模式
    // 获取宽度的模式
    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    // 获取高度的模式
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    // 获取宽度的规格
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    // 获取高度的规格
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

    // 如果宽高的模式都是warp_content,则使用默认的宽高值
    if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(mWidthmHigth);

    }
    // 如果只有宽度模式是warp_content,则设置宽度为默认值,高度为测量出的值
    else if (widthSpecMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(mWidthheightSpecSize);
    }
    // 如果只有高度模式是warp_content,则设置高度为默认值,宽度为测量出的值
    else if (heightSpecMode == MeasureSpec.AT_MOST) {
        setMeasuredDimension(widthSpecSizemHigth);
    }


}

从写onDraw()

 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();
        int width = getWidth() - paddingLeft - paddingRight;
        int height = getHeight() - paddingBottom - paddingTop;
        mPaint.setColor(rotateBack);
        //画布设置颜色
//       canvas.drawColor(Color.RED);

        //画圆(第一个参数是x点、 第二个是y点、  第三个半径  )
        radius = Math.min(width,height)/2;
        canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,radius,mPaint);

        //画线startX:起始端点的X坐标。startY:起始端点的Y坐标。stopX:终止端点的X坐标。stopY:终止端点的Y坐标
//        canvas.drawLine(0, 0, 100, 100,mPaint);

        //画多条直线 前两个表示的是直线起点的横纵坐标,后两个表示的是直线终点的横纵坐标。(两两为一个点)
//      float []pts={10,10,100,100,200,200,400,400};
//      canvas.drawLines(pts,mPaint);


        // 绘制圆角矩形
//        RectF re1 = new RectF(30,30, 200, 200);
//        canvas.drawRoundRect(re1, 30,30, mPaint);

        // 绘制椭圆
//        RectF re11 = new RectF(30,30,300, 200);
//        canvas.drawOval(re11, mPaint);
        //定义一个Path对象,封闭成一个三角形并根据Path对象绘制
//         Path path1 = new Path();
//         path1.moveTo(10, 340);
//         path1.lineTo(70, 340);
//         path1.lineTo(40, 290);
//         path1.close();
//         canvas.drawPath(path1, mPaint);

        // 根据Path绘制五角形
//         Path path2 = new Path();
//         path2.moveTo(26, 360);
//         path2.lineTo(54, 360);
//         path2.lineTo(70, 392);
//         path2.lineTo(40, 420);
//         path2.lineTo(10, 392);
//         path2.close();
//         canvas.drawPath(path2, mPaint);

        //c.绘制正方形
//        canvas.drawRect(170,80,230,140,mPaint);


    }


滚动
/**
 * 根据标签判断滚动
 * @param flag
 */
public void rotate(boolean flag){
    if (flag==true){
        RotateAnimation ra = new RotateAnimation(0360,
                Animation.RELATIVE_TO_SELF0.5F,
                Animation.RELATIVE_TO_SELF0.5F);
        ra.setDuration(1000);
        ra.setRepeatCount(-1);
        this.startAnimation(ra);

    }
}


资料来源于网络希望对你有帮助,菜鸟一枚正在起飞中~~~~~~~~~



0 0
原创粉丝点击