如何设置 "custom" 选项以查看

How to set "custom" option to View

我正在尝试在 class 中设置扩展 LinearLayout 的选项,在 public 构造函数中使用 (Context , AttributeSet) 我使用 TypedArray 获取属性,话虽如此,我用方法 Builder 创建了一个 class 并且我用 class 将参数设置为 View (在 public 构造函数中) ,好吧,如果我在 setContentView(..) 之前调用 Builder,如果我稍后调用它,我有 NullPointerException.

现在的问题是如何在 设置 布局到 MainActivity 之后将 "attributes" 更改为 View class ?

简单的代码是这样的:

MainActivity 进入 onCreate(..):

MyBuilder.set(new MyBuilder.Builder()
.setParam(...)
.setEtc(...)
.build());

setContentView(...);

MyObject obj = (MyObject) findViewById(R.id.myObject); 
//MyObject.java get param from MyBuilder.java and use it for setup MyObject

//Works!

这是我想要的:

setContentView(...);

//Do various op

MyBuilder.set(new MyBuilder.Builder()
.setParam(...)
.setEtc(...)
.build());

MyObject obj = (MyObject) findViewById(R.id.myObject);

//Params to MyObject is set after setContentView()

//With this flow I get NullPointerException in MyObject.java in reference to MyBuilder.java

现在有效的简单流程说明:

这是我想要的:

这是logcat:

java.lang.RuntimeException: Unable to start activity ComponentInfo{it.michelelacorte.lib/it.michelelacorte.lib.MainActivity}: android.view.InflateException: Binary XML file line #56: Binary XML file line #56: Error inflating class it.michelelacorte.lib.MyObject
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
        at android.app.ActivityThread.access0(ActivityThread.java:157)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5527)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
     Caused by: android.view.InflateException: Binary XML file line #56: Binary XML file line #56: Error inflating class it.michelelacorte.lib.MyObject
        at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
        at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
        at it.michelelacorte.lib.MainActivity.onCreate(MainActivity.java:114)
        at android.app.Activity.performCreate(Activity.java:6272)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
        at android.app.ActivityThread.access0(ActivityThread.java:157) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5527) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 
     Caused by: android.view.InflateException: Binary XML file line #56: Error inflating class it.michelelacorte.lib.MyObject
        at android.view.LayoutInflater.createView(LayoutInflater.java:645)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
        at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256) 
        at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
        at it.michelelacorte.lib.MainActivity.onCreate(MainActivity.java:114) 
        at android.app.Activity.performCreate(Activity.java:6272) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
        at android.app.ActivityThread.access0(ActivityThread.java:157) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5527) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance(Native Method)
        at android.view.LayoutInflater.createView(LayoutInflater.java:619)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
        at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256) 
        at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
        at it.michelelacorte.lib.MainActivity.onCreate(MainActivity.java:114) 
        at android.app.Activity.performCreate(Activity.java:6272) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
        at android.app.ActivityThread.access0(ActivityThread.java:157) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5527) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'float it.michelelacorte.lib.MyBuilder.getRadius()' on a null object reference
        at it.michelelacorte.lib.MyObject.<init>(MyObject.java:90)
        at java.lang.reflect.Constructor.newInstance(Native Method) 
        at android.view.LayoutInflater.createView(LayoutInflater.java:619) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
        at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256) 
        at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
        at it.michelelacorte.lib.MainActivity.onCreate(MainActivity.java:114) 
        at android.app.Activity.performCreate(Activity.java:6272) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
        at android.app.ActivityThread.access0(ActivityThread.java:157) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5527) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 

您可以使用 LayoutInflater class、createView 方法来完成。

方法签名是 createView(name, prefix, attrs) 其中 attrsAttributeSet

的实例

这里有一些关于此方法的简短文档, more about LinearLayout

  • 参数:

    • name 要实例化的 class 的全名。
    • attrs 为此实例提供的 XML 属性。
    • 前缀
  • Returns:

    • 查看新实例化的view,或者为null。
  • 投掷:

    • ClassNotFoundException
    • InflateException

尝试这样使用

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.createView(name, prefix, attrs);

您想在 MainActivity 中使用它,所以我确定您定义 LayoutInflater

时不会出现任何问题

但如果您对此有任何疑问,请对此发表评论 post,我会指导您如何操作。

您使用 setContentView() 设置的 XML 资源包含一个标签 <it.michelelacorte.lib.MyObject .../>。然后在构造函数 MyObject.<init>() 中获取 MyBuilder 的实例并使用它来设置布局。

但是由于您只在设置内容视图后初始化 MyBuilder,所以您只会得到一个 null 实例,因此只有一个 NullPointerException.

而是在 MyObject

中创建一个设置方法
public void setup() {
    MyBuilder builder = MyBuilder.get();
    if (builder != null) {
        // setup view with builder
    } else {
        // setup view defaults
    }
}

处理它并在 onCreate()

中适当地调用它
MyObject obj = (MyObject) findViewById(R.id.myObject);
obj.setup();

和构造函数本身

public MyObject() {
    super(...);
    setup();
}