zoukankan      html  css  js  c++  java
  • android开发系列之使用xml自定义控件

          在android开发的过程中,有的时候面对多个Activity里面一些相同的布局,我们需要写多次相同的代码,同时这种方法给我们的项目维护也带来了很大不便。那么有没有一种可行的办法能够将Activity里面相同的布局拆分的很清楚呢?当然是有的,这个时候就轮到自定义控件闪亮登场了。

          其实在android里面有多种方法去实现自定义控件,但是今天这篇博客里面只介绍使用xml的方式进行自定义控件的创建。请看下面的这种场景,不管在哪个页面里面都有个标题,包括一条居中的文本信息和在左边的返回按钮。这个时候我们就可以将上面的标题拆分成一个控件,然后在该控件里面暴露出一个text属性和一个按钮的点击事件。

          首先让我们先来创建一个前台的xml文件用于放置布局,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/test"
        android:gravity="center_vertical">
    
        <TextView
            android:id="@+id/tvBack"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="<"
            android:layout_alignParentLeft="true" />
    
        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="登录"
            android:layout_centerHorizontal="true"/>
    
    </RelativeLayout>
    

     可以看到在上面的布局里面,我们只是放置了两个TextView,一个表示返回,另一个则表示title。

           看到这里聪明的你也许就能猜到了,会不会在自定义控件的时候,我们也同样需要采用某种方法加载上面的布局文件,然后在加载的时候同时关联自己定义好的属性和事件到上面返回的TextView点击事件和标题的TextView的text属性呢?是的,请看比较重要的后台关联代码类定义:

    public class TitleControl extends RelativeLayout {
    }
    

     可以发现TitleControl我们是直接从RelativeLayout继承而来的,这样的话TitleControl就属于一种View控件了。接下来所要做的事情,就是定义属性和事件了。现在假设我们需要定义一个MyText属性,那么应该怎么做呢?请看如下代码:

    public class TitleControl extends RelativeLayout {
    
        private TextView tvBack, tvTitle;
        private String title;
    
        public TitleControl(Context context) {
            super(context);
        }
    
        public TitleControl(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            View view = View.inflate(context, R.layout.activity_title, this);
            tvTitle = (TextView) view.findViewById(R.id.tvTitle);
    
            tvBack = (TextView) view.findViewById(R.id.tvBack);
            tvBack.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                   
                }
            });
    
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.title);
            title = a.getString(R.styleable.title_MyText);
            a.recycle();
    
            tvTitle.setText(title, TextView.BufferType.SPANNABLE);
    
        }
    
        public String getTitle() {
            return this.title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    }
    

     在上面的代码里面我们通过View的inflate方法加载前台页面,然后通过findViewById方法就找到了前台需要关联的控件了。但是我们自己定义的属性放在哪里呢?一种比较容易维护的做法就是将属性放置在xml文件里面。下面就让我们来看看属性的xml代码:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="title">
            <attr name="MyText" format="string"/>
        </declare-styleable>
    </resources>
    

            当我们定义好属性xml之后,就可以通过下面的这段代码,将我们自己定义的MyText属性关联到TextView的Text属性上面了。这样就相当于实现了自定义属性。

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.title);
    title = a.getString(R.styleable.title_MyText);
    a.recycle();
    
    tvTitle.setText(title, TextView.BufferType.SPANNABLE);
    

            做到这里我们就差一个自定义事件了,那么我们怎样去定义一个事件关联到TextView的点击上面呢?答案是通过回调方法的方式实现的,请看回调方法的定义:

    private ITitleCallback iTitleCallback;
    
        public interface ITitleCallback {
            void OnBackClickLinear();
        }
    
        public void setTitleClickLinear(ITitleCallback iTitleCallback) {
            this.iTitleCallback = iTitleCallback;
        }
    

     然后在TextView点击的时候执行如下代码就可以了:

    tvBack = (TextView) view.findViewById(R.id.tvBack);
            tvBack.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(iTitleCallback!=null){
                        iTitleCallback.OnBackClickLinear();
                    }
                }
            });
    

           好了,今天就到这里吧!如有不对,欢迎拍砖。

  • 相关阅读:
    根据数组对象中的某个属性值排序
    vue小知识
    vue项目中config文件中的 index.js 配置
    小问题
    原生无缝轮播
    webpack打包提交代码
    echarts
    面试问题
    MySql
    vue-router 跳转原理
  • 原文地址:https://www.cnblogs.com/xiaocai20091687/p/android-xiaocai-control.html
Copyright © 2011-2022 走看看