Search code examples
androidlistviewcustom-view

Add custom view dynamically to a recyclerview


I have to create a new custom view for each item added in a recycler view.

@Override
public ListViewAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
    BaseViewHolder viewHolder =new BaseViewHolder(view);
    return viewHolder;
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
    if(holder instanceof BaseViewHolder){
    circleAnimationViewClass =new CircleAnimationView(mContext);

    circleAnimationViewClass.addRadius(circleList.get(position).getRadius());
    circleAnimationViewClass.addSpeed(circleList.get(position).getSpeed());
    circleAnimationViewClass.addColor(circleList.get(position).getColor());
    if(getItemViewType(position) >-1){
        circleAnimationViewClass.onStart();
        holder.bindCircle(circleList.get(position));

    }
    }

}
public class BaseViewHolder extends RecyclerView.ViewHolder {

    protected Context mActivityContext;
    View circleAnimationView;
    TextView radiusTextView;
    TextView speedTextView;
    public BaseViewHolder(View itemView) {
        super(itemView);
        this.circleAnimationView = (CircleAnimationView ) itemView.findViewById(R.id.animationView);
        this.radiusTextView = (TextView)itemView.findViewById(R.id.radiusText);
        this.speedTextView=(TextView)itemView.findViewById(R.id.speedText);
        mActivityContext =itemView.getContext();
    }
    public void bindCircle(CircleProperties objCircle){
        circleAnimationViewClass.drawCanvas((CircleProperties)objCircle);
        circleAnimationViewClass.invalidate();
    }
}

This is my circleanimation class

 public void addRadius(int radius){
        circleRadius =radius;
    }
    public void addSpeed(int speed){
        circleSpeed=speed;
    }
    public void addColor(int color){
        circleColor= color;
    }
 public CircleAnimationView(Context context, AttributeSet attributes) 
{
        super(context, attributes);
        TypedArray typedArray = context.obtainStyledAttributes(attributes, R.styleable.CircleAnimationView);
        circleRadius = typedArray.getColor(R.styleable.CircleAnimationView_radius, 20);
        circleSpeed = typedArray.getColor(R.styleable.CircleAnimationView_speed, 100);
        circleColor =typedArray.getColor(R.styleable.CircleAnimationView_circleColor, Color.BLACK);
        typedArray.recycle();
    }


    @Override
    public void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
            Paint paint = new Paint();
            paint.setStrokeWidth(5);
            paint.setColor(circleColor);
            if (i == 0) {
                startXPos = dpToPx(circleRadius);
                i = dpToPx(circleRadius);
                canvas.drawCircle(startXPos, dpToPx(40), dpToPx(circleRadius), paint);
                //canvas.drawCircle(dpToPx(200), dpToPx(200), dpToPx(30), paint);
            } else {
                startXPos =   startXPos >= (canvas.getWidth() - dpToPx(circleRadius)) ? dpToPx(circleRadius) : startXPos + dpToPx(circleSpeed / 16);

                canvas.drawCircle(startXPos, dpToPx(40), dpToPx(circleRadius), paint);

            }
            i++;
    }

Problem is when i am not getting the values of radius and speed in onDraw. I am using invalidate to call the ondraw of custom view. Main requiremnt is each time a new item is added to recycler view, i need to create customview for that item and do a custum drwaing of item.


Solution

  • Use Recycler View or at least the view holder pattern correctly. And RecyclerView.Adapter.

    public class ListViewAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    
    private List<CircleProperties> properties;
    
    ListViewAdapter(Activity context, List<CircleProperties> circleObjectList){
        mContext = context;
        circleList =circleObjectList;
    }
    
    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType.equals(A_VIEW_TYPE) {
            return new CircleAViewHolder(mActivityContext, mInflater.inflate(CircleViewHolder.CIRCLE_A_VIEW_ID, parent, false));
        } else if(viewType.equals(B_VIEW_TYPE) {
            new CircleAViewHolder(mActivityContext, mInflater.inflate(CircleViewHolder.CIRCLE_B_VIEW_ID, parent, false));
        }       
    }
    
    @Override
    public int getItemViewType(int position) {
        return properties.get(position).getType();
    }
    
    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        holder.bind(properties.get(position));
    }
    
    @Override
    public int getItemCount() {
        return properties.size();
    }
    }
    

    Then create view holders like this...

    public class BaseViewHolder extends RecyclerView.ViewHolder {
    
    protected Context mActivityContext;
    protected int mPosition;
    
    public BaseViewHolder(View itemView) {
        super(itemView);
    }
    
    public BaseViewHolder(Context context, View itemView) {
        super(itemView);
        mActivityContext = context;
    
    }
    
    public void bind(Object data){
    }
    }
    

    And subclass that view holder like...

    private class CircleAViewHolder extends BaseViewHolder{
    
        CircleAnimationView circleAnimationView;
        TextView radiusTextView;
        TextView speedTextView;
    
        ViewHolder(Context context, View itemView) {
            this.circleAnimationView = (CircleAnimationView ) itemView.findViewById(R.id.circle_animation_view);
            this.radiusTextView = (TextView)itemView.findViewById(R.id.radius_view);
            this.speedTextView=(TextView)itemView.findViewById(R.id.speed_text_view);
        }
    
        public void bind(Object data){
            CircleProperties circleProp = (CircleProperties) data;
            radiusTextView.setText(circleProp.getRadius());
            speedTextView.setText(circleProp.getSpeed());
            animaitonView.drawCanvas(data);
            //TODO: Any other view setup using data.
        }
    }
    

    And a second view holder like...

    private class CircleBViewHolder extends BaseViewHolder{
    
        CircleAnimationView animationView;
        TextView diameterTextView;
        TextView velocityTextView;
    
        ViewHolder(Context context, View itemView) {
            this.animationView = (CircleAnimationView) itemView.findViewById(R.id.animation_view);
            this.diameterTextView =(TextView)itemView.findViewById(R.id.diameter_view);
            this.velocityTextView=(TextView)itemView.findViewById(R.id.velocity_text_view);
        }
    
        public void bind(Object data){
            CircleProperties circleProp = (CircleProperties) data;
            diameterTextView.setText(circleProp.getDiameter());
            velocityTextView.setText(circleProp.getVelocity());
            animaitonView.drawCanvas(data);
            //TODO: Any other view setup using data.
        }
    }