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

自定义View简单使用

作者: 沈溺_16e5 | 来源:发表于2019-04-15 20:39 被阅读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.gif
    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.gif
    4、圆形进度条
    圆形进度条.gif
    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>
    

    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>
    

    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、在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简单使用

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