zoukankan      html  css  js  c++  java
  • Android 自定义View 启航 一般View定义

       Android应用程序使用View和ViewGroup来构建用户界面,它们都是继承自View类(或其子类)例如:Button、TextView、EditText等。各类View搭配上Style和Animation可以编织出非常丰富的UI,足以应付绝大部分的需求。但有时候我们也需要一些特别的View ,以带给用户与众不同的体验。

        在此我打算写一个大长篇都是关于android View的,主要内容为:SDK上部分文章翻译(英文水平有限尽请拍砖);自定义的View、android源代码分析、开源View代码分析;各类App应用的界面模仿;以理论+代码示例+实践 的方式指导本系列博文的撰写。

        ——因为本人水平有限,而且写系列经常虎头蛇尾,所以这个系列就不写总目录了。如果哪天您发现本系列不在更新,而我又开始了另一个“大长篇”,那么请扔鸡蛋吧。(但是我们不退票!)

        ——出于前车之鉴,本系列中的源码将不提供打包服务。

       言归正传,在我们编写android程序时一般是自定义以一个类继承自Activity 并且重写onCreate方法:

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }

    setContentView()方法包含多个重载其中一个便是“setContentView(View view)”,也就是说可以直接通过一个View的实例来构建内容。我们尝试放入一个TextView,上面的代码变成了这样:

    @Override
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
      // setContentView(R.layout.main);

          TextView sayHello = new TextView(this);
          sayHello.setText("Hello world! I'm a TextView.");
          setContentView(sayHello);
           
        }

    运行这段代码,在模拟器上你应该可以看到以下结果:

    截屏(2011-12-05 22_08_58).jpg

    如此简单不是吗?好吧让我们再让它丰富点:

    @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      // setContentView(R.layout.main);
    //  TextView sayHello = new TextView(this);
    //  sayHello.setText("Hello world! I'm a TextView.");
      setContentView(new SayHello(this));
           
        }
     
     
     class SayHello extends View{

      public SayHello(Context context) {
       super(context);
      }

      @Override
      protected void onDraw(Canvas canvas) {
       super.onDraw(canvas);
       Paint mPaint=new Paint() ;
       mPaint.setTextSize(22f);
       mPaint.setColor(Color.RED);
       canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
      }
     }

    这次我们自定义了一个局部类SayHello 继承自View并且重写了 onDraw 方法(需要注意的是由于View没有无参构造函数所以我们为其指定实现哪一个构造函数)。在onDraw 方法中我们定义了一个Paint,现在你只需要理解它有绘画的功能即可,那么它要在哪里绘画呢?答案就是在Canvas上,可以把Canvas理解成画布。

    现在我们设置mPaint的字体大小为22F  颜色为红色,然后在画布上写出“Hello world。。。”这几个红色的字,并且把onCreate里的setContentView 为setContentView(new SayHello(this));
    最后在模拟器上你应该看到的是:

     截屏(2011-12-05 22_37_57).jpg

    so cool! 不是吗?

    不!不对,我们在Android的开发View不是这样的,它应该是通过 Xml.......@##¥%

    好吧 让我们再把例子修改一下。

     首先我们将SayHello 类提取出来,并且将它放入一个单独的类文件中,接下来就是重点:我们需要添加另外的一些构造函数以便给View传递参数,最好你看到的SayHello 类应该是这样的:

    public class SayHello extends View {
     
     public SayHello(Context context)
     {
      super(context);
     }

     public SayHello(Context context, AttributeSet attrs) {
      this(context, attrs,0);
     }
     
     public SayHello(Context context, AttributeSet attrs,int defStyle)
     {
      super(context, attrs, defStyle);
     }
     
     
     @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      Paint mPaint=new Paint() ;
      mPaint.setTextSize(22f);
      mPaint.setColor(Color.RED);
      canvas.drawText("Hello world! I'm a TextView.", 0, 100, mPaint);
     }
     

    }

    这里简单讲解一下新增的构造函数的作用,在新的构造函数中为View的构造函数传递了AttributeSet attrs,int defStyle两个参数,这代表着该View可以通过XML 来创建并且接受Style来设定样式。等到相关博文时会再具体讲解。

    接下来,我们恢复Activity类里的onCreate方法让它看起来像这个样子:

    @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
       setContentView(R.layout.main);

           
        }

    和一开始没啥两样对吧。

      最后我们需要去修改布局文件main 在文件里加入以下 xml标签:

     <com.××××.customview.SayHello
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >
        </com.××××.customview.SayHello>

    (注意××××,代表SayHello类所在的包,这里需要的是全名)。

    然后再次运行程序,你应该看到以下结果:

     截屏(2011-12-05 22_58_04).jpg

    是不是和我们平常定义View时很像了?

    你感觉得还不够,还缺乏些什么?

    好吧,你很聪明,我们的Text应该是在XML上通过某个属性配置而成的,而不是写在代码里!

    为了将SayHello的属性暴露到XMl上首先我们需要在res/value 文件夹下新建一个XMl文件,命名为:atts。

    在里面添加如下代码:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
     <declare-styleable name="SayHello">
         <attr name="content" format="string"></attr>
         <attr name="text_color" format="color"></attr>
     </declare-styleable>
       
    </resources>

     需要注意的是这里是没有智能提示的

    然后我们需要修改SayHello类,还记得那个AttributeSet吗?我们将通过它来获取XML配置上的属性值。修改后的SayHello类代码是这样的:

    private int mColor;
     private String mContent;

    public SayHello(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      TypedArray typeArray = context.obtainStyledAttributes(attrs,
        R.styleable.SayHello);
      mColor=typeArray.getColor(R.styleable.SayHello_text_color, 0XFF00FF00);
      mContent=typeArray.getString(R.styleable.SayHello_content);
      
     }

    @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      Paint mPaint = new Paint();
      mPaint.setTextSize(22f);
      mPaint.setColor(mColor);
      canvas.drawText(mContent, 0, 100, mPaint);
     }

    现在可以去XML上为哥哥属性添加值了,不过先别着急我们的得将命名空间告诉它。

    在布局文件的根源是上(通常是Layout)添加: xmlns:SayHello="http://schemas.android.com/apk/res/com.XXXX.customview"

    SayHello 可以为您任意想要定义的名字,它将作为属性的前缀使用就像android:Layout 一样而我们的为:SayHello:content,后半段http://schemas.android.com/apk/res/ 为固定值,紧接着的是你整个APP的包命名,你不知道自己包名称?赶去去 AndroidManifest.xml文件中看看吧(注意该包名需要保持和manifest中的 package 保持一致,否则会提示无法找到XML属性)。

    最后我们终于可以在XML上定义自己想要的字体颜色的内容了:

    <com.XXXX.customview.SayHello
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            SayHello:text_color="#1212f0"
            SayHello:content="this is a xml attr view">
        </com.XXXX.customview.SayHello>

     运行程序您应该会看到以下结果:

    剪切板(2011-12-05 23_29_55).png

    这就是我们View 一般的定义方式和过程。

    ——启航。

     //本笔记从 麦库中复制过来, 图片连不上,请见谅

  • 相关阅读:
    [置顶] Docker学习总结(3)——Docker实战之入门以及Dockerfile(三)
    [置顶] Docker学习总结(2)——Docker实战之入门以及Dockerfile(二)
    Vue-Router中History模式【华为云分享】
    Linux系统通过FTP进行文档基本操作【华为云分享】
    窥探日志的秘密【华为云分享】
    弹性负载均衡:负载无限,均衡有道【华为云分享】
    不给糖果就捣乱,用Python绘制有趣的万圣节南瓜怪【华为云分享】
    机器学习笔记(八)---- 神经网络【华为云分享】
    还在为运维烦恼?体验云上运维服务,提意见赢好礼!【华为云分享】
    Vue+ElementUI项目使用webpack输出MPA【华为云分享】
  • 原文地址:https://www.cnblogs.com/keyindex/p/2321027.html
Copyright © 2011-2022 走看看