尝试以编程方式添加视图时应用程序崩溃

Posted

技术标签:

【中文标题】尝试以编程方式添加视图时应用程序崩溃【英文标题】:App crashes when trying to add a view programmatically 【发布时间】:2011-05-14 16:59:44 【问题描述】:

嘿,我不喜欢 android 的 TimePicker(它很大),所以我自己创建了一个,但每次我尝试添加它时,它只会让我的应用程序崩溃。我尝试以相同的方式添加 TimePicker 并且它正在工作。 这是代码,3 个类,内部类创建数字滚动条,第二个类创建一个带有两位数滚动条的时间选择器,一个用于小时,一个用于分钟。第三个类用于应用程序,并创建一组两个时间选择器,一个用于打开时间,一个用于关闭时间。

公共类 openCloseTimesPicker 扩展 LinearLayout 私有 smallTimePicker openTimePicker; 私人 smallTimePicker closeTimePicker;

    public openCloseTimesPicker(Context context) 
        super(context);

        setOrientation(HORIZONTAL);

        setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

        TextView from = new TextView(context);
        TextView until = new TextView(context);

        from.setGravity(Gravity.CENTER_VERTICAL);
        from.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        from.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 25.0f);
        from.setText("מ:");

        until.setGravity(Gravity.CENTER_VERTICAL);
        until.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        until.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 25.0f);
        until.setText("עד:");

        addView(closeTimePicker);
        addView(until);
        addView(openTimePicker);
        addView(from);
    
    public String getOpenHour()
        return openTimePicker.getHour();
    
    public String getCloseHour()
        return closeTimePicker.getHour();
    
    private class smallTimePicker extends LinearLayout
        private digitsScroller minutes;
        private digitsScroller hours;

        public smallTimePicker(Context context) 
            super(context);
            minutes = new digitsScroller(context, 0, 59);
            hours = new digitsScroller(context, 0, 23);

            setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

            setGravity(Gravity.CENTER_HORIZONTAL);

            // Stacks elements vertically
            setOrientation(HORIZONTAL);

            TextView colon = new TextView(context);
            colon.setGravity(Gravity.CENTER_VERTICAL);
            colon.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            colon.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 25.0f);
            colon.setText(':');

            addView(hours);
            addView(colon);
            addView(minutes);

        
        public String getHour()
            return hours.getDigits() + ':' + minutes.getDigits();
        
        private class digitsScroller extends LinearLayout

            private ImageView increase;
            private ImageView decrease;
            private TextView digitDisplay;
            private int minimum, maximum;

            public digitsScroller(Context context, int minimum, int maximum) 
                super(context);

                this.minimum = minimum;
                this.maximum = maximum;

                setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

                setGravity(Gravity.CENTER_HORIZONTAL);

                // Stacks elements vertically
                setOrientation(VERTICAL);

                initializeViews(context);

                addView(increase);
                addView(digitDisplay);
                addView(decrease);
            
            private void initializeViews(Context context) 
                // Layout settings
                LayoutParams childParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

                // Setting the increase button
                increase = new ImageView(context);
                increase.setLayoutParams(childParams);
                increase.setImageResource(R.drawable.add_increase);
                increase.setOnClickListener(new View.OnClickListener() 
                    @Override
                    public void onClick(View v) 
                        // Evaluate whether the digit display may be increased further
                        int currentValue = Integer.valueOf(digitDisplay.getText().toString());
                        currentValue = currentValue < maximum ? currentValue + 1 : minimum;

                        updateDigitValue(currentValue);
                    
                );

                // Setting the decrease button
                decrease = new ImageView(context);
                decrease.setLayoutParams(childParams);
                decrease.setImageResource(R.drawable.add_decrease);
                decrease.setOnClickListener(new View.OnClickListener() 
                    @Override
                    public void onClick(View v) 
                        // Evaluate whether the digit display may be increased further
                        int currentValue = Integer.valueOf(digitDisplay.getText().toString());
                        currentValue = currentValue > minimum ? currentValue - 1 : maximum;

                        updateDigitValue(currentValue);
                    
                );

                // Setting the digits display
                digitDisplay = new TextView(context);
                digitDisplay.setGravity(Gravity.CENTER_HORIZONTAL);
                digitDisplay.setLayoutParams(childParams);
                digitDisplay.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 25.0f);
                digitDisplay.setText('0'+minimum);
            
            private void updateDigitValue(int newValue) 
                digitDisplay.setText((newValue > 9) ? Integer.toString(newValue) : '0'+ Integer.toString(newValue));
                digitDisplay.postInvalidate();
            
            public String getDigits()
                String digits = digitDisplay.getText().toString();
                return (digits.length()>1) ? digits : '0'+digits;
            
        
    

这是将视图添加到布局的代码:

    else if(v.getId() == R.id.add_open_time)
        table.addView(new openCloseTimesPicker(AddShopActivity.this));
    

我再说一遍,当我尝试这样的事情时,它正在工作:

    else if(v.getId() == R.id.add_open_time)
        table.addView(new TimePicker(AddShopActivity.this));
    

这是使用 adb logcat 的日志:

D/AndroidRuntime(  227): Shutting down VM
W/dalvikvm(  227): threadid=3: thread exiting with uncaught exception (group=0x4
001aa28)
E/AndroidRuntime(  227): Uncaught handler: thread main exiting due to uncaught e
xception
E/AndroidRuntime(  227): java.lang.NullPointerException
E/AndroidRuntime(  227):        at android.view.ViewGroup.addView(ViewGroup.java
:1701)
E/AndroidRuntime(  227):        at android.view.ViewGroup.addView(ViewGroup.java
:1688)
E/AndroidRuntime(  227):        at elad.openapp.AddShopActivity$openCloseTimesPi
cker.<init>(AddShopActivity.java:99)
E/AndroidRuntime(  227):        at elad.openapp.AddShopActivity.onClick(AddShopA
ctivity.java:72)
E/AndroidRuntime(  227):        at android.view.View.performClick(View.java:2344
)
E/AndroidRuntime(  227):        at android.view.View.onTouchEvent(View.java:4133
)
E/AndroidRuntime(  227):        at android.widget.TextView.onTouchEvent(TextView
.java:6510)
E/AndroidRuntime(  227):        at android.view.View.dispatchTouchEvent(View.jav
a:3672)
E/AndroidRuntime(  227):        at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:882)
E/AndroidRuntime(  227):        at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:882)
E/AndroidRuntime(  227):        at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:882)
E/AndroidRuntime(  227):        at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:882)
E/AndroidRuntime(  227):        at com.android.internal.policy.impl.PhoneWindow$
DecorView.superDispatchTouchEvent(PhoneWindow.java:1712)
E/AndroidRuntime(  227):        at com.android.internal.policy.impl.PhoneWindow.
superDispatchTouchEvent(PhoneWindow.java:1202)
E/AndroidRuntime(  227):        at android.app.Activity.dispatchTouchEvent(Activ
ity.java:1987)
E/AndroidRuntime(  227):        at com.android.internal.policy.impl.PhoneWindow$
DecorView.dispatchTouchEvent(PhoneWindow.java:1696)
E/AndroidRuntime(  227):        at android.view.ViewRoot.handleMessage(ViewRoot.
java:1658)
E/AndroidRuntime(  227):        at android.os.Handler.dispatchMessage(Handler.ja
va:99)
E/AndroidRuntime(  227):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  227):        at android.app.ActivityThread.main(ActivityThrea
d.java:4203)
E/AndroidRuntime(  227):        at java.lang.reflect.Method.invokeNative(Native
Method)
E/AndroidRuntime(  227):        at java.lang.reflect.Method.invoke(Method.java:5
21)
E/AndroidRuntime(  227):        at com.android.internal.os.ZygoteInit$MethodAndA
rgsCaller.run(ZygoteInit.java:791)
E/AndroidRuntime(  227):        at com.android.internal.os.ZygoteInit.main(Zygot
eInit.java:549)
E/AndroidRuntime(  227):        at dalvik.system.NativeStart.main(Native Method)

I/Process (   44): Sending signal. PID: 227 SIG: 3
I/dalvikvm(  227): threadid=7: reacting to signal 3
E/dalvikvm(  227): Unable to open stack trace file '/data/anr/traces.txt': Permi
ssion denied

谢谢,埃拉德!

【问题讨论】:

当您的应用程序崩溃时,您会遇到什么错误/堆栈跟踪? 如何查看?我刚得到一个FC.. 在 Emulator 运行时从终端运行“adb logcat”,或者如果您在 Eclipse 或其他一些 Android“感知”IDE 中运行,它应该具有某种形式的 logcat 终端。跨度> 我已将日志添加到问题中 【参考方案1】:

在您的 openCloseTimesPicker 构造函数中。 closeTimePickeropenTimePicker 似乎未初始化。

    addView(closeTimePicker);
    addView(until);
    addView(openTimePicker);
    addView(from);

【讨论】:

该死,我是个白痴。它真的很快,发生了什么哈哈。谢谢你,它运作良好。【参考方案2】:

在您发布的代码中,您实际上没有创建 openTimePicker 和 closeTimePicker。我看到了变量声明,但没有调用创建实例。

无需创建它们即可调用

addView(closeTimePicker);

只是将 null 传递给 addView

【讨论】:

该死,我是个白痴。它真的很快,发生了什么哈哈。谢谢你,它运作良好。

以上是关于尝试以编程方式添加视图时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式添加约束会导致崩溃

Xcode 10 - 以编程方式添加按钮时,滚动视图不允许滚动

尝试添加 UInavigationBar 按钮时发生崩溃

以编程方式将 UILabel 添加到自定义 tableViewCell

以编程方式具有自动布局的滚动视图

iOS:以编程方式更改从 Interface Builder 设置的约束