美文网首页
自定义View简单使用

自定义View简单使用

作者: 清风兑酒 | 来源:发表于2019-05-04 19:04 被阅读0次
1.spinner_view.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="60dp" />

    <ImageView
        android:id="@+id/iv_arrow"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentRight="true"
        android:src="@drawable/down_arrow"/>

</RelativeLayout>
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;

import java.util.ArrayList;

public class SpinnerView extends RelativeLayout{
    private EditText et;
    private ImageView ivArrow;
    private ArrayList<String> mData;
    private ArrayAdapter<String> adapter;
    private PopupWindow popupWindow;

    public SpinnerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        View view = LayoutInflater.from(context).inflate(R.layout.spinner_view, null);
        addView(view);
        initData();
        initView(view);
    }

    private void initData() {
        mData = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            mData.add("秋裤:"+i);
        }
    }

    private void initView(View view) {
        et = view.findViewById(R.id.et);
        ivArrow = view.findViewById(R.id.iv_arrow);
        ivArrow.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                pop();
            }
        });
    }

    private void pop() {
        if (popupWindow==null){
            ListView listView = new ListView(getContext());

            adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_expandable_list_item_1, mData);
            listView.setAdapter(adapter);
            listView.setBackgroundResource(R.drawable.listview_background);
            popupWindow = new PopupWindow(listView, et.getWidth(), 700);
            popupWindow.setBackgroundDrawable(new ColorDrawable());
            popupWindow.setOutsideTouchable(true);

            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    popupWindow.dismiss();
                    et.setText(mData.get(position));
                    et.setSelection(mData.get(position).length());
                }
            });
        }

        popupWindow.showAsDropDown(et);
    }

}
1.png
2
package com.example.lenovo.day11;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View{

    private final int mStartX;
    private final int mStartY;
    private final int mEndX;
    private final int mEndY;
    private final Paint paint;
    private final Paint mCirclePanit;
    private final Bitmap mBitmap;
    private final Path mPath;
    private final RectF mRectF;

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        // 1、画直线
        mStartX = 50;
        mStartY = 50;
        mEndX = 200;
        mEndY = 200;
        paint = new Paint();
        paint.setColor(Color.parseColor("#FFFFFF"));
        paint.setStrokeWidth(5);
        paint.setAntiAlias(true);

        // 3、画空心圆
        mCirclePanit = new Paint();
        mCirclePanit.setColor(Color.parseColor("#FFFFFF"));
        mCirclePanit.setStrokeWidth(5);
        mCirclePanit.setAntiAlias(true);
        mCirclePanit.setStyle(Paint.Style.STROKE);

        // 4、画图片
        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.c);

        // 5、画三角形(多边形)
        int x1 = 50;
        int y1 = 50;
        int x2 = 700;
        int y2 =80;
        int x3 = 360;
        int y3 = 650;

        mPath = new Path();
        mPath.moveTo(x1,y1);
        mPath.lineTo(x2,y2);
        mPath.lineTo(x3,y3);
        mPath.lineTo(x1,y1);

        // 7、画扇形
        mRectF = new RectF(50, 50, 720, 720);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 6、裁剪 (先裁切再画别的东西,比如图片)
//        canvas.clipPath(mPath);

        // 1、画直线
//        canvas.drawLine(mStartX,mStartY,mEndX,mEndY,paint);

        // 2、画圆
//        canvas.drawCircle(200,200,50,paint);

        // 3、画空心圆
//        canvas.drawCircle(200,200,50,mCirclePanit);

        // 4、画图片
//        canvas.drawBitmap(mBitmap,50,50,mCirclePanit);

        // 5、画三角形(多边形)
//        canvas.drawPath(mPath,mCirclePanit);

        // 7、画扇形
        //startAngle 其实角度,水平向右0度
        //sweepAngle 夹角
        //useCenter true,实心的扇形
        canvas.drawArc(mRectF,0,120,false,mCirclePanit);
    }
}
3.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class BallView extends View{

    private final Bitmap bitmap;
    private final Paint paint;
    private float mLeft;
    private float mTop;

    public BallView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ball);
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap,mLeft,mTop,paint);
    }

    /**
     * 触摸事件,在这里获取手指触摸的位置,然后小球重新绘制到对应位置就可以了
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mLeft = event.getX();
        mTop = event.getY();
        //重新绘制
        invalidate();
        //滑动的时候这个方法消费触摸事件
        return true;
    }
}
3.png
4、圆形进度条
4.png
4.1、在res文件夹下的values文件中创建attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--declare-styleable name="CircleProgress" 加了name之后,标签中的属性就可以直接给CircleProgress-->
    <declare-styleable name="CircleProgress">
        <!--自定义的属性-->
        <!-- format 属性值的类型 color 颜色 reference 关联类型-->
        <attr name="ring_color" format="reference|color"/>
        <attr name="ring_width" format="dimension"/>
        <!--起始角度-->
        <attr name="startAngle" format="float"/>
        <attr name="sweepAngle" format="float"/>
        <attr name="circle_color" format="reference|color"/>

        <!--使用系统的属性-->
        <attr name="android:textColor"/>
        <attr name="android:text"/>
        <attr name="android:textSize"/>
    </declare-styleable>
</resources>
4.2、在Activity对应的xml文件中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <com.example.circleprogressbar.CircleProgress
        app:ring_width="12dp"
        app:ring_color="@color/colorAccent"
        app:circle_color="@color/colorPrimary"
        app:startAngle="-90"
        app:sweepAngle="0"
        android:textColor="@color/colorAccent"
        android:text="0%"
        android:textSize ="20sp"
        android:id="@+id/cp"
        android:background="#cecece"
        android:layout_width="300dp"
        android:layout_height="300dp" />

    <Button
        android:id="@+id/btn"
        android:text="开始下载"
        android:layout_marginTop="30dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
4.3、创建一个CircleProgress类并继承View
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * @author
 *         Created by asus on 2019/4/15.
 *         a.自定义一个CustomView(extends View )类
           b.编写values/attrs.xml,在其中编写styleable和item等标签元素
           c.在布局文件中CustomView使用自定义的属性(注意namespace)
           导入自定义属性,以下两种方式都可(namespace)
           http://schemas.android.com/apk/res/包名
           http://schemas.android.com/apk/res-auto
           d.在CustomView的构造方法中通过TypedArray获取

           xmlns:app="http://schemas.android.com/apk/res-auto" 命名空间 xml name space
 */
public class CircleProgress extends View{
    private static final String TAG = "CircleProgress";
    private float mSweepAngle;
    private float mRingWidth;
    private int mRingColor;
    private float mStartAngle;
    private int mTextColor;
    private String mText;
    private float mTextSize;
    private RectF mRectF;
    private Paint mRingPaint;
    private int mCx;
    private int mCy;
    private int mRadius;
    private int mCircleColor;
    private Paint mCirclePaint;
    private Paint mTextPaint;
    private float mDy;
    public CircleProgress(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        //获取设置的属性
        int attributeCount = attrs.getAttributeCount();
        //开发有时候不用这种,因为关联类型的获取出来是资源id,一般TypedArray
       /* for (int i = 0; i < attributeCount; i++) {
            String attributeName = attrs.getAttributeName(i);
            String attributeValue = attrs.getAttributeValue(i);
            Log.d(TAG, "attributeName: "+attributeName+",value:"+attributeValue);
        }*/
        //TypedArray
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgress);
        if (ta != null) {
            mRingWidth = ta.getDimension(R.styleable.CircleProgress_ring_width, 20);
            mRingColor = ta.getColor(R.styleable.CircleProgress_ring_color, 0);
            mStartAngle = ta.getFloat(R.styleable.CircleProgress_startAngle, -90);
            mSweepAngle = ta.getFloat(R.styleable.CircleProgress_sweepAngle, 0);
            mTextColor = ta.getColor(R.styleable.CircleProgress_android_textColor, 0);
            mCircleColor = ta.getColor(R.styleable.CircleProgress_circle_color, 0);
            mText = ta.getString(R.styleable.CircleProgress_android_text);
            mTextSize = ta.getDimension(R.styleable.CircleProgress_android_textSize, 20);

            //#ffffff--->int
            Log.d(TAG, "textcolor: " + mRingColor);
            //释放资源
            ta.recycle();
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int max = Math.max(width, height);
        mCx = max/2;
        mCy = mCx;
        mRadius = max/4;
        //防止有人给弄成长方形的
        int widthHeigth = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);
        super.onMeasure(widthHeigth, widthHeigth);

        //环
        mRectF = new RectF(0.1f*max, 0.1f*max, 0.9f*max, 0.9f*max);
        mRingPaint = new Paint();
        mRingPaint.setColor(mRingColor);
        mRingPaint.setAntiAlias(true);
        mRingPaint.setStyle(Paint.Style.STROKE);
        mRingPaint.setStrokeWidth(mRingWidth);

        //内圆
        mCirclePaint = new Paint();
        mCirclePaint.setColor(mCircleColor);
        mCirclePaint.setAntiAlias(true);

        //文本
        mTextPaint = new Paint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        //水平居中
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        //垂直居中需要向下移动center线到baseline线的距离
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float textHeight = fontMetrics.descent - fontMetrics.ascent;
        mDy = textHeight / 2 - fontMetrics.descent;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //1.先画环
        canvas.drawArc(mRectF,mStartAngle,mSweepAngle,false,mRingPaint);
        //2.画内圆
        canvas.drawCircle(mCx,mCy,mRadius,mCirclePaint);
        //3.文本,文本不是从给定点的左上角开始写的,而是要对齐baseline,所以文本靠右上角
        //canvas.drawText(mText,mCx,mCy,mTextPaint);
        //canvas.drawText(mText,mCx,mCy+(center线到Baseline的距离),mTextPaint);
        canvas.drawText(mText,mCx,mCy+mDy,mTextPaint);
    }

    /**
     * 设置进度
     * @param progress 0--100
     */
    public void setProgress(int progress) {
        mText = progress+" %";
        mSweepAngle = progress * 360 * 1.0f/100;
        //重新绘制
        //invalidate();
        //非ui线程调用这个方法
        postInvalidate();
    }

    public float getmSweepAngle() {
        return mSweepAngle;
    }
}
4.4、在Acticity中
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private CircleProgress cp;
    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        cp = (CircleProgress) findViewById(R.id.cp);
        btn = (Button) findViewById(R.id.btn);

        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn:
                down();
                break;
        }
    }

    private void down() {
        if (cp.getmSweepAngle()==0){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <= 100; i++) {
                        try {
                            Thread.sleep(300);
                            cp.setProgress(i);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }else {
            Toast.makeText(this, "正在下载中,请稍后", Toast.LENGTH_SHORT).show();
        }
    }
}

相关文章

  • 自定义View简介

    自定义View简介 自定义View简介 简单理解,就是在系统自带的空间满足不了你的需求的时候,你就会使用自定义Vi...

  • 【Android】 自定义View那点事(二)

    回顾 上一节我们学会了使用Canvas和Paint实现自定义View的绘制,我们已经知道如何简单实现自定义View...

  • 通过圆形载入View了解自定义View

    这是自定义View的第一篇文章,通过制作简单的自定义View来了解自定义View的流程。自定义View是Andro...

  • 自定义View理论

    自定义View类型 1. 自定义View 在没有现成的View,需要自己实现的时候,就使用自定义View,一般继承...

  • 自定义View - 字母索引列表

    自定义view 布局 使用

  • 六大操作手势

    使用 touches 方法来监听 view 的触摸事件弊端: 必须得自定义 view, 在自定义的 View 当中...

  • iOS-自定义View的封装

    在开发过程中,自定义控件使用的频率非常高,接下来简单对自定义控件做个小结 View的封装 如果一个view内部的子...

  • 自定义View简单使用

    1.创建一个包:weight 2.创建一个类:ClicleView extends View 四个构...

  • 自定义View简单使用

    1 spinner_view.xml 2 3 4、圆形进度条 2、在Activity对应的xml文件中 3、创建一...

  • 自定义View简单使用

    1.spinner_view.xml 2 3. 4、圆形进度条 4.1、在res文件夹下的values文件中创建a...

网友评论

      本文标题:自定义View简单使用

      本文链接:https://www.haomeiwen.com/subject/jsjfoqtx.html