Android自定义控件(1)--自定义View

Android实现自定义相机系列(1)—自定义view裁剪控件 目标 本系列文章主要记录自定义相机拍照系列,包括: 1、使用Android的Camera API自定义拍照模式,例如人脸拍照,OCR拍照等; 2、对拍完的照片进行裁剪; 3、自定义图片伸缩view,使用手势对图片进行放大缩小操作; 本人写博客也是为了自己学习和分享,也会参考网络上许多文章和开源项目,希望大家一块学习进步。这一篇文章主要介绍自定义裁剪view控件。 ... 阅读详情

Android自定义View

一、View绘制原理

View的绘制基本上由measure()、layout()、draw()三个函数完成。

1.1 测量onMeasure

测量过程中的相关方法主要有:

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()中计算view的宽高,并调用setMeasuredDimension()方法保存测量结果;measure()与setMeasuredDimension()为final方法,onMeasure()在子类中需要重写。

1.1.1 关于MeasureSpec

MeasureSpec是一个View的内部类,它封装了一个view的尺寸,在onMeasure()中可以根据MeasureSpec的值具体确定view的尺寸;MeasureSpec的值保存在一个int值中,其32位中的前两位表示 MODE ,后30位表示 size 。

  • MeasureSpec中的MODE
    共有三种:UNSPECIFIED、EXACTLY 和 AT_MOST;
    – UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大,一般为系统内部使用;
    – EXACTLY:精准模式,对应 match_parent ,父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间,根据MeasureSpec中size确定;
    – AT_MOST:最大模式,对应 wrap_content ,子容器可以是MeasureSpec中size值大小内的任意大小。

  • MeasureSpec的使用

      // 获取mode
      int specMode=MeasureSpec.getMode(measureSpec);
      // 获取size
      int specSize=MeasureSpec.getSize(measureSpec);
      //生成MeasureSpec
      int measureSpec1=MeasureSpec.makeMeasureSpec(size,mode);
    
  • 根据MODE确定子view的MeasureSpec

      public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
      int specMode = MeasureSpec.getMode(spec);
      int specSize = MeasureSpec.getSize(spec);
    
      int size = Math.max(0, specSize - padding);
    
      int resultSize = 0;
      int resultMode = 0;
    
      switch (specMode) {
      //当父View要求一个精确值时,为子View赋值
      case MeasureSpec.EXACTLY:
          //如果子view有自己的尺寸,则使用自己的尺寸
          if (childDimension >= 0) {
              resultSize = childDimension;
              resultMode = MeasureSpec.EXACTLY;
              //当子View是match_parent,将父View的大小赋值给子View
          } else if (childDimension == LayoutParams.MATCH_PARENT) {
              resultSize = size;
              resultMode = MeasureSpec.EXACTLY;
              //如果子View是wrap_content,设置子View的最大尺寸为父View
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {
              resultSize = size;
              resultMode = MeasureSpec.AT_MOST;
          }
          break;
    
      // 父布局给子View了一个最大界限
      case MeasureSpec.AT_MOST:
          if (childDimension >= 0) {
              //如果子view有自己的尺寸,则使用自己的尺寸
              resultSize = childDimension;
              resultMode = MeasureSpec.EXACTLY;
          } else if (childDimension == LayoutParams.MATCH_PARENT) {
              // 父View的尺寸为子View的最大尺寸
              resultSize = size;
              resultMode = MeasureSpec.AT_MOST;
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {
              //父View的尺寸为子View的最大尺寸
              resultSize = size;
              resultMode = MeasureSpec.AT_MOST;
          }
          break;
    
      // 父布局对子View没有做任何限制
      case MeasureSpec.UNSPECIFIED:
          if (childDimension >= 0) {
          //如果子view有自己的尺寸,则使用自己的尺寸
              resultSize = childDimension;
              resultMode = MeasureSpec.EXACTLY;
          } else if (childDimension == LayoutParams.MATCH_PARENT) {
              //因父布局没有对子View做出限制,当子View为MATCH_PARENT时则大小为0
              resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
              resultMode = MeasureSpec.UNSPECIFIED;
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {
              //因父布局没有对子View做出限制,当子View为WRAP_CONTENT时则大小为0
              resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
              resultMode = MeasureSpec.UNSPECIFIED;
          }
          break;
      }
    
      return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
      }
    

这段代码只为子view设置了MeasureSpec参数而并未确定子view的实际大小,实际大小仍需在onMeasure()中具体设置。

  • 子view的测量模式
    可以看出,子view的测量模式由自身LayoutParam和父view的MeasureSpec决定:
    – 父view测量模式为UNSPECIFIED:若子view有尺寸,则使用,否则为0;
    – EXACTLY:父布局为精准模式,有确定大小,若子view有大小则直接使用,否则不能超出父view的大小;
    – AT_MOST:父布局为最大模式,则子view若有大小则直接使用,没有大小则不得超出父view大小;
1.1.2 onMeasure()源码分析
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
            getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
  • setMeasuredDimension(int measuredWidth, int measuredHeight) :该方法用来设置View的宽高,在我们自定义View时也会经常用到;

  • getDefaultSize(int size, int measureSpec):该方法用来获取View默认的宽高,源码:

      public static int getDefaultSize(int size, int measureSpec) {
      	int result = size;
      	int specMode = MeasureSpec.getMode(measureSpec);
      	int specSize = MeasureSpec.getSize(measureSpec);
    
      	switch (specMode) {
      		case MeasureSpec.UNSPECIFIED:
          		result = size;
          		break;
      	case MeasureSpec.AT_MOST:
      	case MeasureSpec.EXACTLY:
          		result = specSize;
          	break;
      	}
      	return result;
      }
    
  • getSuggestedMinimumWidth():获取建议的尺寸,源码:

      protected int getSuggestedMinimumWidth() {
      	return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
      	// view无背景时默认大小为mMinWidth(通过android:minWidth设置,默认为0);有背景时默认大小为mMinWidth与背景的最小尺寸中的较大者。
    

    }

1.2 布局layout()

设置view在屏幕中的显示位置,对于View来说用于计算其位置参数,而对于ViewGroup则需计算自身以及子view的位置。
相关方法主要有:

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中才会使用。

1.2.1 layout()源码
//参数l、t、r、b为view边界相对父view的距离
public void layout(int l, int t, int r, int b) {
    if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
        onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
        mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
    }

    int oldL = mLeft;
    int oldT = mTop;
    int oldB = mBottom;
    int oldR = mRight;

    //这里通过setFrame或setOpticalFrame方法确定View在父容器当中的位置。
    boolean changed = isLayoutModeOptical(mParent) ?
            setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);

    //调用onLayout方法。onLayout方法是一个空实现,不同的布局会有不同的实现。
    if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
        onLayout(changed, l, t, r, b);

    }

}
  • layout()中已经通过setOpticalFrame()或setFrame()方法对view自身位置进行设置,所以onLayout()一般用于ViewGroup对子view的位置进行计算。

1.3 绘制draw()

主要用前两步得到的参数完成视图的最终绘制,绘制流程的入口为draw()方法,主要步骤如下:

  1. draw background if needed
  2. save canvas if needed
  3. draw content of the view
  4. draw child views
  5. draw edges 、shadow if needed
  6. draw decorator such as scrollbars

绘制流程的主要方法:

	public void draw(Canvas canvas)

	protected void onDraw(Canvas canvas)
1.3.1 draw()源码
public void draw(Canvas canvas) {
    int saveCount;
    // 1. 如果需要,绘制背景
    if (!dirtyOpaque) {
        drawBackground(canvas);
    }

    // 2. 有过有必要,保存当前canvas。
    final int viewFlags = mViewFlags;
  
    if (!verticalEdges && !horizontalEdges) {
        // 3. 绘制View的内容。
        if (!dirtyOpaque) onDraw(canvas);

        // 4. 绘制子View。
        dispatchDraw(canvas);

        drawAutofilledHighlight(canvas);

        // Overlay is part of the content and draws beneath Foreground
        if (mOverlay != null && !mOverlay.isEmpty()) {
            mOverlay.getOverlayView().dispatchDraw(canvas);
        }

        // 6. 绘制装饰,如滚动条等等。
        onDrawForeground(canvas);

        // we're done...
        return;
    }
}

/**
*  1.绘制View背景
*/
private void drawBackground(Canvas canvas) {
    //获取背景
    final Drawable background = mBackground;
    if (background == null) {
        return;
    }

    setBackgroundBounds();

    //获取便宜值scrollX和scrollY,如果scrollX和scrollY都不等于0,则会在平移后的canvas上面绘制背景。
    final int scrollX = mScrollX;
    final int scrollY = mScrollY;
    if ((scrollX | scrollY) == 0) {
        background.draw(canvas);
    } else {
        canvas.translate(scrollX, scrollY);
        background.draw(canvas);
        canvas.translate(-scrollX, -scrollY);
    }
}

/**
* 3.绘制View的内容,该方法是一个空的实现,在各个业务当中自行处理。
*/
protected void onDraw(Canvas canvas) {
}

/**
* 4. 绘制子View。该方法在View当中是一个空的实现,在各个业务当中自行处理。
*  在ViewGroup当中对dispatchDraw方法做了实现,主要是遍历子View,并调用子类的draw方法,一般我们不需要自己重写该方法。
*/
protected void dispatchDraw(Canvas canvas) {

}

自定义view时一般重写onDraw(),而继承自ViewGroup时不需要。

1.3.2 绘制坐标系

如下图所示,在安卓系统中,一屏幕左上角为原点,向左为x轴,向下为y轴。
Android系统坐标系
而对于控件View来说,其自身的坐标系及使用方法如下:
View坐标系

  • 获取view坐标
    可以使用如下方法获取view各边界到其父view的距离:
    getTop()、getLeft()、getBottom()、getRight();
  • 获取view尺寸:
    width=getRight()-getLeft()
    height=getBottom()-getTop()
    也可以直接使用view提供的getWidth()和getHeight()方法来获取;

二、自定义控件属性

对于安卓定义的系统控件,使用 android: 命名空间进行配置,而对于自定义控件的参数配置,则可以使用自定义属性。

<declare-styleable name="CustumView">
    <attr name="viewText" format="string"  />
</declare-styleable>

2.1 属性值的类型

  1. reference:参考某一资源id

– 属性定义:

<attr name = "background" format = "reference" />

– 属性使用:

<ImageView android:background = "@drawable/图片ID"/>
  1. dimension:尺寸值,< Button android:layout_width = “42dip”/>
  2. color:颜色值,< TextView android:textColor = “#00FF00” />
  3. boolean:布尔值,< Button android:focusable = “true”/>
  4. float:浮点值,< alpha android:fromAlpha = “1.0”/>
  5. integer:整型,< animated-rotate android:framesCount = “12”/>
  6. string:字符串,< TextView android:text = “我是文本”/>
  7. fraction:百分数,< rotate android:pivotX = “200%”/>
  8. enum:枚举;使用中只能用其中的一个,不可android:orientation = “horizontal|vertical";

– 属性定义

<attr name="orientation">
    <enum name="horizontal" value="0" />
    <enum name="vertical" value="1" />
</attr> 

– 属性使用

<LinearLayout  
	android:orientation = "vertical">
< /LinearLayout>
  1. flag:位或运算;使用时可以使用多个值;

– 定义

<attr name="gravity">
        <flag name="top" value="0x01" />
        <flag name="bottom" value="0x02" />
        <flag name="left" value="0x04" />
        <flag name="right" value="0x08" />
        <flag name="center_vertical" value="0x16" />
        ...
</attr>

– 使用

<TextView android:gravity="bottom|left"/>
  1. 混合类型:定义属性时可以指定多个类型;

–定义

<attr name = "background" format = "reference|color" />

– 使用

<ImageView android:background = "@drawable/图片ID" />
或者:
<ImageView android:background = "#00FF00" />

三、自定义View开发步骤

3.1 新建属性集文件并添加自定义属性

在资源文件夹的 values 目录创建attrs.xml文件,在其中添加属性集:

<declare-styleable name="Dock">
    <attr name="dockHeight" format="dimension"/>
    <attr name="dockBacgroundColor" format="color"/>
    <attr name="dockIconSize" format="dimension"/>
</declare-styleable>

3.2 创建自定义控件类集成View

创建控件类,其中一个参数的构造参数为通过new关键字新建时调用;修改构造函数使其相互调用;

public Dock(Context context) {
    this(context,null);
}

public Dock(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs,0);
}

public Dock(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    ctx=context;

    initAttrs(context,attrs);
}

3.3 通过TypedArray获取属性集中各属性值并设置给控件

private void initAttrs(Context context, AttributeSet attrs){
    TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.Dock);
    iconSize=(int)ta.getDimension(R.styleable.Dock_dockIconSize,dp2px(context,60));

    dockHeight=iconSize + 2*20; //(int)ta.getDimension(R.styleable.Dock_dockHeight,dp2px(context,100));
    dockBgColor=ta.getColor(R.styleable.Dock_dockBacgroundColor, Color.parseColor("#f8f8f8"));

    ta.recycle();
}

3.4 通过onMeasure()设置控件尺寸

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //去除wrap_content、Match_Parent对控件的影响
    setMeasuredDimension(width, mHeight);
}

3.5 通过onDraw()方法完成控件绘制

通过onDraw()方法传递的canvas对象完成控件的最终绘制,可通过getWidth()或getRight()-getLeft()获取view的宽(以及高)。

@Override
protected void onDraw(Canvas canvas) {
	// 准备画笔mPaint
    canvas.drawCircle(100,100,10, mPaint);
}
【安卓自定义控件系列】安卓自定义控件之组合控件 在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组 阅读详情

相关推荐

Unity中实现HLS视频加密与流式播放的完整方案

本文详细介绍了在Unity中实现HLS视频加密与流式播放的完整方案。针对Unity原生VideoPlayer无法直接支持实时解密的问题,提出了基于HLS协议与AES-128加密的成熟解决方案,并重点阐述了如何利用AVPro Video插件进行集成。文章涵盖了从密钥生成、使用FFmpeg进行视频加密切片,到在Unity中动态加载密钥并播放加密流的全流程,为保护付费课程、独家动画等视频内容提供了安全且高效的实践路径。

weixin_29290963的博客 393

android继承View实现复杂的自定义控件(1)

刚接触自定义控件这块内容,想和大家交流下,所以做了这个Demo(程序有些问题会在下面和大家说明) 语言表达不是太好,我就简单说下我做的Demo 1、新建类文件并继承View类,子类复写了onDraw()和onMeasure()方法,实现代码如下: public class PubView extends View{ private Paint mPaint; priv

longying12344的博客 457

Xarray实战:从气象数据到可视化分析的完整流程(附Python代码)

本文详细介绍了使用Xarray库处理气象数据的完整实战流程。针对气象领域常见的NetCDF和GRIB格式,文章从数据读取、坐标操作、智能索引、统计计算到高级可视化,提供了完整的Python代码示例。重点阐述了Xarray如何高效处理高维标记数据,帮助地球科学领域的研究人员将繁琐的数据处理工作转化为高效的分析流水线。

d6e7f8g9h的博客 290

android 自定义view的入门学习之组合控件(1)

android中的自定义view学习文章已经屡见不鲜,但是真正的入门开始级别的我很少查阅到,以下的内容仅仅是本人在学习中的记录 强烈推荐 讲的很细 很细 很细 学习地址:https://space.bilibili.com/44272436/video?tid=0&page=1&keyword=&order=pubdate 在推荐一个android里面用的工具类 有需要的小伙伴可以看一下(真的很方便,其次还是看自己会不会用) https://github.com/Bla...

72的博客 292

从实习生到独立上手:我是如何用海思PQTool搞定IPC图像调试的

本文分享了从实习生到独立使用海思PQTool进行IPC图像调试的成长历程。通过工具搭建、核心参数调整和实战案例,详细介绍了如何高效解决图像质量问题,特别强调了ISP调试中的关键参数和实用技巧,适合刚入门的图像调试工程师参考。

weixin_33756596的博客 312

从315MHz到125kHz:手把手教你用Arduino模拟汽车钥匙的RKE/PKE信号(附代码)

本文详细介绍了如何使用Arduino开发板和射频模块模拟汽车钥匙的RKE/PKE信号,包括硬件准备、代码实现和安全机制。通过实践教程,读者可以深入理解315MHz和125kHz信号在汽车电子领域的应用,掌握无钥匙进入系统的核心技术。

weixin_30945039的博客 223

安卓中自定义控件心得(1)—选用SurfaceView还是View问题

问题:在自定义控件中,我们可以集成view或者SurfaceView,我们什么时候使用View,什么时候使用SurfaceView呢? View: 使用情景:如果没有动态效果,或者动画效果比较简单,使用View最合适不过了 线程:在主线程中绘制,所以在不影响UI线程的情况下比较适用。 假如我们的自定义控件有连续不断的动画,这样就会比较频繁的占用主线程,当我们再做其在主线...

liujian8654562的博客 324

A Super-Resolution Imaging Method for Forward-Looking Scanning Radar Based on Improved TV论文阅读

具体而言,作者提出了一种改进的总变差(Improved Total Variation, ITV)方法,通过引入。论文旨在解决前视扫描雷达(Forward-Looking Scanning Radar)超分辨率成像中传统。(Batch Processing),以增强图像边缘特征的保留能力,并提升计算效率。论文的核心创新点在于对传统TV正则化的邻域梯度计算进行扩展,提出。ITV剖面(图3d)在噪声下仍保持矩形边缘,仅存。​(公式10):实现稀疏约束。),抑制远端单元贡献。(幅度远低于目标)。

yangqoor的博客 1240

Android自定义View----1. 自定义自绘控件

Android自定义View----1. 自定义自绘控件 本节前言 自定义View的实现方式大概可以分为三种: (1).自绘控件   (2).组合控件   (3).继承控件 上一节讲了自定义组合控件,本节讲解自绘控件使用. 本节正文 1. 简介 自定义view中,自绘控件相对较难部分,自绘控件可以理解为,

Steampy专栏 863

Unity抖音小游戏上架实战:从零到一,详解流程与避坑指南

本文详细介绍了Unity抖音小游戏上架的全流程,包括环境准备、SDK集成、开发者账号注册、软著申请、打包提交流程及常见问题解决方案。重点解析了抖音小游戏平台特有的配置细节和避坑技巧,帮助开发者高效完成游戏上架并优化用户体验。

weixin_33704234的博客 261

多物理场光学仿真软件:COMSOL_(10).激光器与谐振腔仿真

定义Nd:YAG晶体的材料属性% 折射率% 吸收系数% 发射截面% 定义光泵浦源% 泵浦光波长% 泵浦光强度% 泵浦光方向% 定义全反射镜% 选择边界% 完美电导体边界条件% 定义部分反射镜% 选择边界% 反射率边界条件% 反射率通过 COMSOL 对激光器和光学谐振腔进行仿真,可以全面评估激光器的性能,包括输出功率、效率、稳定性和模式选择等。这些仿真结果为激光器的设计和优化提供了重要的参考依据。

kkchenjj的博客 1649

Android自定义View----1. 自定义组合控件

Android自定义View----1. 自定义View 实现方式 本节正文: 自定义View的实现方式大概可以分为三种,自绘控件、组合控件以及继承控件。接下来看下每种方式分别是如何自定义View的。 一、组合控件 自定义view中,组合控件是最简单的实现方式,组合控件可以理解为,充分利用系统原有的组件基础上,将多个组件放到同一个布局

Steampy专栏 777

基于互联网的智能旧衣回收箱设计与实现

本文介绍了基于嵌入式系统的智能旧衣回收箱的设计与实现,涵盖了硬件设计、软件开发、图像识别、物联网连接等方面的内容。通过利用最新的技术,如图像识别、物联网和云计算,实现了智能、便捷的旧衣物回收系统。未来,随着技术的不断进步,智能回收系统将会在环保领域发挥更大的作用。

2201_76125393的博客 908

android群英传之自定义View--对现有控件进行扩展(1)

很多时候系统自带的控件无法满足我们设计的要求,这个时候android提供的允许自定义view的办法就帮了我们大忙。在android中,自定义view主要有三种实现方式 1.对现有控件进行扩展 2.通过组合实现新的控件 3.重写view来实现新的控件 现在先是第一点,对现有控件进行扩展 书中给了两个例子,第一个是对textview控件进行扩展,代码片段如下: protecte

sinat_21112393的博客 1069

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

文章标题 Android 自定义控件---- View1

public class MyView extends View {private RectF mrect; private float circleXY; private float radius; private Paint cPaint; private Paint marcPaint; private Paint mTextPaint; private float length; priva

qq_35290457的博客 331

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

android自定义控件学习【1】----自定义卡券View

今日,博主花了点时间看了一篇自定义控件的帖子,看起来好牛X,于是准备自己试试,废话不多说,先来看效果图,今天要做的是自定义锯齿边的卡券View,如下: 也许,你第一眼看到这个效果会觉得这不就是加个背景图片事儿吗?其实不然,以上效果为纯代码编写。其实也很简单,关键是思考清除自己要出的效果该怎么用算法,下面贴上代码: /** * 优惠券自定义View * * @author jih

Lucky_jhf的博客 785

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Android零基础入门第24节:自定义View简单使用

当我们开发中遇到Android原生的组件无法满足需求时,这时候就应该自定义View来满足这些特殊的组件需求。

鑫鱻的博客 2020

Android 基础-------自定义控件

关于Android 的自定义控件     在Android 中自定义控件可以分为三种   1.android 原生控件的扩展 2.组合控件(增加新的属性等) 3.通过重写onMearse  onLayout onDraw以及OnTouch  完全自定义的全新控件   一  原生扩展空间    该种模式的自定义控件是 由于原生控件无法完全满足需求,从而对对

a06963938的博客 451

Android自定义view——动态画圆形

最近经常会被问到自定义控件方向的问题,今天抽空做了一个简单的demo。简单仿照火箭闹钟首页的动画。就是动态的画一个圆形,这个和当前时间的秒值绑定。下面直接看代码

deeny的博客 2550

android 怎么固定控件,Android中如何使控件保持固定宽高比

我们在android开发过程中可能会遇到一种情况,一个组件需要保持固定的宽高比,但是组件本身大小却不定。尤其在android屏幕碎片化的情况下,很多时候我们需要让一个组件宽度与屏幕宽度一致,这样就无法确定宽度。那么如何让控件保持固定宽高比?有几种方法供大家选择。1、自定义view自定义view,重写onMeasure或onLayout等相关方法,通过预定的比例计算宽高。下面是简单示意:@Overr...

weixin_34644072的博客 688

Android自定义View控件

转自:http://blog.youkuaiyun.com/lvwenbo0107/article/details/50542597 为什么要自定义控件 1.特定的显示风格。 2.处理特有的用户交互。(textView支持一些滑动功能) 3.优化我们的布局。(嵌套布局绘制比较慢) 4.封装。(tab页按钮不好看) 如何自定义控件 1.自定义属性声明与获取。

Dream It Possible 1899

Android 自定义View 三板斧之三——重写View来实现全新控件

 通常情况下,Android实现自定义控件无非三种方式。   Ⅰ、继承现有控件,对其控件的功能进行拓展。   Ⅱ、将现有控件进行组合,实现功能更加强大控件。   Ⅲ、重写View实现全新的控件   本文来讨论最难的一种自定义控件形式,重写View来实现全新的控件。   首先,我们要明白在什么样的情况下,需要重写View来实现一种全新的控件,一般当我们遇到...

weixin_33835103的博客 109

Android 自定义View合集

自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/Mr-XiaoLiang 自定义控件三部曲 http://blog.youkuaiyun.com/harvic880925?viewmode=contents 自定义控件博客

苦心孤诣的专栏 1万+

Android自定义View的实现方法,带你一步步深入了解View(四)

转载请注明出处:http://blog.youkuaiyun.com/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回顾一下,我们一共学习了LayoutInflater的原理分析、视图的绘制流程、视图的状态及重绘等知识,算是把View中很多重要的知识点都涉及到了。如果你还没有看过我前面的几篇文章,建

专注Android开发 404

Android自定义View的四种方式

一 前言 在Android开发中有很多业务场景,原生的控件是无法满足应用,并且经常也会遇到一个UI在多处重复使用情况,那么就需要通过自定义View的方式来实现这些UI效果。作为一个Android开发工程师自定义View属于一个必备技能。 像前几天正好做了一个上传本地图片的网格UI,点击相机的icon就可以上传选择本地图片,选中图片之后就可以显示的界面上。本来可以使用Android原生GridView,但是这个控件由于嵌套到ScrollView中,所以导致滑动事件冲突,当然网上...

nihaomabmt的专栏 9970

Android自定义View的三种方式:继承布局,继承原生控件,继承View

自定义View是Android开发的基本技能,本文记录了自定义View的三种方式

Alpinist Wang 1万+
上一篇: PackageManager获取应用列表
下一篇: Android自定义控件(2)--自定义ViewGroup/组合控件
HanZhizhi
博客等级 码龄11年 297粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值