仅在针对API 19运行时片段中的Elusive NullPointerException(18个工作正常。)

时间:2014-07-22 18:27:38

标签: android android-fragments

我在调试/运行API 19设备时遇到异常。问题是难以捉摸的,我无法确定原因。项目的目标sdk为19,最小sdk为11.当对抗18岁及以下时,一切正常。我没有API级别19的配置限定符。我可以采取哪些步骤来确定确切原因?

修改 问题在于Spinner TextViews的膨胀方式,详见我的答案。

LogCat结果:

07-22 13:42:48.145: E/AndroidRuntime(1628): FATAL EXCEPTION: main
07-22 13:42:48.145: E/AndroidRuntime(1628): Process: com.example.android.abl, PID: 1628
07-22 13:42:48.145: E/AndroidRuntime(1628): java.lang.NullPointerException
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.TextView.makeNewLayout(TextView.java:6113)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.TextView.onMeasure(TextView.java:6408)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.Spinner.setUpChild(Spinner.java:632)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.Spinner.makeView(Spinner.java:585)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.Spinner.getBaseline(Spinner.java:431)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1262)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:590)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1226)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.ScrollView.onMeasure(ScrollView.java:326)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1456)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.View.measure(View.java:16497)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1916)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1113)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1295)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.Choreographer.doFrame(Choreographer.java:544)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.os.Handler.handleCallback(Handler.java:733)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.os.Handler.dispatchMessage(Handler.java:95)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.os.Looper.loop(Looper.java:136)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at android.app.ActivityThread.main(ActivityThread.java:5017)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at java.lang.reflect.Method.invokeNative(Native Method)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at java.lang.reflect.Method.invoke(Method.java:515)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
07-22 13:42:48.145: E/AndroidRuntime(1628):     at dalvik.system.NativeStart.main(Native Method)

活动:

public class LogEntryPagerActivity extends ActionBarActivity {
    private ViewPager mViewPager;
    private Project mProject;

    public static final String TAG = "LogEntryPagerActivity";

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);

         // view created from id resource instead of xml layout. 
         mViewPager = new ViewPager(this);
         mViewPager.setId(R.id.logViewPager);
         setContentView(mViewPager);

        mProject = ABL.get(this).getActiveProject();

        FragmentManager fm = getSupportFragmentManager();

        mViewPager.setAdapter(new FragmentStatePagerAdapter(fm){
            @Override
            public Fragment getItem(int position) {
                LogEntry le = mProject.getLogEntries().get(position);
                return LogEntryFragment.newInstance(le.getLogEntryId());
            }
            @Override
            public int getCount() {
                return mProject.getLogEntries().size();
            }           
        });


    }   

}

片段:

public class LogEntryFragment extends Fragment {

    public static final String DIALOG_DATE ="dialogdate";
    private static final int REQUEST_DATE = 5534;
    private static final String KEY_ACTIVE_LOGENTRY = "activelogentryid";

    private LogEntry mLogEntry;
    private EditTextPlus mEtDate;
    private Spinner mSpinnerTag;
    private EditTextPlus mEtHour;
    private EditTextPlus mEtMin;
    private EditTextPlus mEtSummary;
    private EditTextPlus mEtDetail;
    private TextView mSubtitleTextView;

    private Spinner mSpinnerVisibility;

    private int mActiveLogEntryId;

    public static LogEntryFragment newInstance(int id){
        Bundle args = new Bundle();
        args.putInt(AppUtil.EXTRA_LOGENTRY_ID, id);

        LogEntryFragment frag = new LogEntryFragment();
        frag.setArguments(args);
        return frag;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_ACTIVE_LOGENTRY, mActiveLogEntryId);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_logentry, menu);
    }   

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // set title
        getActivity().setTitle(ABL.get(getActivity()).getActiveProject().getName());

        setHasOptionsMenu(true);

        // get needed extra
        int id = getArguments().getInt(AppUtil.EXTRA_LOGENTRY_ID, 0);

        if(savedInstanceState != null){
            mActiveLogEntryId = savedInstanceState.getInt(KEY_ACTIVE_LOGENTRY, 0);
            id = mActiveLogEntryId;
        }

        // find existing entry and set local variable
        Project activeProject = ABL.get(getActivity()).getActiveProject();      
        mLogEntry = activeProject.getLogEntry(id);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View rootView = inflater.inflate(R.layout.fragment_logentry, container, false);

        // if the manifest has parent activity data then enable the up button
        if(NavUtils.getParentActivityIntent(getActivity()) != null){
            // enable app icon as a button and display caret (this does not wire the button)
            ((ActionBarActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);           
        }

        mSubtitleTextView = (TextView)rootView.findViewById(R.id.logentry_subtitle);
        updateSubtitle();

        mEtDate = (EditTextPlus)rootView.findViewById(R.id.logentry_date);
        updateDate();

        mSpinnerTag = (Spinner)rootView.findViewById(R.id.logentry_tag);
        loadTagData();
        setSpinnerTagSelected();
        wireTagListeners();

        // time (hour and minute)
        mEtHour = (EditTextPlus)rootView.findViewById(R.id.logentry_hour);
        mEtHour.addTextChangedListener(new GenericTextWatcher(mEtHour));

        mEtMin = (EditTextPlus)rootView.findViewById(R.id.logentry_minute);
        mEtMin.addTextChangedListener(new GenericTextWatcher(mEtMin));

        if(mLogEntry.getTimeHour()>0){
            mEtHour.setText(String.valueOf(mLogEntry.getTimeHour()));
        }
        if(mLogEntry.getTimeMin()>0){
            mEtMin.setText(String.valueOf(mLogEntry.getTimeMin()));
        }

        mEtSummary = (EditTextPlus)rootView.findViewById(R.id.logentry_summary);
        mEtSummary.setText(mLogEntry.getSummary());
        mEtSummary.addTextChangedListener(new GenericTextWatcher(mEtSummary));

        mEtDetail = (EditTextPlus)rootView.findViewById(R.id.logentry_detail);
        mEtDetail.setText(mLogEntry.getDetail());
        mEtDetail.addTextChangedListener(new GenericTextWatcher(mEtDetail));

        mSpinnerVisibility = (Spinner)rootView.findViewById(R.id.logentry_visiblity);
        loadVisiblityData();
        setSpinnerVisibilityCodeSelected();
        wireVisibilityCodeListeners();

        ImageButton calendarButton = (ImageButton)rootView.findViewById(R.id.logentry_calendar_btn);
        calendarButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                DatePickerFragment dialog = DatePickerFragment.newInstance(mLogEntry.getDate());
                // set outer class instance (Fragment) as target
                dialog.setTargetFragment(LogEntryFragment.this, REQUEST_DATE);
                dialog.show(fm, DIALOG_DATE);
            }
        });

        return rootView;
    }

    private void wireVisibilityCodeListeners(){
        mSpinnerVisibility.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String visCode = ((SpinnerAdapterVisibility)parent.getAdapter()).getCodeFromIndex(position);
                mLogEntry.setVisibilityCode(visCode);               
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                //
            }
        });
    }

    private void wireTagListeners(){
        mSpinnerTag.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                int tagId = ((SpinnerAdapterTag)parent.getAdapter()).getIdFromIndex(position);
                mLogEntry.setPrimaryTag(tagId);
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                //              
            }
        });
    }

    private void setSpinnerTagSelected(){
        if(mLogEntry.getPrimaryTag()==0){
            mSpinnerTag.setSelection(8);
        }
        SpinnerAdapterTag t = (SpinnerAdapterTag)mSpinnerTag.getAdapter();
        int position = t.getIndexById(mLogEntry.getPrimaryTag());
        mSpinnerTag.setSelection(position);
    }

    private void setSpinnerVisibilityCodeSelected(){
        SpinnerAdapterVisibility v = (SpinnerAdapterVisibility)mSpinnerVisibility.getAdapter();
        int position = v.getIndexByCode(mLogEntry.getVisibilityCode());
        mSpinnerVisibility.setSelection(position);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
        case android.R.id.home:
            // meta data defined in manifest for parent activity
            if(NavUtils.getParentActivityIntent(getActivity()) != null){
                NavUtils.navigateUpFromSameTask(getActivity());
            }
            return true;
        case R.id.menu_item_logentry_camera:
            Intent ii = new Intent(getActivity(), Camera1Activity.class);
            startActivityForResult(ii, 0);
            return true;                
        default:
            return super.onOptionsItemSelected(item);               
        }
    }



    // return from date dialog
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode != Activity.RESULT_OK) return;
        if (requestCode == REQUEST_DATE){
            Date dt = (Date)data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
            mLogEntry.setDate(dt);
            updateDate();
        }
    }

    public void updateDate(){
        mEtDate.setText(getDisplayDate());
    }

    public String getDisplayDate(){
        DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getActivity().getApplicationContext());
        return dateFormat.format(mLogEntry.getDate());      
    }

    public void updateSubtitle(){
        if(mLogEntry.getLogEntryId()>0){
            mSubtitleTextView.setText(getString(R.string.logentry_title_existing_notext) + " ");        
        }else{
            mSubtitleTextView.setText(R.string.logentry_title_new);
        }       
    }

    public void loadVisiblityData(){
        // mSpinnerVisibility
        List<VisibilityCode> visibilityCodes = AppUtil.getVisibilityCodes();        
        //List<VisibilityCode> visibilityCodes = db.getBuildTypes();
        SpinnerAdapterVisibility adapterVisiblity = new SpinnerAdapterVisibility(getActivity(), (ArrayList<VisibilityCode>) visibilityCodes);
        mSpinnerVisibility.setAdapter(adapterVisiblity);        
    }

    public void loadTagData(){
        // database handler
        DatabaseHandler db = DatabaseHandler.getInstance(getActivity());
        // makes
        List<Tag> tags = db.getTags(getActivity());
        SpinnerAdapterTag adapterTag = new SpinnerAdapterTag(getActivity(), (ArrayList<Tag>) tags);
        mSpinnerTag.setAdapter(adapterTag);
    }

    @Override
    public void onPause() {
        super.onPause();
        saveLogEntry();
    }

    public void saveLogEntry(){
        if(mLogEntry.save(getActivity())){
            // success
            mActiveLogEntryId = mLogEntry.getLogEntryId();
        }else{
            // fail to save
            Toast.makeText(getActivity(), getString(R.string.new_save_fail_temp), Toast.LENGTH_SHORT).show();                   
        }
    }



    protected boolean isNumeric(EditText editText) {
        String text = editText.getText().toString().trim();
        Boolean isnum = false;
        int value = 0;
        try{
            value = Integer.parseInt(text);
            isnum = true;
        }catch (NumberFormatException e){
            isnum = false;
        }
        return isnum;
    }

    // inner TextWatcher
    private class GenericTextWatcher implements TextWatcher{
        private View view;
        private GenericTextWatcher(View view) {
            this.view = view;
        }
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        public void afterTextChanged(Editable editable) {
            String text = editable.toString();
            switch(view.getId()){
                case R.id.logentry_date:
                    //isValidDate(mEtDate);
                    break;
                case R.id.logentry_hour:
                    //validateHour(mEtHour);
                    break;
                case R.id.logentry_minute:
                    //validateMinute(mEtMin);
                    break;
                case R.id.logentry_summary:
                    mLogEntry.setSummary(text);
                    break;
                case R.id.logentry_detail:
                    mLogEntry.setDetail(text);
                    break;  
            }
        }
    }


}

片段布局

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res/com.example.android.abl" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" >
<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:padding="8dp" 
    android:orientation="vertical" >

    <TextView 
        android:id="@+id/logentry_subtitle" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/logentry_title_new" 
        style="?android:listSeparatorTextViewStyle" />

    <LinearLayout
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginLeft="8dp" 
        android:orientation="horizontal">           
        <TextView 
            android:layout_weight="30"  
            android:layout_width="0dp" 
            android:layout_gravity="center_vertical" 
            android:layout_height="wrap_content" 
            android:text="@string/logentry_date_label" 
            android:textSize="@dimen/dx_textview_label_textsize" />
        <LinearLayout 
            android:layout_weight="70" 
            android:layout_width="0dp" 
            android:layout_height="wrap_content" 
            android:orientation="horizontal"> 
            <com.example.android.abl.EditTextPlus android:id="@+id/logentry_date" 
                android:layout_weight="1"  
                android:layout_width="0dp"  
                android:layout_height="wrap_content"  
                android:inputType="date" 
                android:imeOptions="actionNext"             
                android:hint="@string/logentry_date_hint" 
                android:textColorHint="@color/hintlight" 
                app:errMessage="@string/err_default" />     
            <ImageButton android:id="@+id/logentry_calendar_btn" 
                android:layout_weight="0" 
                android:layout_width="40dp" 
                android:layout_height="40dp" 
                android:contentDescription="@string/calendar" 
                android:src="@drawable/ic_menu_today" />  
        </LinearLayout> 
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginLeft="8dp" 
        android:orientation="horizontal">
        <TextView  
            android:layout_weight="30"  
            android:layout_width="0dp"          
            android:layout_height="wrap_content" 
            android:layout_gravity="center_vertical" 
            android:text="@string/logentry_tag_label" 
            android:textSize="@dimen/dx_textview_label_textsize" />
        <Spinner  
            android:id="@+id/logentry_tag" 
            android:layout_weight="70"  
            android:layout_width="0dp"          
            android:layout_height="wrap_content"
            android:focusable="true" 
            android:focusableInTouchMode="true" 
            android:inputType="text" 
            android:imeOptions="actionNext" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginLeft="8dp" 
        android:orientation="horizontal">
        <TextView  
            android:layout_weight="30"  
            android:layout_width="0dp"          
            android:layout_height="wrap_content" 
            android:layout_gravity="center_vertical" 
            android:text="@string/logentry_time_label" 
            android:textSize="@dimen/dx_textview_label_textsize" />
        <LinearLayout
            android:layout_weight="70"  
            android:layout_width="0dp" 
            android:layout_height="wrap_content" 
            android:orientation="horizontal">
            <com.example.android.abl.EditTextPlus android:id="@+id/logentry_hour" 
                android:layout_width="wrap_content"        
                android:layout_height="wrap_content" 
                android:inputType="number" 
                android:imeOptions="actionNext"             
                android:hint="@string/logentry_hour_hint" 
                android:textColorHint="@color/hintlight"
                android:ems="2" 
                android:maxLength="2" 
                app:errMessage="@string/err_num_only" />
            <TextView  
                android:layout_width="wrap_content"        
                android:layout_height="wrap_content" 
                android:text="@string/logentry_hour_label" 
                android:layout_marginRight="16dp"
                android:textSize="@dimen/dx_textview_label_textsize" />
            <com.example.android.abl.EditTextPlus android:id="@+id/logentry_minute" 
                android:layout_width="wrap_content"        
                android:layout_height="wrap_content" 
                android:inputType="number" 
                android:imeOptions="actionNext"             
                android:hint="@string/logentry_minute_hint" 
                android:textColorHint="@color/hintlight" 
                android:ems="2" 
                android:maxLength="2" 
                app:errMessage="@string/err_num_only" />
            <TextView  
                android:layout_width="wrap_content"        
                android:layout_height="wrap_content" 
                android:text="@string/logentry_minute_label"  
                android:textSize="@dimen/dx_textview_label_textsize" />                     
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent" 
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:paddingLeft="8dp" >
        <TextView 
            android:layout_weight="30" 
            android:layout_width="0dp"          
            android:layout_height="wrap_content" 
            android:layout_gravity="center_vertical"  
            android:text="@string/logentry_visiblity"  
            android:textSize="@dimen/dx_textview_label_textsize" />        
        <Spinner  
            android:id="@+id/logentry_visiblity" 
            android:layout_weight="70"  
            android:layout_width="0dp"       
            android:layout_height="wrap_content" 
            android:focusable="true" 
            android:focusableInTouchMode="true"  
            android:inputType="text" 
            android:imeOptions="actionDone" />          
    </LinearLayout>

    <LinearLayout           
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:orientation="vertical">

        <com.example.android.abl.EditTextPlus android:id="@+id/logentry_summary" 
            android:layout_width="match_parent"    
            android:layout_height="wrap_content"  
            android:inputType="text" 
            android:imeOptions="actionNext"          
            android:hint="@string/logentry_summary_hint" 
            android:textColorHint="@color/hintlight" 
            android:maxLength="120"  
            app:errMessage="@string/err_default" />

        <com.example.android.abl.EditTextPlus android:id="@+id/logentry_detail" 
            android:layout_width="match_parent"  
            android:layout_height="wrap_content" 
            android:inputType="textMultiLine" 
            android:lines="6" 
            android:minLines="4"  
            android:maxLines="10" 
            android:gravity="top|left"  
            android:scrollbars="vertical" 
            android:imeOptions="actionNext"  
            android:hint="@string/logentry_details_hint"  
            android:textColorHint="@color/hintlight" 
            android:maxLength="2000"  
            app:errMessage="@string/err_default" />
    </LinearLayout>

</LinearLayout>
</ScrollView>

上面布局中出现的EditTextPlus小部件

public class EditTextPlus extends EditText {
    public String errMessage;
    private ArrayList<TextWatcher> mListeners = null;

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

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

    public EditTextPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }
    private void init(AttributeSet attrs) {
        if (attrs!=null) {
             TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.EditTextPlus);
             String eMsg = a.getString(R.styleable.EditTextPlus_errMessage);
             if (eMsg!=null) {
                 errMessage = eMsg;
             }
             a.recycle();
        }
    }

    @Override
    public void addTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners == null) 
        {
            mListeners = new ArrayList<TextWatcher>();
        }
        mListeners.add(watcher);
        super.addTextChangedListener(watcher);
    }

    @Override
    public void removeTextChangedListener(TextWatcher watcher)
    {       
        if (mListeners != null) 
        {
            int i = mListeners.indexOf(watcher);
            if (i >= 0) 
            {
                mListeners.remove(i);
            }
        }
        super.removeTextChangedListener(watcher);
    }   

    public void clearTextChangedListeners()
    {
        if(mListeners != null)
        {
            for(TextWatcher watcher : mListeners)
            {
                super.removeTextChangedListener(watcher);
            }
            mListeners.clear();
            mListeners = null;
        }
    }   

}

1 个答案:

答案 0 :(得分:3)

为碰巧遇到它的其他人回答我自己的问题。

在附加SDK源之后,我能够确定API 19(4.4)更加特别关于我的Spinner TextViews被夸大的方式。就我而言,我正在使用:

TextView textview = (TextView) inflater.inflate(android.R.layout.simple_spinner_item, null);

正确的方法是:

TextView textview = (TextView) inflater.inflate(android.R.layout.simple_spinner_item, parent, false);