2016-08-04 35 views
-2

Ich erstellte eine benutzerdefinierte Ansicht, die PinView von RelativeLayout erweitert. In Konstruktoren rufe ich meine Methode init() auf und bläht eine Ansicht aus einem Layout auf.Warum können wir eine Ansicht in customview nicht aufblähen, während diese customview initialisiert wird?

inflate(getContext(), R.layout.layout_pin_view, this); 

Nach diesem aufblasen fließen, ich brauche meine andere Ansichten (Bildansicht) in dieser aufgeblasenen Ansicht hinzufügen, indem addView anfordernden(). Und wirft:

catch (NoSuchMethodException e) { 
      InflateException ie = new InflateException(attrs.getPositionDescription() 
        + ": Error inflating class " 
        + (prefix != null ? (prefix + name) : name)); 
      ie.initCause(e); 
      throw ie; 

kann ich aufblasen successly mit:

mLlPins.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 
       mLlPins.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       .... 
       .... 
       addView(...) 



      } 
     }); 

Haben Sie eine Idee, warum wir eine dynamische Ansicht mit Aufblasen in synchron schaffen kippen?

Meine Code-Teile: (sagt als Container)

private void init() { 
    View view = inflate(getContext(), R.layout.layout_pin_view, this); 
    mEtPin = (PinEditText) view.findViewById(R.id.etPin); 
    mLlPins = (LinearLayout) view.findViewById(R.id.llPins); 
    mEtPin.setVisibility(View.VISIBLE); 
    mEtPin.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)}); 
    mEtPin.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      return false; 
     } 
    }); 
    mEtPin.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 

     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      if (mImageViews != null) { 
       for (int i = 0; i < mImageViews.length; i++) 
        mImageViews[i].setEnabled(i < s.length()); 
       if (s.length() == mMaxLength) { 
        InputMethodManager imm = (InputMethodManager) mEtPin.getContext().getSystemService(
          Context.INPUT_METHOD_SERVICE); 
        imm.hideSoftInputFromWindow(mEtPin.getWindowToken(), 0); 
       } 
      } 
     } 
    }); 
    mLlPins.setClickable(false); 
    mEtPin.setText(mEtPin.getText()); 

    mEtPin.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 

     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      if (mImageViews == null) return; 
      for (int i = 0; i < mMaxLength; i++) { 
       if (mImageViews[i] != null) { 
        if (i < s.length()) { 
         mImageViews[i].setImageAlpha(255); 
         continue; 
        } 
       } 
       mImageViews[i].setImageAlpha(0); 
      } 

     } 
    }); 

    setMaxLength(4); 
} 
private void setMaxLength(int maxLength) { 
    LayoutInflater inflater = LayoutInflater.from(mLlPins.getContext()); 
    mMaxLength = maxLength; 
    mEtPin.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); 
    mImageViews = new ImageView[maxLength]; 
    mLlPins.removeAllViews(); 
    int totalContentLenght = mLlPins.getMeasuredWidth() - dpToPx((maxLength - 1) * mMargin); 
    int itemWidthHeight = totalContentLenght/maxLength; 
    int itemMargin = dpToPx(mMargin/2); 
    int itemPadding = (int) (itemWidthHeight * srcRatio); 
    for (int i = 0; i < maxLength; i++) { 
     mImageViews[i] = (ImageView) inflater.inflate(mPinImage, null); 
     mImageViews[i].setEnabled(false); 
     mImageViews[i].setPadding(itemPadding, itemPadding, itemPadding, itemPadding); 
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(itemWidthHeight, itemWidthHeight); 
     if (i == 0) { 
      params.setMargins(0, 0, itemMargin, 0); 
     } else if (i < maxLength - 1) { 
      params.setMargins(itemMargin, 0, itemMargin, 0); 
     } else { 
      params.setMargins(itemMargin, 0, 0, 0); 

     } 
     mImageViews[i].setImageAlpha(0); 
     mLlPins.addView(mImageViews[i], params); 

    } 

} 
+1

Bitte posten Sie Ihre Konstrukteure und 'init()' Methode und die Stack-Trace von der gefangenen 'Ausnahme'. –

+1

Ahh! Es ist meine Schuld. Ich habe das Problem gefunden, während ich versuche, Protokolle zu bekommen. In Activity wird diese Aktivität nach dem Erstellen durch einige Steuerelemente geschlossen. Wenn ich diesen Prozess debugge, wird Fehler ausgegeben, wie ich geschrieben habe. Ich muss diese Frage schließen. Und ich muss auch globallayoutlistener für die Größe der Ansicht verwenden :) – atasoyh

Antwort

1

In meinem Verständnis Sie die Aussicht wegen der übergeordneten Ansicht nicht aufblasen kann, ist nicht gezeichnet, was bedeutet, alle seine Layout-Parameter nicht abgerechnet werden, wenn Sie hinzufügen Eine View, deren View aufgrund des Containers ihre eigenen View-Parameter nicht berechnen kann, ist noch nicht gestartet. Wenn Sie das Kind Ansicht Verfahren im Inneren des Behälters onCreate Verfahren einzuleiten verwenden möchten, können Sie die folgende in Ihrem Container erstellen Methode versuchen:

containerVariable.post(new Runnable(){ 
    @Override 
    public void run(){ 
     // initiate your child view and add child view here 
    } 
}); 
+0

Könnte ich es anstelle von GlobalLayoutListener verwenden? Welche Methode ist besser geeignet? – atasoyh

+1

In meinem Verständnis, GlobalLayoutListener ist eine Methode in der Standard-Android-Bibliothek und es ist mehr bevorzugt, aber ich schlage vor post-Methode aufgrund GlobalLayoutListener muss mit verschiedenen Android-Version Problem zu behandeln, und post-Methode ist eine Art von Verfahren Umgang mit Möglichkeiten. –