【问题标题】:Android Custom View ConstructorAndroid 自定义视图构造函数
【发布时间】:2011-02-22 11:49:23
【问题描述】:

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

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

描述说:

类初始化 与往常一样, super 被首先调用。此外, 这不是默认构造函数,但是 一个参数化的。 EditText 是 使用这些参数创建时 从 XML 布局文件膨胀, 因此,我们的构造函数需要 把它们传给 超类构造函数也是如此。

有更好的描述吗?我一直在试图弄清楚构造函数应该是什么样子,并且我提出了 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);
} 

【问题讨论】:

标签: xml android custom-view


【解决方案1】:

你不需要第一个,因为那行不通。

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

第四个是错误的,AFAIK。没有将Map 作为第三个参数的View 构造函数。有一个将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
}

您可以在this book example 中查看此代码的其余部分。

【讨论】:

  • super(context, attrs) 和 super(context, attrs, 0) 对我来说工作不同。第一个没问题,但第二个从视图中删除了原始样式。这是新版本 Android 中的错误吗?
  • 是的,我的this() 方法有缺陷。只需对超类(例如,super(context, attrs))做一个简单的链,并在每个构造函数中调用一个公共私有方法(例如,init();)。有关示例,请参见 github.com/commonsguy/cwac-colormixer/blob/master/src/com/…
  • 是的,我做了完全相同的事情,但在第一个构造函数中调用了 this(context, null)。一个缺陷是你必须在两个构造函数中初始化 final 字段——你不能在 init() 方法中这样做。
  • @Brutall:是的,虽然我倾向于在可能的情况下直接在数据成员声明中初始化最终数据成员。
  • @vanleeuwenbram 是的,使用这种方法,应用程序将在运行 Gingerbread 或更低版本的任何设备上崩溃。那是因为super(context, attrs, defStyle); 需要 API 级别 11。为了向后兼容,请改用私有 init() 方法。
【解决方案2】:

这是我的模式(在此处创建自定义 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
    }

}

// view_custom.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Views -->
</merge>

【讨论】:

  • 这不如@CommonsWare 解决方案有效,因为它不允许您将字段标记为“最终”,而使用 this() 调用链会。
  • @greg7gkb 但是@Commonsware 解决方案存在缺陷。您必须调用每个单独的超级并使用 init()
  • 无需将Context传递给init(),调用getContext()即可
【解决方案3】:

当您从 xml 添加自定义 View 时,例如:

 <com.mypack.MyView
      ...
      />

你需要公共构造函数 MyView(Context context, AttributeSet attrs), 否则当Android 尝试inflate 你的View 时你会得到一个Exception

当您从xml 添加您的View指定 android:style attribute 时:

 <com.mypack.MyView
      style="@styles/MyCustomStyle"
      ...
      />

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

第三个构造函数通常在您扩展和自定义样式时使用,然后您想在布局中将 style 设置为给定的 View

编辑详细信息

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);
    }

See this

【讨论】:

  • 我在同一布局中几乎没有自定义视图。如何向构造函数传递一个索引,告诉它它属于哪个自定义视图?
  • 你应该阅读 TypedArray 和 styleable 属性。 stackoverflow.com/questions/11039829/…
  • @Nepstar,我读了那篇文章,但我不明白它将如何解决我的问题,因为据我所知,可样式化属性是在应用程序运行之前定义的静态属性。因此,我的自定义组件的所有实例都将获得相同的数据,而我需要为每个正在运行的组件提供一个唯一的 id。
  • 澄清一下,我的每个组件都是列表的一部分,我需要知道组件在列表中的位置,以及它包含的数据。此外,onClick 不会这样做,因为自定义组件是一个 numberPicker,它会获得很多点击。只有在用户点击SAVE按钮后,我才需要收集每一行的每个numberPicker中的数据。
  • 您应该在您的 customView 中创建一个类似 setIndex 的方法,然后您可以像 (textView.setText("DummyText");101apps.co.za/index.php/articles/creating-custom-views.html 本教程向您展示如何在运行时更改 circleColor(以编程方式)
猜你喜欢
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多