自定义View

Android自定义必输红点

2019-08-21  本文已影响0人  周蛋蛋
image.png

首先看UI给的图形,那个红点,最蠢的方法就是我们写一个TextView在设置一个android:drawablePadding="",但是这样写很不友好,要切图,但是*的话我们直接也可以输入法敲出来,所以还是自定义,以后不管这个点在哪里,我们直接可以用了

第一步:设置属性

在values的文件夹下的attrs.xml中设置属性


image.png
    <declare-styleable name="RequiredTextView">
        <attr name="android:text" />
        <attr name="prefix" format="string|reference" />
        <attr name="prefix_color" format="integer|reference" />
    </declare-styleable>

顺便讲一下属性的意义:

<declare-styleable name="名称">
  <attr name = "background" format="reference" />
</declare-styleable>

 <ImageView
      android:layout_width = "42dp"
      android:layout_height = "42dp"
      android:background = "@drawable/图片ID" />
<declare-styleable name="名称">
  <attr name = "textColor" format="color" />
</declare-styleable>

<TextView
      android:layout_width = "42dp"
      android:layout_height = "42dp"
      android:textColor = "#ABABAB" />
<declare-styleable name="名称">
  <attr name = "focusable" format="boolean" />
</declare-styleable>
<TextView
      android:layout_width = "42dp"
      android:layout_height = "42dp"
      android:focusable = "true" />
<declare-styleable name = "MapView">
    <attr name = "apiKey" format = "string" />
</declare-styleable>

<com.google.android.maps.MapView
   android:layout_width = "fill_parent"
   android:layout_height = "fill_parent"
   android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g" />

属性定义时可以指定多种类型值。

<declare-styleable name = "名称">
  <attr name = "background" format = "reference|color" />
</declare-styleable>
<ImageView
  android:layout_width = "42dip"
  android:layout_height = "42dip"
  android:background = "@drawable/图片ID|#00FF00" />

基本上我们就先介绍常用的这几个

第二步:自定义TextView

public class RequiredTextView extends android.support.v7.widget.AppCompatTextView {
    private String prefix = "*";
    private int prefixColor = Color.RED;

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

    public RequiredTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }


    public RequiredTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    /**
     * @param context
     * @param attrs   获取属性的集合
     * SPAN_EXCLUSIVE_INCLUSIVE 不包前包后
     */
    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RequiredTextView);
        prefixColor = typedArray.getInteger(R.styleable.RequiredTextView_prefix_color, Color.RED);
        String text = typedArray.getString(R.styleable.RequiredTextView_android_text);
        prefix = typedArray.getString(R.styleable.RequiredTextView_prefix);
        if (TextUtils.isEmpty(prefix)) prefix = "*";
        if (TextUtils.isEmpty(text)) text = "";
        typedArray.recycle();
        setText(text+prefix);

    }
    public void setText(String texts) {
        SpannableString spannableString = new SpannableString(texts);
        spannableString.setSpan(new ForegroundColorSpan(prefixColor), texts.length()-1,texts.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
        setText(spannableString);
    }
}

android开发者网站上有相关的说明文档:
public View (Context context)是在java代码创建视图的时候被调用,如果是从xml填充的视图,就不会调用这个
public View (Context context, AttributeSet attrs)这个是在xml创建但是没有指定style的时候被调用
public View (Context context, AttributeSet attrs, int defStyle)给View提供一个基本的style,如果我们没有对View设置某些属性,就使用这个style中的属性。


image.png

现在你知道为啥我们在自己定义View的时候至少要重写(Context context, AttributeSet set)构造器了吧?因为不重写时,我们将无法获取到layout中配置的属性!!当然,也因为这样,LayoutInflater在inflater布局时会通过反射去调用View的(Context context, AttributeSet attrs)构造器。
set 中实际上又有两种数据来源,当然最后都会包含在set中。一种是直接使用android:layout_width="wrap_content"这种直接指定的,还有一种是通过style="@style/somestyle"这样指定的。


也是自定义一个可以在Theme中配置的样式的关键,先看个栗子吧:
如果我想通过在系统主题里面设置一个样式,修改所有textview的样式,你一般会这么做:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    //在主题中设置textview的style
    <item name="android:textViewStyle">@style/textviewstyle</item>
</style>

<style name="textviewstyle" parent="android:style/Widget.TextView">
    <!--指定一些属性-->
</style>

 public TextView(Context context, AttributeSet attrs) {
    //指定属性textViewStyle为defStyleAttr,然后系统会去搜索Theme中你为这个
    //属性配置的style
    this(context, attrs, com.android.internal.R.attr.textViewStyle);
  }

上一篇 下一篇

猜你喜欢

热点阅读