自定义view基础入门

1.res/values/下新建attrs文件,声明自定义控件需用到的属性变量

<declare-styleable name="LabelView">
        <attr name="text" format="string"></attr>
        <attr name="textcolor" format="color"></attr>
        <attr name="textsize" format="dimension"></attr>
    </declare-styleable>

2.新建自定义类继承View类,实现构造方法。注意:必须实现第二个构造方法,否则会出现构造函数不被调用报空指针异常

public class Labview extends View {
    private Paint mTextPaint;
    private String mText;
    private int mAscent;
    private float size;
    private Rect rect;
    public Labview(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    @SuppressLint("Recycle")
    public Labview(Context context, AttributeSet attrs) {
        super(context, attrs,0);
        // TODO Auto-generated constructor stub
        TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.LabelView);//获取声明的属性变量
        mText =array.getString(R.styleable.LabelView_text);//获取文字内容
        mAscent=array.getColor(R.styleable.LabelView_textcolor,android.R.color.white);//获取文字颜色
        size=array.getDimensionPixelSize(R.styleable.LabelView_textsize,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));//获取文字大小
        System.out.println("mText  "+mText+"  mAscent  "+mAscent+"  size  "+size);
        mTextPaint=new Paint();//新建绘图类
        mTextPaint.setTextSize(size);//设置绘图类的文字大小
        rect=new Rect();
        mTextPaint.getTextBounds(mText, 0, mText.length(), rect);
    }
    @SuppressLint("Recycle")
    public Labview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub

    }
    @SuppressLint("DrawAllocation") @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        mTextPaint.setColor(Color.BLUE);  //先画View的背景,这个地方若后面设置其他颜色会和前一个颜色混合
        canvas.drawRect(0, 0,getMeasuredWidth() ,getMeasuredHeight(), mTextPaint);  //在画布上绘制背景颜色的大小
        mTextPaint.setColor(mAscent);  //绘制文本颜色
        canvas.drawText(mText, getMeasuredWidth()/2-rect.width()/4+getPaddingLeft()/6, getMeasuredHeight()/2+rect.height()/2, mTextPaint);  //绘制文本的位置
        this. setOnClickListener(new OnClickListener() {//设置监听
            
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                mText=randomText();
                postInvalidate();//点击后进行控件重绘
            }
        }) ;
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//设置控件的宽高
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
        int width;  
        int height ;  
        if (widthMode == MeasureSpec.EXACTLY)  
        {  
            width = widthSize;  
        } else  
        {  
            mTextPaint.setTextSize(size);  
            float textWidth = rect.width();  
            int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());  
            width = desired;  
        }  

        if (heightMode == MeasureSpec.EXACTLY)  
        {  
            height = heightSize;  
        } else  
        {  
            mTextPaint.setTextSize(size);  
            float textHeight = rect.height();  
            int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());  
            height = desired;  
        }  
        setMeasuredDimension(width, height);  
    }
    private String randomText()  
    {  
        Random random = new Random();  
        Set<Integer> set = new HashSet<Integer>();  
        while (set.size() < 4)  
        {  
            int randomInt = random.nextInt(10);  
            set.add(randomInt);  
        }  
        StringBuffer sb = new StringBuffer();  
        for (Integer i : set)  
        {  
            sb.append("" + i);  
        }  
 
        return sb.toString();  
    }  
}


### DBSCAN算法概述 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的空间聚类算法,可以发现任意形状的,并能有效地识别噪声点。该算法不需预先指定的数量,而是依据数据本身的分布情况自动确定。 #### 密度可达与密度相连的概念 在DBSCAN中定义了几个核心概念用于描述数据之间的关系: - **Epsilon (ε)**:表示邻域半径; - **MinPts**:指最小数量的数据点数;如果某个点在其给定的距离范围内至少包含`MinPts`个邻居,则认为它是核心对象。 当两个点都属于同一个核心对象的邻域时,它们被认为是“直接密度可达”的。而所谓“密度可达”,是指存在一系列由核心对象组成的路径连接两点。“密度相连”则意味着对于一对点A和B来说,即使两者不是直接相邻或者通过其他非核心点间接关联起来,只要能找到一条经过若干个核心点构成的道路使得这两者之间相互连通即可[^2]。 #### 算法实现流程 以下是简化版的伪代码展示如何利用上述原则构建DBSCAN模型: ```python def dbscan(X, eps, min_samples): clusters = [UNCLASSIFIED] * n_samples # 初始化所有样本标签为未分类 cluster_id = 0 # 当前分配给新的最大ID号 for P in range(n_samples): # 遍历每一个样本P if not visited[P]: performExpandCluster(P, X, clusters, cluster_id, eps, min_samples) return clusters # 返回最终得到的所有样本所属类别列表 def expand_cluster(P, neighbors, C, ... ): add_point_to_cluster(C, P) # 将当前考察的对象加入到正在形成的C当中去 while there are unprocessed points Q within epsilon neighborhood N: process_next_neighbor(Q,... ) # 对于N内的下一个待处理元素Q执行如下操作... if Q is a core point and has not been processed yet: append all its reachable points into the queue to be further explored. ``` 此过程涉及到遍历整个输入空间X中的各个位置作为起点尝试扩展新的群组直到不再有符合条件的新成员为止。每当成功创建了一个完整的集合之后就增加计数值并继续寻找剩余部分可能存在的其它独立子集[^1]。 #### 应用实例 由于具备无需事先知道具体要分成多少份的优势特性再加上良好的抗噪性能让DBSCAN成为众多领域内备受青睐的选择方案之一。例如,在地理信息系统(GIS),可以通过设定合理的距离阈值来检测城市交通流量模式下的热点区域;又或者是生物信息学方面用来研究基因表达谱型式的相似性分组等问题上都有出色表现[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值