栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Android自定义控件(UI,点击事件)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android自定义控件(UI,点击事件)

前言

总的来说自定义控件可以理解为重写创造并绘制一个控件,所以就要涉及到它的大小,位置,以及它的其他样式。在此博客中我只针对继承自View的自定义控件

一.测量
    public final void measure(int widthMeasureSpec, int heightMeasureSpec)  
    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  

measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果,measure,setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。即在重写的onMeasure()方法的最后setMeasuredDimension()为控件设置大小

关于MeasureSpec:

(1) UPSPECIFIED :未指定模式,父容器对于子容器没有任何限制,子容器想要多大就多大,通常在绘制自定义View时才会用

(2) EXACTLY:精确值模式,父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间,当控件的layout_width和layout_height属性指定为具体数值或match_parent时为该模式。

(3) AT_MOST:最大值模式,子容器可以是声明大小内的任意大小,当空间的宽高设置为wrap_content时为该模式
 

二.布局
    public void layout(int l, int t, int r, int b)
    protected boolean setFrame(int left, int top, int right, int bottom)
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)

layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用
 

三.绘制

3.)绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。

    public void draw(Canvas canvas)
    protected void onDraw(Canvas canvas)

通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。

————————————————
版权声明:本文为CSDN博主「中流击水浪遏飞舟」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yuanheng19930119/article/details/88055225

代码实现

自定义控件

package com.example.coustomapplication;


import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;

import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

public class SimpleView extends View {

    private final static String TAG = SimpleView.class.getSimpleName();
    //画笔
    private Paint mPaint;
    private RectF oval;
    //事件处理
    private EventHandle mEventHandle;
    //鼠标按下位置
    private int startX,startY;
    //按下鼠标时控件的位置
    private int startLeft,startTop;
    //状态栏高度
    int statusHeight = 0;
    //背景颜色
    int backgroundColor=Color.GRAY;
    int progressColor=Color.RED;
    int textColor=Color.WHITE;
    int textSize=30;
    int circleRadius=2048;
    int progress=120;//进度



    //定义一个接口对象listerner
    private OnItemSelectListener listener;
    //获得接口对象的方法。
    public void setOnItemSelectListener(OnItemSelectListener listener) {
        this.listener = listener;
    }
    //定义一个接口
    public interface  OnItemSelectListener{
        public void onItemSelect();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_DOWN:
                float x=event.getX();
                float y = event.getY();
                //当屏幕被点击后,将参数传入。
                if(listener!=null){
                    listener.onItemSelect();
                }
                invalidate();
                return true;

            case MotionEvent.ACTION_UP:

                invalidate();
                return true;
        }
        return super.onTouchEvent(event);
    }


    public SimpleView(Context context) {
        super(context);
        init();
    }

    public SimpleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initParameter(context,attrs);
        init();
    }

    public SimpleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initParameter(context,attrs);
        init();
    }

    private void init(){
        mPaint = new Paint();
        //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(textSize);
        oval=new RectF();
        mEventHandle=null;
        startY=startX=0;

        int resourceId = this.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusHeight = this.getResources().getDimensionPixelSize(resourceId);
        }

    }
    private void initParameter(Context context, AttributeSet attrs)
    {

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SimpleView);
        if (typedArray != null) {
            backgroundColor = typedArray.getColor(R.styleable.SimpleView_percent_background_color, Color.GRAY);
            progressColor = typedArray.getColor(R.styleable.SimpleView_percent_progress_color, Color.RED);
            circleRadius = (int)typedArray.getDimension(R.styleable.SimpleView_percent_circle_radius, 2048);
            progress = typedArray.getInt(R.styleable.SimpleView_percent_circle_progress, 120);
            textColor=typedArray.getColor(R.styleable.SimpleView_percent_text_color,Color.WHITE);
            textSize=(int)typedArray.getDimension(R.styleable.SimpleView_percent_text_size,30);
            if(progress>360)
                progress=360;
            if(progress<0)
                progress=0;
            typedArray.recycle();
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        Log.e(TAG, "onMeasure--widthMode-->" + widthMode);
        switch (widthMode) {
            case MeasureSpec.EXACTLY:
                //精确值模式,当控件的layout_width和layout_height属性指定为具体数值或match_parent时。
                break;
            case MeasureSpec.AT_MOST:
                //最大值模式,当空间的宽高设置为wrap_content时。
                break;
            case MeasureSpec.UNSPECIFIED:
                //未指定模式,View想多大就多大,通常在绘制自定义View时才会用。
                break;
        }
        //取最小边为控件的宽高的最小值
        int minWidth=widthSize>heightSize?heightSize:widthSize;
        setMeasuredDimension(minWidth,minWidth);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        
        mPaint.setColor(backgroundColor);
        // FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        int with = getWidth();
        int height = getHeight();
        Log.e(TAG, "onDraw---->" + with + "*" + height);

        float radius = with / 2-5;

        //如果设置的半径比较合理,就去设置的半径
        if(circleRadius 

attrs文件


    
        
            
            
            
            
            
            
        
    

XML文件





主活动

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    private SimpleView simpleView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        simpleView = findViewById(R.id.sv_a);
        simpleView.setOnItemSelectListener(new SimpleView.OnItemSelectListener() {
            @Override
            public void onItemSelect() {
                Log.d("gaoqiang", "onItemSelect: ");
            }
        });
       
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1025571.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号