Quiero añadir TextView para el elemento de la RecyclerView.Adapter basado en la ModalObject enviado a la RecyclerView.Adapter

Ejemplo:

Tuve un objeto modal con isAddText variable. En onCreateViewHolder creará el Titular de Objeto con el envío de la itemView como un parámetro.

@Override
public SolventViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.solvent_list, null);
    SolventViewHolders rcv = new SolventViewHolders(layoutView);
    return rcv;
}

SolventViewHolders.java

public SolventViewHolders(View itemView) {
    super(itemView);
    itemView.setOnClickListener(this);
    textView = (TextView) itemView.findViewById(R.id.country_name);
    imageView = (ImageView) itemView.findViewById(R.id.country_photo);
    // Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. 
}
Usted puede agregar textview en el diseño, y basado en su condición de hacerla visible/invisible.
No quiero así que..porque contienen más puntos de vista y dependencias

OriginalEl autor user3607798 | 2015-09-01

3 Comentarios

  1. 22

    El problema

    Normalmente, usted tendría que ejecutar itemView.addView(ver, layoutParams) para agregar otro punto de vista mediante programación a su diseño, pero la cosa con ViewHolders es, van a ser reutilizados por RecyclerView para enlazar los diferentes elementos de la adaptador, así que usted no puede hacer eso o esta nueva TextView que usted desea agregar aparecerá cuando otro elemento vinculado a esta viewHolder instancia de nuevo.

    Puedo pensar en un par de maneras que usted puede lograr su objetivo:


    1. Cambiar la Vista de la visibilidad

    La primera forma es agregar este textView a su diseño y su visibilidad por DESAPARECIDO por defecto, y el conjunto es VISIBLE cuando la unión que uno de los elementos que necesita este TextView, tales como:

    @Override
    public void onBindViewHolder(AbstractViewHolder holder, int position) {
        holder.extraTextView.setVisibility(View.GONE);
        if(shouldShowExtraTextView) {
            holder.extraTextView.setVisibility(View.VISIBLE);
            holder.extraTextView.setText(/* your text */);
        }
        //proceed to bind item to holder
    }

    2. Implementar diferentes ViewHolders

    La segunda forma es más elegante, implica la creación de diferentes ViewHolder tipo. En primer lugar usted necesita para crear int constantes para los dos tipos de vista para ser mostrado por RecyclerView. Lugar en el adaptador con el siguiente código:

    private static final int VIEW_ORDINARY = 0;
    private static final int VIEW_WITH_EXTRA_TEXT_VIEW = 1;

    A continuación, implementar el getItemViewType(int posición) método del adaptador:

    @Override
    public int getItemViewType(int position) {
        if(position == /* position of item that needs extra text view */) {
            return VIEW_WITH_EXTRA_TEXT_VIEW;
        } else {
            return VIEW_ORDINARY;
        }
    }

    Siguiente paso es crear diferentes de soporte, dependiendo del tipo devuelto:

    @Override
    public SolventViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType == VIEW_WITH_EXTRA_TEXT_VIEW) {
            View itemView = LayoutInflater.from(parent.getContext())
                                          .inflate(R.layout.solvent_list_with_extra_text_view, parent, false);
            return new SolventViewHolderWithExtraTextView(itemView);
        } else {
            View itemView = LayoutInflater.from(parent.getContext())
                                          .inflate(R.layout.solvent_list, parent, false);
            return new SolventViewHolder(itemView);
        }
    }

    Por supuesto, usted necesita para definir SolventViewHolderWithExtraTextView:

    class SolventViewHolderWithExtraTextView extends SolventViewHolder {
        TextView extraTextView;
    
        public SolventViewHolderWithExtraTextView(View itemView) {
            super(itemView);
            this.extraTextView = (TextView) findViewById(R.id.extra_text_view);
        }
    }

    Y, a continuación, en onBindViewHolder():

    @Override
    public void onBindViewHolder(SolventViewHolder holder, int position) {
        //you can use inheritance to handle binding logic or check the item view type again:
        //bind ordinary view
        if(getItemViewType(position)) {
            //bind the extra textView
            ((SolventViewHolderWithExtraTextView)holder).extraTextView.setText("I hope this works");
        }
    }

    De esta manera usted tiene otro tipo de ViewHolder de los elementos que es necesario que otro TextView, y va a ser reutilizado dentro de esa categoría. Es una manera preferida de hacer lo que usted quiere.


    3. Agregar/quitar la Vista de forma dinámica

    Otra respuesta (que es realmente feo solución si me preguntan a mí) es agregar y quitar la vista de forma dinámica, tales como:

    @Override
    public void onBindViewHolder(AbstractViewHolder holder, int position) {
        if(shouldDisplayExtraTextView) {
            if(!holder.displaysExtraTextView() {
                holder.addExtraTextView();
            }
            holder.extraTextView.setText("This solution is really ugly");
            } else {
            if(holder.displaysExtraTextView() {
                holder.removeExtraTextView();
            }
        }
    }
    
    class SolventViewHolders extends RecyclerView.ViewHolder {
        TextView extraTextView;
        boolean viewAdded = false;
    
        public SolventViewHolders(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            textView = (TextView) itemView.findViewById(R.id.country_name);
            imageView = (ImageView) itemView.findViewById(R.id.country_photo);
             // Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. 
    
            extraTextView = new TextView();
    }
    
    public void addExtraTextView() {
        ((ViewGroup)itemView).addView(extraTextView, layoutParams);
        viewAdded = true;
    }
    
    public void removeExtraTextView() {
        ((ViewGroup)itemView).removeView(extraTextView);
        viewAdded = false;
    }
    
    public boolean displaysExtraTextView() {
        return viewAdded;
    }

    Esto es realmente feo, porque a la vista de agregar a itemView usted necesita para lanzar a ViewGroup (que no tiene que ser), así que asegúrese de que siempre será un ViewGroup o su subclase. También, usted necesita para proporcionar una correcta layoutParams para agregar el extraTextView a itemView.

    No quiero inflar los diseños, la única manera para mí para agregar los puntos de vista de forma dinámica.
    He editado mi respuesta a incluir otra manera de lograr lo que quieres, aunque realmente no es una solución elegante, pero si por alguna razón, como usted dice, no se puede inflar otra presentación, esta debe hacer el truco.
    ¿Qué pasa si una presentación(vista) tiene un botón y otro no, suponiendo que el botón ha evento OnClick en práctica?
    lo que si había un número indeterminado de puntos de vista para agregar?
    entonces usted necesita su itemView a ser otro n-vistas contenedor como ListView, podría ser otra RecyclerView, cualquier aplicación de AdapterView o cualquier custom punto de vista que es capaz de sostener cantidad variable de puntos de vista, básicamente, un «anidadas vista de lista’ problema

    OriginalEl autor maciekjanusz

  2. 2

    También puede establecer itemView.setHasTransientState(true) en el que caso de que la vista no se recicla hasta setHasTransientState se establece en false.

    OriginalEl autor grgrssll

  3. 1

    Con la ayuda de @grgrssll la respuesta que yo era capaz de solucionar mi problema. En mi caso necesitaba N-número de TextViews dentro de cada fila.

    En mi onBindViewHolder

    @Override
    public void onBindViewHolder(@NonNull final HistoryViewHolder vh, int position) {
        ...
        //Generating N-number of TextViews depending on size of itemsMap
        for (Map.Entry<String, Model> entry : itemsMap.entrySet()) {
            SelectedModel s = entry.getValue();
            //Set setHasTransientState to true
            vh.itemDetailsContainer.setHasTransientState(true);    
            //Dynamically adding the views
            vh.itemDetailsContainer.addView(getItemTextView(context, s.getItemName()));
            ...
        }
        //Set setHasTranssientState to false after loop
        vh.itemDetailsContainer.setHasTransientState(false);
        ...
    }

    OriginalEl autor ymerdrengene

Dejar respuesta

Please enter your comment!
Please enter your name here