Android自定义简单的View

Android Studio 之 View组件常用属性及其对应的编程接口 1、设置控件背景: android:background <===> public void setBackgroundResource(int resid) 2、设置控件是否可以产生点击事件: android:clickable <====> public void setClickable(boolean clickable) 3、定义视图的内容... 阅读详情

Android自定义View实现很简单

继承View,重写构造函数、onDraw,(onMeasure)等函数。

 

如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml。在其中定义你的属性。

 

在使用到自定义View的xml布局文件中需要加入xmlns:前缀="http://schemas.android.com/apk/res/你的自定义View所在的包路径".

在使用自定义属性的时候,使用前缀:属性名,如my:textColor="#FFFFFFF"。、


format值的格式


1 "reference" //引用
2 "color" //颜色
3 "boolean" //布尔值
4 "dimension" //尺寸值
5 "float" //浮点值
6 "integer" //整型值
7 "string" //字符串
8 "fraction" //百分数,比如200%

枚举型的格式:

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


  1. <resources>  
  2.     <declare-styleable name="MyView">  
  3.         <attr name="textColor" format="color"/>  
  4.         <attr name="textSize" format="dimension"/>  
  5.     </declare-styleable>  
  6. </resources> 
  

XML文件中使用:

1 android:orientation = "vertical"

标志位、位或运算,格式如下:

01 <attr name="windowSoftInputMode">
02   <flag name = "stateUnspecified" value = "0" />
03   <flag name = "stateUnchanged" value = "1" />
04   <flag name = "stateHidden" value = "2" />
05   <flag name = "stateAlwaysHidden" value = "3" />
06   <flag name = "stateVisible" value = "4" />
07   <flag name = "stateAlwaysVisible" value = "5" />
08   <flag name = "adjustUnspecified" value = "0x00" />
09   <flag name = "adjustResize" value = "0x10" />
10   <flag name = "adjustPan" value = "0x20" />
11   <flag name = "adjustNothing" value = "0x30" />
12 </attr>

XML文件中使用:

1android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">

属性定义可以指定多种类型:

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

XML文件中使用:

1android:background = "@drawable/图片ID|#00FF00"


 

实例:

[java]  view plain copy
  1. package demo.view.my;  
  2. import android.content.Context;  
  3. import android.content.res.TypedArray;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.graphics.Paint.Style;  
  8. import android.util.AttributeSet;  
  9. import android.view.View;  
  10. /** 
  11.  * 这个是自定义的TextView. 
  12.  * 至少需要重载构造方法和onDraw方法 
  13.  * 对于自定义的View如果没有自己独特的属性,可以直接在xml文件中使用就可以了 
  14.  * 如果含有自己独特的属性,那么就需要在构造函数中获取属性文件attrs.xml中自定义属性的名称 
  15.  * 并根据需要设定默认值,放在在xml文件中没有定义。 
  16.  * 如果使用自定义属性,那么在应用xml文件中需要加上新的schemas, 
  17.  * 比如这里是xmlns:my="http://schemas.android.com/apk/res/demo.view.my" 
  18.  * 其中xmlns后的“my”是自定义的属性的前缀,res后的是我们自定义View所在的包 
  19.  * @author Administrator 
  20.  * 
  21.  */  
  22. public class MyView extends View {  
  23.       
  24.     Paint mPaint; //画笔,包含了画几何图形、文本等的样式和颜色信息  
  25.     public MyView(Context context) {  
  26.         super(context);  
  27.           
  28.     }  
  29.       
  30.     public MyView(Context context, AttributeSet attrs){  
  31.         super(context, attrs);  
  32.         mPaint = new Paint();  
  33.         //TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组  
  34.         //在使用完成后,一定要调用recycle方法  
  35.         //属性的名称是styleable中的名称+“_”+属性名称  
  36.         TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyView);  
  37.         int textColor = array.getColor(R.styleable.MyView_textColor, 0XFF00FF00); //提供默认值,放置未指定  
  38.         float textSize = array.getDimension(R.styleable.MyView_textSize, 36);  
  39.         mPaint.setColor(textColor);  
  40.         mPaint.setTextSize(textSize);  
  41.           
  42.         array.recycle(); //一定要调用,否则这次的设定会对下次的使用造成影响  
  43.     }  
  44.       
  45.     public void onDraw(Canvas canvas){  
  46.         super.onDraw(canvas);  
  47.         //Canvas中含有很多画图的接口,利用这些接口,我们可以画出我们想要的图形  
  48.         //mPaint = new Paint();  
  49.         //mPaint.setColor(Color.RED);  
  50.         mPaint.setStyle(Style.FILL); //设置填充  
  51.         canvas.drawRect(10, 10, 100, 100, mPaint); //绘制矩形  
  52.           
  53.         mPaint.setColor(Color.BLUE);  
  54.         canvas.drawText("我是被画出来的", 10, 120, mPaint);  
  55.     }  
  56. }  

 

相应的属性文件:

 

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="MyView">  
  4.         <attr name="textColor" format="color"/>  
  5.         <attr name="textSize" format="dimension"/>  
  6.     </declare-styleable>  
  7. </resources>  

 

在布局文件中的使用:

 

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
  3.               xmlns:my="http://schemas.android.com/apk/res/demo.view.my"   
  4.     android:orientation="vertical"  
  5.     android:layout_width="fill_parent"  
  6.     android:layout_height="fill_parent"  
  7.     >  
  8.       
  9.     <demo.view.my.MyView  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"   
  12.         my:textColor="#FFFFFFFF"   
  13.         my:textSize="22dp"  
  14.         />  
  15. </LinearLayout>  







关于  Matrix

Matrix ,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。

        首先介绍一下矩阵运算。加法和减法就不用说了,太简单了,对应位相加就好。图像处理,主要用到的是乘法 。下面是一个乘法的公式:

矩阵相乘示例

 

在 Android 里面, Matrix 由 9 个 float 值构成,是一个 3*3 的矩阵。如下图。

 

Android中Matrix矩阵

 

没专业工具,画的挺难看。解释一下,上面的 sinX 和 cosX ,表示旋转角度的 cos 值和 sin 值,注意,旋转角度是按顺时针方向计算的。 translateX 和 translateY 表示 x 和 y 的平移量。 scale 是缩放的比例, 1 是不变, 2 是表示缩放 1/2 ,这样子。

 

[java]  view plain copy
  1.  1. public   class  MyView  extends  View {    
  2.  2.     
  3.  3.     private  Bitmap mBitmap;    
  4.  4.     
  5.  5.     private  Matrix mMatrix =  new  Matrix();    
  6.  6.     
  7.  7.     public  MyView(Context context) {    
  8.  8.     
  9.  9.         super (context);    
  10. 10.     
  11. 11.         initialize();    
  12. 12.     
  13. 13.     }    
  14. 14.     
  15. 15.     private   void  initialize() {         
  16. 16.     
  17. 17.         mBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap();            
  18. 18.     
  19. 19.         float  cosValue = ( float ) Math.cos(-Math.PI/ 6 );    
  20. 20.     
  21. 21.         float  sinValue = ( float ) Math.sin(-Math.PI/ 6 );    
  22. 22.     
  23. 23.         mMatrix.setValues(    
  24. 24.     
  25. 25.                 new   float []{    
  26. 26.     
  27. 27.                         cosValue, -sinValue, 100 ,    
  28. 28.     
  29. 29.                         sinValue, cosValue, 100 ,    
  30. 30.     
  31. 31.                         0 ,  0 ,  2 });    
  32. 32.     
  33. 33.     }    
  34. 34.     
  35. 35.     @Override   protected   void  onDraw(Canvas canvas) {    
  36. 36.     
  37. 37. //      super.onDraw(canvas);  //当然,如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。     
  38. 38.     
  39. 39.         canvas.drawBitmap(mBitmap, mMatrix, null );    
  40. 40.     
  41. 41.     }    
  42. 42.     
  43. 43. }    

 

运行结果如下:

运行结果

 

以左上角为顶点,缩放一半,逆时针旋转30度,然后沿x轴和y轴分别平移50个像素,代码 里面写的是100,为什么是平移50呢,因为缩放了一半。

       大家可以自己设置一下Matrix的值,或者尝试一下两个Matrix相乘,得到的值设置进去,这样才能对Matrix更加熟练。

这里讲的直接赋值的方式也许有点不好理解,不过还好, andrid 提供了对矩阵的更方便的方法

 

Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在

Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。


    set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。


    post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。例如,要将一个图片旋
转30度,然后平移到(100,100)的地方,那么可以这样做:

 

[java]  view plain copy
  1. # Matrix m =  new  Matrix();    
  2. #     
  3. # m.postRotate(30 );    
  4. #     
  5. # m.postTranslate(100 ,  100 );    

这样就达到了想要的效果。


    pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。例如上面的例子,如果用pre的话

,就要这样:

[java]  view plain copy
  1. 1. Matrix m =  new  Matrix();    
  2. 2.     
  3. 3. m.preTranslate(100 ,  100 );    
  4. 4.     
  5. 5. m.preRotate(30 );    

 

旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,是围绕(0,0)点来进行。

 

[java]  view plain copy
  1.  1. package  chroya.demo.graphics;    
  2.  2.     
  3.  3. import  android.content.Context;    
  4.  4. import  android.graphics.Bitmap;    
  5.  5. import  android.graphics.Canvas;    
  6.  6. import  android.graphics.Matrix;    
  7.  7. import  android.graphics.Rect;    
  8.  8. import  android.graphics.drawable.BitmapDrawable;    
  9.  9. import  android.util.DisplayMetrics;    
  10. 10. import  android.view.MotionEvent;    
  11. 11. import  android.view.View;    
  12. 12.     
  13. 13. public   class  MyView  extends  View {    
  14. 14.         
  15. 15.     private  Bitmap mBitmap;    
  16. 16.     private  Matrix mMatrix =  new  Matrix();    
  17. 17.         
  18. 18.     public  MyView(Context context) {    
  19. 19.         super (context);    
  20. 20.         initialize();    
  21. 21.     }    
  22. 22.     
  23. 23.     private   void  initialize() {    
  24. 24.             
  25. 25.         Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.show)).getBitmap();    
  26. 26.         mBitmap = bmp;    
  27. 27.         /*首先,将缩放为100*100。这里scale的参数是比例。有一点要注意,如果直接用100/   
  28. 28. bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是float型的,直接用100f就好。*/     
  29. 29.         mMatrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight());    
  30. 30.                 //平移到(100,100)处     
  31. 31.         mMatrix.postTranslate(100 ,  100 );    
  32. 32.                 //倾斜x和y轴,以(100,100)为中心。     
  33. 33.         mMatrix.postSkew(0 .2f,  0 .2f,  100 ,  100 );    
  34. 34.     }    
  35. 35.         
  36. 36.     @Override   protected   void  onDraw(Canvas canvas) {    
  37. 37. //      super.onDraw(canvas);  //如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。     
  38. 38.             
  39. 39.         canvas.drawBitmap(mBitmap, mMatrix, null );    
  40. 40.     }    
  41. 41. }    

 

运行结果




Canvas类

需要绘制到画布上,这就得用Canvas类了。在Android中既然把Canvas当做画布,那么就可以在画布上绘制我们想要的任何东西。除了在画布上绘制之外,还需要设置一些关于画布的属性,比如,画布的颜色、尺寸等。下面来分析Android中Canvas有哪些功能,Canvas提供了如下一些方法:

       Canvas(): 创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布。
       Canvas(Bitmap bitmap): 以bitmap对象创建一个画布,则将内容都绘制在bitmap上,因此bitmap不得为null。
       Canvas(GL gl): 在绘制3D效果时使用,与OpenGL相关。
       drawColor: 设置Canvas的背景颜色。
       setBitmap:  设置具体画布。
       clipRect: 设置显示区域,即设置裁剪区。
       isOpaque:检测是否支持透明。
       rotate:  旋转画布
       setViewport:  设置画布中显示窗口。
       skew:  设置偏移量。

       上面列举了几个常用的方法。在游戏开发中,我们可能需要对某个精灵执行旋转、缩放和一些其它操作。我们可以通过旋转画布来实现,但是旋转画布时会旋转画布上的所有对象,而我们只是需要旋转其中的一个,这时就需要用到save 方法来锁定需要操作的对象,在操作之后通过 restore 方法来解除锁定,下面我们先来看一下运行效果吧。

我们对左边的矩形执行了旋转操作,而没有旋转右边的矩形,由于我们设置了裁剪区域,因此左边的矩形只能看到一部分,下面让我们来看看代码 这里我只贴出了我们自己的 View类 GameView Activity类不贴出了 就在里边 new 一个GameView类 然后设置布局 然后main.xml也不贴出来了 因为它根本就没用到。

Java代码 
import android.content.Context;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.Rect;  
import android.view.KeyEvent;  
import android.view.MotionEvent;  
import android.view.View;  
 
public class GameView extends View implements Runnable {  
/* 声明Paint对象 */  
private Paint mPaint = null;  
 
public GameView(Context context) {  
super(context);  
/* 构建对象 */  
mPaint = new Paint();  
 
/* 开启线程 */  
new Thread(this).start();  
}  
 
public void onDraw(Canvas canvas) {  
super.onDraw(canvas);  
 
/* 设置画布的颜色 */  
canvas.drawColor(Color.BLACK);  
 
/* 设置取消锯齿效果 */  
mPaint.setAntiAlias(true);  
 
/* 设置裁剪区域 */  
canvas.clipRect(10, 10, 280, 260);  
 
/* 线锁定画布 */  
canvas.save();  
/* 旋转画布 */  
canvas.rotate(45.0f);  
 
/* 设置颜色及绘制矩形 */  
mPaint.setColor(Color.RED);  
canvas.drawRect(new Rect(15, 15, 140, 70), mPaint);  
 
/* 解除画布的锁定 */  
canvas.restore();  
 
/* 设置颜色及绘制另一个矩形 */  
mPaint.setColor(Color.GREEN);  
canvas.drawRect(new Rect(150, 75, 260, 120), mPaint);  
}  
 
// 触笔事件  
public boolean onTouchEvent(MotionEvent event) {  
return true;  
}  
 
// 按键按下事件  
public boolean onKeyDown(int keyCode, KeyEvent event) {  
return true;  
}  
 
// 按键弹起事件  
public boolean onKeyUp(int keyCode, KeyEvent event) {  
return false;  
}  
 
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {  
return true;  
}  
 
public void run() {  
while (!Thread.currentThread().isInterrupted()) {  
try {  
Thread.sleep(100);  
} catch (InterruptedException e) {  
Thread.currentThread().interrupt();  
}  
// 使用postInvalidate可以直接在线程中更新界面  
postInvalidate();  
}  
}  
} 


  canvas.drawRect(RectF,Paint)方法用于画矩形,第一个参数为图形显示区域,第二个参数为画笔,设置好图形显示区域Rect和画笔Paint后,即可画图;


    canvas.drawRoundRect(RectF, float, float, Paint) 方法用于画圆角矩形,第一个参数为图形显示区域,第二个参数和第三个参数分别是水平圆角半径和垂直圆角半径。


    canvas.drawLine(startX, startY, stopX, stopY, paint):前四个参数的类型均为float,最后一个参数类型为Paint。表示用画笔paint从点(startX,startY)到点(stopX,stopY)画一条直线;


    canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint):第一个参数oval为RectF类型,即圆弧显示区域,startAngle和sweepAngle均为float类型,分别表示圆弧起始角度和圆弧度数,3点钟方向为0度,useCenter设置是否显示圆心,boolean类型,paint为画笔;


    canvas.drawCircle(float,float, float, Paint)方法用于画圆,前两个参数代表圆心坐标,第三个参数为圆半径,第四个参数是画笔;


   清楚这些函数的用法之后,我们是否就噼里啪啦地敲代码了呢?别急,我们来搞个设计。既然这些函数都是用来画图的,也就是说它们有共性——画。所有我们应该设计一个接口interface,对于这次任务,只需要一个成员方法就足够了。对于每一个图形,是只用一个方法画,还是将画图封装成类呢?我建议是封装成类。因为说不定你明天就会嫌弃它不会动,想它动起来,或者你过两天又希望在机器人的每个部位加点什么。所以我将每一个图形封装成类,都实现一个名叫drawGraphics的接口。最后,要记得给UI创建一个线程哦。


   就这样我开始动手做了,但是很快就发现问题了。什么问题?在定位的时候,也就是设置每个图形的显示区域时,我自以为这里的Rect跟Java的Rectangle是一样的,但我错了。原来这厮跟MFC中的RECT结构才是一家人,害我折腾了许久。


    Rect(int left,int top,int right,int bottom)
 
    left
              矩形左上角X坐标值
    top
              矩形左上角Y坐标值
    right
              矩形右下角X坐标值
    bottom
              矩形右下角Y坐标值

  
package com.dengchuan.android.drawable;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;


public class GameView extends View  implements  Runnable{


//声明Paint对象
   private  Paint mPaint= null;
   private drawGraphics drawGraphics= null;


  
   public GameView(Context context) {
        super(context);
       //开启线程
       new  Thread(this).start();
   }


   public void  onDraw(Canvas canvas) {
       super.onDraw(canvas);
       //构建对象
       mPaint= new Paint();
       //设置画布为黑色背景
       canvas.drawColor(Color.BLUE);
       //消除锯齿
       mPaint.setAntiAlias(true);
      //设置图形为空心
//       mPaint.setStyle(Paint.Style.STROKE);
       mPaint.setStyle(Paint.Style.FILL);
       //绘制机器人的头部和眼睛
       drawGraphics=  new DrawCircle(mPaint);
       drawGraphics.draw(canvas);
       //绘制机器人的天线
       drawGraphics=  new DrawLine(mPaint);
       drawGraphics.draw(canvas);
       //绘制机器人的身子和四肢
       drawGraphics= new DrawRect(mPaint);
       drawGraphics.draw(canvas);
       
   }
    
      @Override
      public void run() {
           // TODOAuto-generated method stub
           while(!Thread.currentThread().isInterrupted()) {
                try{
                      Thread.sleep(1000);
                } catch(InterruptedException e) {
                  // TODO: handle exception
                  Thread.currentThread().interrupt();
                }
                 //使用postInvalidate 可以直接在线程中更新界面
                  postInvalidate(); 
           }
     }


}

package com.dengchuan.android.drawable;


import android.graphics.Canvas;


public interface drawGraphics {
public void  draw(Canvas canvas);
}

package com.dengchuan.android.drawable;


import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;


public class DrawLine implements  drawGraphics{
 
    private Paint paint=  null;


    public  DrawLine(){
        paint=  new  Paint();
    }
    public  DrawLine(Paint paint){
    this.paint=  paint;
    }
   
     @Override
     public void draw(Canvas canvas) {
         // TODOAuto-generated method stub
         paint.setAntiAlias(true);
         //绘制直线
         paint.setColor(Color.GREEN);
         //设置线条粗细
         paint.setStrokeWidth(12);
         canvas.drawLine(120,40,170,90, paint);
         canvas.drawLine(320,90,370,40, paint);
    }
}
package com.dengchuan.android.drawable;


import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;


public class DrawRect implements  drawGraphics{
 
    private  Paint paint=  null;


    public DrawRect(){
    paint= new  Paint();
    }
    public DrawRect(Paint paint){
    this.paint= paint;
    }


   
      @Override
      public void  draw(Canvas canvas) {
          // TODOAuto-generated method stub
          //定义圆角矩形对象
          RectF rectF1 = new RectF(120,170,370,500);
          RectF rectF2 = new RectF(40,150,90,400);
          RectF rectF3 = new RectF(390,150,440,400);
          RectF rectF4 = new RectF(140,520,200,650);
          RectF rectF5 = new RectF(290,520,350,650);
          paint.setAntiAlias(true);
          //设置画笔颜色为BLUE
          paint.setColor(Color.GREEN);
          //在画布上绘制圆角矩形/圆弧/直线
          canvas.drawRoundRect(rectF1, 30, 30, paint);
          canvas.drawRoundRect(rectF2, 20, 20, paint);
          canvas.drawRoundRect(rectF3, 20, 20, paint);
          canvas.drawRoundRect(rectF4, 20, 20, paint);
          canvas.drawRoundRect(rectF5, 20, 20, paint);
     }
}

package com.dengchuan.android.drawable;


import android.app.Activity;
import android.os.Bundle;


public class GameStart extends Activity {
private  GameView mGameView=  null; 
 
    
    @Override
    public  void  onCreate(Bundle  savedInstanceState) { 
        super.onCreate(savedInstanceState);
        this.mGameView= new GameView(this);
        setContentView(mGameView);
    }


}

package com.dengchuan.android.drawable;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;


public class GameView extends View  implements  Runnable{


//声明Paint对象
   private  Paint mPaint= null;
   private drawGraphics drawGraphics= null;


  
   public GameView(Context context) {
        super(context);
       //开启线程
       new  Thread(this).start();
   }


   public void  onDraw(Canvas canvas) {
       super.onDraw(canvas);
       //构建对象
       mPaint= new Paint();
       //设置画布为黑色背景
       canvas.drawColor(Color.BLUE);
       //消除锯齿
       mPaint.setAntiAlias(true);
      //设置图形为空心
//       mPaint.setStyle(Paint.Style.STROKE);
       mPaint.setStyle(Paint.Style.FILL);
       //绘制机器人的头部和眼睛
       drawGraphics=  new DrawCircle(mPaint);
       drawGraphics.draw(canvas);
       //绘制机器人的天线
       drawGraphics=  new DrawLine(mPaint);
       drawGraphics.draw(canvas);
       //绘制机器人的身子和四肢
       drawGraphics= new DrawRect(mPaint);
       drawGraphics.draw(canvas);
       
   }
    
      @Override
      public void run() {
           // TODOAuto-generated method stub
           while(!Thread.currentThread().isInterrupted()) {
                try{
                      Thread.sleep(1000);
                } catch(InterruptedException e) {
                  // TODO: handle exception
                  Thread.currentThread().interrupt();
                }
                 //使用postInvalidate 可以直接在线程中更新界面
                  postInvalidate(); 
           }
     }


}






简单说说Android自定义view学习推荐的方式 这几天比较受关注,挺开心的,嘿嘿。 这里给大家总结一下学习自定义view的一些技巧。 1.首先 去看看鸿洋神的博客 Android 自定义view(1). 鸿洋神的入门教程讲的很详细。再次膜拜。 然后我这里对上面博客补充一些内容,那就是MeasureSpec相关的一些东西,这些东西我在《圆形百分比》这篇博客里提到过。 ---------------------------- 阅读详情

相关推荐

Android自定义View之自定义一个简单的阶梯式布局

onMeasure: 确定自身的大小 确定子View的大小 流程: 1. ViewGroup开始测量自己的尺寸 2. 为每个子View计算测量的限制信息 3. 把上一步确定的限制信息,传递给每一个字View,然后子View开始measure自己的尺寸 4. 获取子View测量完成后的尺寸 5. ViewGroup根据自身的情况,计算自己的尺寸 6. 保存自身的尺寸 onLayout: 1. 根据规则确定子View位置 流程: 1. 遍历子View 2. 确定自己的规则 3. 子View的测量尺寸 .

fakerXuan的博客 553

Android 自定义view 入门 案例

9.最后在新建一个页面:ThreeActivity, 并在AndroidManifest.xml,设置为启动页面。创建完成后,在xml添加自定义view:activity_three.xml。第一个是逻辑代码,第二个是布局,第三个是view需要使用的属性(通过这种方式创建属性,多次创建可能造成一些变量重复定义。8.更新自定义布局:sample_super_circle_view.xml。sample_super_circle_view.xml布局源码。3.输入自定义名称,选择开发语言。11.最后运行即可。

LlanyW的专栏 1220

android学习笔记之自定义View之实现一个简单的加载动画

一、概述学习自定义view最基础的知识后就需要做一个小demo来检验自己的成果,比如实现以下加载动画。

falconkevin的博客 1520

Android Studio的代码笔记--Adapter+GridView学习

android 用gridview+adapter 实现显示本地应用

weixin_45208598的博客 1313

Android studio编写的自定义view

在网上找了很多关于自定义view的博客,但都是用eclipse编写的代码。这是我用Android studio写的代码,很简单。

DPM|03Injection设置

摘要:本文介绍了CFD软件Fluent中粒子注入的设置方法。粒子注入是将离散颗粒引入连续相的过程,可用于模拟灰尘、燃料液滴等。设置流程包括:选择粒子类型(质量less、惰性等)、定义注入点属性(坐标、时间、粒径等)、处理多组分粒子、使用文本文件批量定义复杂注入。文中还详细说明了要考虑的湍流影响,包括随机追踪法模拟湍流扩散,以及粒子旋转建模等注意事项。最后介绍了多种注入类型和粒子类型,并强调在湍流系统中需设置足够的尝试次数以确保结果准确性。

qq_28258217的博客 2229

Android Studio中android.view.View类找不到

问题背景 作为一个安卓新手玩家,碰到一些比较玄学的问题还是蛮崩溃的。 电脑运行AS导致死机后再重启,代码就一系列报红,找不到最基础的View类和Handler类。 网上的方法基本都试过,都没有解决问题,这些方法包括: 1)File->Invalidate Cache 2)删掉项目目录下的.idea和.gradle包,然后重新build 解决思路 出现问题还是要动脑思考出现问题的原因,出错的源头在哪里。 View是最基本的类,所以它应该是在安卓的SDK中就有的,所以我们来查一下安卓SDK

Algorithm_goddness的博客 4497

fMRI独立成分分析方法(ICA)工具GIFT

详细介绍了进行fmri数据进行ICA分析的工具包GIFT的使用,和进行ICA分析的流程。

m0_58256026的博客 1万+

Android 自定义View 加 lifecycle 简单使用

 在自定义View中了解在 onMeasure中进行view 的测量,在onLayout中进行对view位置的控制,在onDraw中进行view的绘制。 通过 lifecycle控制view的生命周期,防止出现内存泄露问题如在相应的生命周期中操作动画的执行状态

日积月累 1409

LightGBM处理类别特征和缺失值有多省心?一个真实业务数据案例带你上手

本文通过真实电商数据案例,详细解析了LightGBM如何高效处理类别特征和缺失值。相比传统方法,LightGBM仅需一行代码即可自动处理高基数类别特征和缺失值,大幅提升模型训练效率和预测准确度,特别适合业务场景中的脏数据处理。

weixin_30689307的博客 460

HWSD2.0土壤数据处理实战:从下载到属性提取全流程解析

本文详细解析了HWSD2.0全球土壤数据库从数据下载、属性筛选到GIS空间连接与提取的全流程实战方法。重点介绍了如何利用ArcGIS Pro等工具,将土壤单元编码与黏粒含量等属性表关联,最终生成全球土壤属性专题栅格图,为农业规划与生态研究提供关键数据支撑。

weixin_29214691的博客 610

android view流星,刚学习安卓几个月,自己写了一个简单的自定义View

package com.hy.rpg.view;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import a...

weixin_42502408的博客 183

计算机网络期末复习提纲(全知识点总结)

计算机网络期末复习提纲全知识点总结第一章 概述1.基本概念- 链路,结点,协议和服务,实体和对等实体,各层PDU- C/S模式,B/S模式,P2P模式- LAN,WAN,MAN,PAN的划分- 网络性能参数:速率,带宽,吞吐量,时延,往返时间,信道利用率2.互联网的组成(边缘部分与核心部分的作用)3.电路交换与分组交换,数据报交换和虚电路交换的特点4.TCP/IP体系结构,数据的封装与解封装第二章 物理层1.信号编码:不归零编码,曼切斯特编码2.影响信号失真程度的因素3.传输介质:双绞线,同轴电缆,光纤(单

mcyuuji的博客 8万+

Android自定义View示例(零)—很简单的自定义View

MainActivity如下: package cc.testcompounddrawables; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.widget.TextView; /** * Demo描述: *

谷哥的小弟 2799

华为OD机试2025A卷 - 分苹果(Java & Python& JS & C++ & C )

华为OD机试2025A卷 - 分苹果(Java & Python& JS & C++ & C )

算法大师! 720

[AI] 本地部署 Dify 遇到 Internal Error?一文彻底解决密码不一致引发的问题

摘要:Dify本地部署常见InternalError错误主要由配置残留或密码不一致导致,特别是修改.env文件后未同步清除数据库记录。彻底解决方案包括:1)清理Docker数据;2)删除旧配置和数据库;3)还原源代码;4)重建.env文件;5)重新初始化部署。关键提醒:记录部署路径、备份.env文件并妥善保存密码。该错误本质是配置冲突,最有效方法是完全重置而非调试,保持清晰的部署管理可避免多数InternalError问题。(149字)

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 435

Android下 一个自定义VIEW实现简单的弹幕效果

Android下 一个自定义VIEW实现简单的弹幕效果 先上图: xml布局: <com.co.barrage.BarrageView android:id="@+id/barrage_view" android:layout_width="match_parent" android:layout_height="ma

tianguilin1020的博客 912

[Python从零到壹] 十四.机器学习之分类算法五万字总结全网首发(决策树、KNN、SVM、分类对比实验)

分类(Classification)属于有监督学习(Supervised Learning)中的一类,它是数据挖掘、机器学习和数据科学中一个重要的研究领域。分类模型类似于人类学习的方式,通过对历史数据或训练集的学习得到一个目标函数,再用该目标函数预测新数据集的未知属性。本章主要讲述分类算法基础概念,并结合决策树、KNN、SVM分类算法案例分析各类数据集,从而让读者学会使用Python分类算法分析自己的数据集,研究自己领域的知识,从而创造价值。 19.1 分类 19.1.1 分类模型 与前面讲述的聚类模型类似

杨秀璋的专栏 2万+

Android基于Canvas,自定义View实现简单的画图工具

我们要实现的功能:1、点击相应的按钮,在图上画出相应的图形,并实时展现在画布上。2、橡皮檫功能,点击橡皮擦按钮,可以擦除画图上的图形。3、点击确定按钮可以停止当前的绘制。4、点击保存按钮可以把绘制的图形保存为jpg格式的图片文件。具体如下图:具体实现步骤:1、先自定义view,在view里实现各种画图的操作,代码如下:public class TestView extends View { ...

weixin_42058532的博客 697

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Android自定义View(1)——初步实现简单的自定义View

已经有一段时间没有给大家更新博客了,貌似自从学校的实训一开始就一直没有心思去学新的东西和写博客,因为这段时间一直都有很多事情要忙,而且笔者马上就要开始实习工作了,可能心理上也是有一定的压力哈哈。现在事情都处理的差不多了,可以重操旧业专心学习了!!!!! 今天给大家带来的是如何关于自定义View的文章,之后笔者会将动画和自定义View的文章陆陆续续整合到一起,方便大家阅读。 目录 自定义Vie...

zy_jibai 3260

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

android实现横向选择器,安卓开发 简单实现自定义横向滚动选择View : HorizontalselectedView...

一、需求:今日产品经理让在产品里面加了个横向选择的功能,控件样子大致要求为: 网上找了好久没找到此控件,只能自己动手写了,很适合新手练习自定义View,并贡献给大家,效果如下: 其实很多滚轮控件也只是这个简单控件 组合一下就可以了 。有任何问题可以加QQ群询问:661614986。二、实现思路:这里我偷懒了,没有把上、左、右三个箭头写到控件里面,写进去也简单,不过突然感觉在外面布局,写个方法出来也...

weixin_42393261的博客 1469

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android自定义View之超简单圆形数字指示器

Android自定义View之超简单圆形数字指示器

Gao_yuyu的博客 1663

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

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

鑫鱻的博客 2020

android 字体描边实现,Android自定义View实现简单文字描边功能

本文实例为大家分享了Android实现简单文字描边功能的具体代码,供大家参考,具体内容如下效果图:实现代码:package com.example.zhangyu.myview.widget;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;impo...

weixin_42508185的博客 397

android 自定义园view,Android 自定义简单View

Android 自定义简单View阅读此篇博客前请先行阅读 Android View 自定义属性 然后我们来回顾一下自定义View需要做哪些事情:自定义View属性【attrs】自定义View类并继承自View,重写构造器,并获取上面自定义View属性重写onMeasure方法,如果需要的话重写onDraw方法上面四个步骤一般在自定义View的时候都需要,如果父类的onMeasure测量有误,这里...

weixin_39867594的博客 94

Android 自定义View(一) 介绍和一个简单TextView显示

转载注明出处:http://blog.csdn.net/lb454048898/article/details/50791101

辣鸡的记录之路 982
上一篇: Android Build获得系统信息
下一篇: android动画详解
qeqeqe236
博客等级 码龄17年 98粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值