【问题标题】:Passing values to custom view in android将值传递给android中的自定义视图
【发布时间】:2015-05-12 15:39:55
【问题描述】:

干杯,

我有一个接收用户输入(2 个数字,宽度和高度)的应用程序,理论上,根据该输入,我有一个自定义视图,应该绘制一个网格(宽度和高度)。

注意:

  • 这 2 个值应在视图尝试绘制自身之前接收。
  • 这两个值不是常数,因此我认为 XML 方法没有帮助。
  • 有人告诉我,向 View 构造函数添加另一个参数是邪恶的。
  • 不要将我的 2 个值与 canvas.getWidth 等混淆。这些值仅用于绘制某些内容,仅此而已。
  • My View 也是一个 ViewGroup。
  • 主要问题在于 XML 文件中声明的视图。

我通过创建一个包含这 2 个静态值的 SchemeContext 类暂时解决了这个问题,我只是将它们设置在 onCreate 中(在 onCreateView 之前),然后在需要时在自定义 View onDraw 中使用它们(SchemeContext.width)。这不是人们所说的 OOP 我在 java 上强制使用全局变量,并且由于片段生命周期而按时设置。

我已经看到了这个答案How to pass variables to custom View before onDraw() is called?

但这更像是一种变通方法,而不是一种解决方案(而且可能不是最快的解决方案)。必须有一个明智的解决方案,我不认为 android 上的 3D 游戏采用这些变通方法(使用 OpenGL 的 SurfaceView 仍然是 View 对吗?:d)。

如果有一个明显的解决方案并且这是一个明显的双重问题,我会删除这个问题。

【问题讨论】:

  • 在您的自定义视图中使用方法 setValues(int width, int height) 有什么问题?在setValues(...) 中分配这些值后,调用 invalidate()`。
  • 为什么添加构造函数是邪恶的?如果您不想这样做,为什么不在将视图添加到其容器之前添加设置值?
  • @Vikram 每个对象在其构造函数返回时都应该是有效的。
  • vikram:因为我认为这是通过视图组树的额外传递。也许它在小应用程序中吹毛求疵,但我认为这可能会导致问题。
  • @KevinKrumwiede 请解释一下。

标签: android android-custom-view


【解决方案1】:

我还没有尝试过,但我认为通过覆盖LayoutInflater.Factory 可以相当干净地做到这一点。这样,您可以拦截需要将额外参数传递给其构造函数的视图的创建,并让其余的视图陷入默认膨胀。

例如,在您的活动中,在您膨胀视图层次结构之前:

LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
MyInflaterFactory factory = new MyInflaterFactory();
// Pass information needed for custom view inflation to factory.
factory.setCustomValue(42);
inflater.setFactory(factory);

对于您的工厂实现:

class MyInflaterFactory implements LayoutInflater.Factory {
    public void setCustomValue(int val) {
        mCustomVal = val;
    }

    @Override
    public View onCreateView (String name, Context context, AttributeSet attrs) {
        if (name.equals("com.package.ViewWithCustomCreation")) {
            return new ViewWithCustomCreation(context, attrs, mCustomVal);
        }
        return null;
    }

    private int mCustomVal;
}

【讨论】:

  • 我不应该写这个。但是,它真棒 o_o
  • 看起来很有趣,我会试一试,然后报告效果如何。
【解决方案2】:

有人告诉我,向 View 构造函数添加另一个参数是邪恶的。

废话。

共有三个(在最新的 API 中为四个)不同的 View 构造函数,每个构造函数用于不同的情况。 (请参阅this thread。)例如,如果您希望能够在 XML 中声明您的视图,那么您必须提供一个具有完全正确参数的构造函数,并让它调用相应的超类构造函数。但是定义你自己的构造函数(甚至其中的几个)并调用超类构造函数来以编程方式创建视图并没有错。

最重要的原则是每个对象在其构造函数返回时必须是有效的。因此,除非您可以在构造函数中提供合理的默认值,否则您别无选择,只能接受对象的属性作为构造函数参数。

【讨论】:

  • 我可能会同意你在 java 中创建的视图。但是在 XML 中声明的视图或视图组的问题仍然存在,我不能说不应该在 XML 中声明自定义元素,因为它已经成为可能。
  • @Spidey 这个答案无法证明开发人员希望子类构造函数与超类构造函数具有完全相同的参数这一相当大胆的说法是正确的。我说的是在代码中创建的视图。
  • 对于 java 编码的视图,你是对的。我仍然有 XML 部分的问题。
  • @Spidey 我以为你说你不能使用 XML,因为参数来自运行时的用户。如果要允许在 XML 中声明,则必须提供一个构造函数,该构造函数接受 ContextAttributeSet,仅此而已。有关如何创建自定义属性,请参阅 this answer
  • 我的参数确实来自运行时的用户,我的具体情况是我创建了一个自定义视图组,我在 XML 中声明它用 DrawerLayout 包装它。这是不好的做法,因为我不明白为什么(除了传递不便的价值)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 2011-04-11
相关资源
最近更新 更多