2015-09-08 22 views
8

Problema principale che il mio LayoutInflater.Factory (codice di esempio sotto) chiama onCreateView e funziona perfettamente con "com.android.support:support-v4:22.0.0". Ma onCreateView non viene chiamato quando mi sono spostato in "com.android.support:support-v4:22.1.0" o versioni successive. Non riesco a capire perché?LayoutInflater.Factory onCreateView non viene chiamato con la libreria di supporto 22.1+

//From many fragments i Call hintManager.inflate 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) { 
    layout = hintManager.inflate(inflater, R.layout.generate_code); 

... 

//here is HintManager method called from various fragments. 
public View inflate(LayoutInflater inflater, int layoutResourceId) { 
    AttributeParser attributeParser = new AttributeParser(); 
    LayoutInflater layoutInflater = attributeParser.getLayoutInflater(inflater); 

    final View v = layoutInflater.inflate(layoutResourceId, null); 
    //here AttributeParserFactory#onCreateView should be called, but it fails with 22.1+ support lib, but works with 22.0 
    attributeParser.setViewAttribute(v); 
    return v; 
} 

... 

//example of factory, that works fine with 22.0 support lib 
private Map<Integer, HashMap<Integer, String>> helpViewList; 

private class AttributeParser { 

    private AttributeParserFactory mFactory; 

    private class AttributeParserFactory implements LayoutInflater.Factory{ 
     @Override 
     public View onCreateView(String name, Context context, AttributeSet attrs) { 
      String id = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "id"); 

      if(id != null){ 
       // String with the reference character "@", so we strip it to keep only the reference 
       id = id.replace("@", ""); 

       TypedArray libraryStyledAttributeList = context.obtainStyledAttributes(attrs, R.styleable.Help); 
       HashMap<Integer, String> libraryViewAttribute = new HashMap<Integer, String>(); 
       int i = 0; 

       for(int attribute : R.styleable.Help){ 
        String attributeValue = null; 
        if (attribute == R.styleable.Help_arrow || attribute == R.styleable.Help_padding) { 
         attributeValue = String.valueOf(libraryStyledAttributeList.getInteger(i, 0)); 
        } 
        else { 
         attributeValue = libraryStyledAttributeList.getString(i); 
        } 

        if(attributeValue != null) 
         libraryViewAttribute.put(attribute, attributeValue); 

        i++; 
       } 

       if(!libraryViewAttribute.isEmpty()) { 
        helpViewList.put(Integer.valueOf(id), libraryViewAttribute); 
       } 

       libraryStyledAttributeList.recycle(); 
      } 

      return null; 
     } 

    } 

    public AttributeParser(){ 
     mFactory = new AttributeParserFactory(); 
    } 

    public void clear() { 
     helpViewList.clear(); 
    } 

    public LayoutInflater getLayoutInflater(LayoutInflater inflater) { 
     LayoutInflater layoutInflater = inflater.cloneInContext(inflater.getContext()); 
     layoutInflater.setFactory(mFactory); 

     return layoutInflater; 
    } 

    public void setFactory(LayoutInflater inflater){ 
     inflater.cloneInContext(inflater.getContext()).setFactory(mFactory); 
    } 

    public void setViewAttribute(Activity activity) { 
     for(Map.Entry<Integer, HashMap<Integer, String>> attribute : helpViewList.entrySet()) 
      if(activity.findViewById((Integer) attribute.getKey()) != null) 
       activity.findViewById((Integer) attribute.getKey()).setTag(attribute.getValue()); 

    } 

    public void setViewAttribute(View view) { 
     for(Map.Entry<Integer, HashMap<Integer, String>> attribute : helpViewList.entrySet()) 
      if(view.findViewById((Integer) attribute.getKey()) != null) 
       view.findViewById((Integer) attribute.getKey()).setTag(attribute.getValue()); 
    } 

    public Map<Integer, HashMap<Integer, String>> getAttributeList() { 
     return helpViewList; 
    } 

    public void setAttributeList(Map<Integer, HashMap<Integer, String>> attributeList) { 
     helpViewList = attributeList; 
    } 

} 
+0

cosa è richiesto per 'cloneInContext'? cosa vuoi veramente ottenere? – pskink

+0

Per creare un nuovo LayoutInflater con un'ulteriore LayoutInflater.Factory per le proprie viste, è possibile utilizzare cloneInContext (Context) per clonare un ViewFactory esistente e quindi richiamare setFactory (LayoutInflater.Factory) su di esso per includere la Factory. – Ragaisis

+0

stai usando frammenti dalla libreria di supporto? sei sicuro che è stato chiamato Fragment # onCreateView? – pskink

risposta

2

risposta Modificato:

Per risolvere questo problema dovremmo usare LayoutInflaterCompat.setFactory che aiuta con LayoutInflater fabbrica in pre/post Lollipop.

Questo è esempio

LayoutInflater layoutInflaterCopy = inflater.cloneInContext(inflater.getContext()); 
    LayoutInflaterCompat.setFactory(layoutInflaterCopy, new LayoutInflaterFactory() { 

     @Override 
     public View onCreateView(View parent, String name, Context context, AttributeSet attrs) { 
      String id = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "id"); 

      if(id != null){ 
       // String with the reference character "@", so we strip it to keep only the reference 
       id = id.replace("@", ""); 

       TypedArray libraryStyledAttributeList = context.obtainStyledAttributes(attrs, R.styleable.Help); 
       HashMap<Integer, String> libraryViewAttribute = new HashMap<Integer, String>(); 
       int i = 0; 

       for(int attribute : R.styleable.Help){ 
        String attributeValue = null; 
        if (attribute == R.styleable.Help_arrow || attribute == R.styleable.Help_padding) { 
         attributeValue = String.valueOf(libraryStyledAttributeList.getInteger(i, 0)); 
        } 
        else { 
         attributeValue = libraryStyledAttributeList.getString(i); 
        } 

        if(attributeValue != null) 
         libraryViewAttribute.put(attribute, attributeValue); 

        i++; 
       } 

       if(!libraryViewAttribute.isEmpty()) { 
        helpViewList.put(Integer.valueOf(id), libraryViewAttribute); 
       } 

       libraryStyledAttributeList.recycle(); 
      } 
      return null; 
     } 
    }); 

    final View v = layoutInflaterCopy.inflate(layoutResourceId, null); 
0

risposta accettato è obsoleto per AppCompat v23, si prega di controllare le fonti di sdk\sources\android-23\android\support\v4\view\LayoutInflaterCompatHC.java per vedere come LayoutInflater.Factory problema è aggirato nel forceSetFactory2 metodo.