1
我在調試/運行API 19設備時遇到異常。問題難以捉摸,我無法確定原因。該項目的目標sdk爲19,min sdk爲11.在18以下運行時,一切正常。我沒有針對API級別19的配置限定符。我可以採取哪些步驟來確定確切原因?只有在針對API 19運行時纔會出現Elusive NullPointerException異常(18可以正常工作。)
編輯 問題在於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>
,上面的佈局出現在
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;
}
}
}
偉大的發現,我想知道爲什麼它會抱怨..到底怎麼你看着辦吧?只是突破點,並非常痛苦地通過它? – reidisaki
@reidisaki,謝謝。是鉤住sdk來源找到細節,然後尋找異常導致膨脹snafu。 –