Android自定义视图构造函数

Mit*_*tch 34 xml android custom-view

我正在学习如何使用以下自定义视图:

http://developer.android.com/guide/topics/ui/custom-components.html#modifying

描述说:

类初始化与往常一样,首先调用super.此外,这不是默认构造函数,而是参数化构造函数.当EditText从XML布局文件中膨胀时,会使用这些参数创建EditText,因此,我们的构造函数需要同时接受它们并将它们传递给超类构造函数.

有更好的描述吗?我一直试图弄清楚构造函数应该是什么样子,我想出了4种可能的选择(参见帖子末尾的例子).我不确定这4个选择是做什么(或不做什么),为什么要实现它们,或者参数是什么意思.有这些的描述吗?

public MyCustomView()
{
    super();
}

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

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

public MyCustomView(Context context, AttributeSet attrs, Map params)
{
    super(context, attrs, params);
} 
Run Code Online (Sandbox Code Playgroud)

Com*_*are 66

你不需要第一个,因为它不起作用.

第三个意味着您的自定义View将可用于XML布局文件.如果你不关心它,你不需要它.

第四个是错的,AFAIK.没有View构造函数将a Map作为第三个参数.有一个int作为第三个参数,用于覆盖窗口小部件的默认样式.

我倾向于使用this()语法来组合这些:

public ColorMixer(Context context) {
    this(context, null);
}

public ColorMixer(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public ColorMixer(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // real work here
}
Run Code Online (Sandbox Code Playgroud)

您可以在本书的示例中看到此代码的其余部分.

  • 是的,我的`this()`方法有缺陷.只需对超类执行一个简单的链(例如,`super(context,attrs)`)并在每个构造函数中调用一个公共私有方法(例如,`init();`).有关示例,请参阅https://github.com/commonsguy/cwac-colormixer/blob/master/src/com/commonsware/cwac/colormixer/ColorMixer.java. (9认同)
  • super(context,attrs)和super(context,attrs,0)对我来说差异化.第一个是好的,但第二个从视图中删除原始样式.这是Android的新版本中的错误吗? (7认同)

yan*_*nko 11

这是我的模式(ViewGoup在这里创建一个自定义,但仍然):

// CustomView.java

public class CustomView extends LinearLayout {

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

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

    public CustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context ctx) {
        LayoutInflater.from(ctx).inflate(R.layout.view_custom, this, true);
            // extra init
    }

}
Run Code Online (Sandbox Code Playgroud)

// view_custom.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Views -->
</merge>
Run Code Online (Sandbox Code Playgroud)

  • @ greg7gkb然而@Commonsware解决方案存在缺陷.你必须调用每个单独的super并使用`init()` (3认同)

Xar*_*mer 7

当您View从以下位置添加自定义时xml :

 <com.mypack.MyView
      ...
      />
Run Code Online (Sandbox Code Playgroud)

你将需要公共构造 MyView(Context context, AttributeSet attrs),否则你将得到一个ExceptionAndroid尝试inflate你的View.

而当你添加Viewxml,也说明android:style attribute这样的:

 <com.mypack.MyView
      style="@styles/MyCustomStyle"
      ...
      />
Run Code Online (Sandbox Code Playgroud)

你还需要第三个公共构造函数 MyView(Context context, AttributeSet attrs,int defStyle).

第三个构造函数通常在扩展样式并自定义时使用,然后您希望将其设置styleView布局中的给定样式

编辑细节

public MyView(Context context, AttributeSet attrs) {
            //Called by Android if <com.mypack.MyView/> is in layout xml file without style attribute.
            //So we need to call MyView(Context context, AttributeSet attrs, int defStyle) 
            // with R.attr.customViewStyle. Thus R.attr.customViewStyle is default style for MyView.
            this(context, attrs, R.attr.customViewStyle);
    }
Run Code Online (Sandbox Code Playgroud)

看到这个