自定义控件的设计

大半个月没写文章了,期间的工作多了是一方面的原因,另一方面,也因为工作的原因,心里有一些迷茫,也没有心思写些什么。不过还好,还是要坚持自己原来的选择才是正确的,只有坚持下去才会知道将来会不会后悔,相信,将来的某一天,即便自己一无所成,也会因为自己曾经努力过不至于太过后悔,哪怕将来再从头再来呢。。

说了一点与题不相干的话。

今天主要是想记录一下最近这两天研究的关于自定义控件的一些东西。首先说明,我的程序是用Android Studio写的。

这个Demo完整的源代码我已经上传,如果有需要的朋友可以前往下载,我把地址贴在这里:

自定义View的实现

一、自定义控件设置的一些属性值:

自定义控件属性在values/attrs.xml中进行设置,该文件中包含若干个attr集合。其中resources是根标签,可以在里面设置n个declare-styleable,其中name定义了变量的名称,attr下的name定义了属性的名称。属性名可以任意设置,建议最好使用英文命名。attr下的format的值得说明:

reference:参考某一资源ID;

color:颜色值;

dimension:尺寸值;

fraction:百分值;

enum:枚举值;

flag:位或运算;

boolean:布尔值;

float:浮点值;

integer:整型值;

string:字符串;

多类型:<attrname="pinned_view1" format="reference|color" />

attrs.xml参考代码:

<?xml version="1.0" encoding="utf-8"?>
<resources>
      <declare-styleable name="custom_view">
          <attr name="custom_id" format="integer"/>
          <attr name="src" format="reference"/>
          <attr name="backgroud" format="reference"/>
          <attr name="text" format="string"/>
          <attr name="textColor" format="color"/>
          <attr name="textSize" format="dimension"/>
      </declare-styleable>
</resources>
二、自定义控件的使用

属性的使用,在自定义VIew的代码中引入自定义的属性,修改构造函数。

Context通过调用obtainStyleAttributes方法来获取一个TypeArray,然后由该TypeArray来对属性进行设置。obtainStyleAttributes方法有四个,最常用的是obtainStyleAttributes(AttributeSet set,int[] attrs),set(现在检索的属性值)直接从构造方法中获得,attrs(制定的检索的属性值)直接从styleable中获得。该方法返回一个由AttributeSet该获得的一系列的基本的属性值,不需要用一个主题或者样式资源执行样式。方法调用结束后必须调用recycle()方法(返回先前检索的数组),否则这次的设定会对下次的使用造成影响。

看代码。我在代码中的注释应该还算比较清晰的。

package com.demo.lvmanman.custumorviewdeme;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by Lvmanman on 2016/5/19.
 */
public class CustomView extends FrameLayout implements View.OnClickListener {

    private CustomListener customListener = null;

    private Drawable mSrc = null;
    private Drawable mBackgroud = null;
    /**
     * 自定义View中的文本,在此处设置为空,因为使用过程中,会显示xml中设置的text文本,如果xml中没有设置,则View中不显示
     */
    private String mText = "";
    /**
     * 设置文本颜色\文本字体大小,此处可以随便定义,起作用的是xml中的定义,如果在xml中没有定义,则文本颜色显示下面设置的默认颜色
     */
    private int mTextColor = 0;
    private float mTextSize = 0;
    private int mCustomId = 0;
    private ImageView mBackgroudView = null;
    private ImageButton mButtonView = null;
    private TextView mTextView = null;
    private LayoutParams mParams = null;


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

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.custom_view);
        mSrc = a.getDrawable(R.styleable.custom_view_src);
        mBackgroud = a.getDrawable(R.styleable.custom_view_backgroud);
        mText = a.getString(R.styleable.custom_view_text);
        //如果使用该自定义View的xml中没有设定textColor、textSize,则默认显示第二个参数。
        mTextColor = a.getColor(R.styleable.custom_view_textColor, Color.WHITE);
        mTextSize = a.getDimension(R.styleable.custom_view_textSize, 20);
        mCustomId = a.getInt(R.styleable.custom_view_custom_id, 0);

        mTextView = new TextView(context);
        mTextView.setTextSize(mTextSize);
        mTextView.setTextColor(mTextColor);
        mTextView.setText(mText);
        mTextView.setGravity(Gravity.CENTER);
        mTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        mButtonView = new ImageButton(context);
        mButtonView.setImageDrawable(mSrc);
        mButtonView.setBackground(null);
        mButtonView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
        mButtonView.setOnClickListener(this);

        mBackgroudView = new ImageButton(context);
        mBackgroudView.setImageDrawable(mBackgroud);
        mBackgroudView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        addView(mBackgroudView);
        addView(mButtonView);
        addView(mTextView);

        this.setOnClickListener(this);

        a.recycle();

    }

    /**
     * This is called when the view is attached to a window
     */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mParams = (LayoutParams) mButtonView.getLayoutParams();

        if (mParams != null) {
            mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
            mButtonView.setLayoutParams(mParams);
        }

        mParams = (LayoutParams) mBackgroudView.getLayoutParams();
        if (mParams != null) {
            mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
            mBackgroudView.setLayoutParams(mParams);
        }

        mParams = (LayoutParams) mTextView.getLayoutParams();
        if (mParams != null) {
            //决定了文本的位置信息。
            mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
            mTextView.setLayoutParams(mParams);
        }

    }

    public void setCustomListener(CustomListener I) {
        customListener = I;
    }

    @Override
    public void onClick(View v) {
        if (customListener != null) {
            customListener.onCustomClick(v, mCustomId);
        }
    }

    public interface CustomListener {
        void onCustomClick(View v, int custom_id);
    }
}
自定义控件的使用,在使用该自定义控件的xml文件中引用。

通常情况下,我们在给控件设置属性时,常常用到诸如android:layout_width=”wrap_content”的语句,现在设置了自定义的控件属性后,我们也可以使用诸如myself:layout_width=”wrap_content”。实现这一点,我们仅仅需要在使用到该自定义view的布局文件中键入一行:

xmlns:nanlus="http://schemas.android.com/apk/res-auto"
在一篇文章上看到,这句代码的设置是这样的:
xmlns:<span style="color:#FF0000;">myself</span>=http://schemas.android.com/apk/res/<span style="color:#CC33CC;">packagename</span>
红色部分是我们自己定义的属性的前缀名字,紫色部分是项目的包名。

但是,经过我的实际运行,发现在我的程序中这样设置会报错误。如图所示:

即便是不报错误,运行出来的结果也是不对的,错误的运行结果如图所示:

可以看到,系统建议我使用我的那句代码去实现。将我的这个代码也贴下来

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:nanlus="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:orientation="horizontal">


        <com.demo.lvmanman.custumorviewdeme.CustomView
            android:id="@+id/custom1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            nanlus:backgroud="@drawable/backgroud"
            nanlus:src="@drawable/style_button"
            nanlus:custom_id="1"
            nanlus:textColor="#8892fe"
            nanlus:textSize="30sp"
            nanlus:text="自定义文本">


        </com.demo.lvmanman.custumorviewdeme.CustomView>
    </LinearLayout>

</RelativeLayout>
最后就比较简单了,我们将自定义View放在一个Activity里了。那么接下来就是编写Activity的代码了,还是直接看代码吧。 大笑

package com.demo.lvmanman.custumorviewdeme;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements CustomView.CustomListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ((CustomView) this.findViewById(R.id.custom1)).setCustomListener(this);


    }

    @Override
    public void onCustomClick(View v, int custom_id) {
        switch (custom_id) {
            case 1:
                Toast.makeText(this, "hello!!!", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}
到这里,就差不多了,接下来就是最后的运行了,我把运行的界面截图放在这里,比较丑,只是表示了自定义View的实现方式。

结语:

这篇文章特别感谢一下作者编写的文章,对我实现该Demo的功能提供了莫大的帮助,希望也能对大家有所帮助,共同努力,共同成长。程序中如有不正确的地方,希望大家多多指正,在这里先谢谢各位!

http://blog.csdn.net/eyu8874521/article/details/8552534

http://www.jb51.net/article/32172.htm


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值