0

I'm trying to create a custom view with two TextViews inside a vertical LinearLayout, but am totally confused as to how it all works.

Currently nothing is appearing as I my onDraw method isn't being called. I think this is due to the fact that my view (the LinearLayout?) has a width and height of both 0.

I think I should be overwriting my onMeasure, but after trying setMeasuredDimension(100,100) this still isn't working.

I am trying to inflate an xml inside the view and use the two TextViews in that.

An explanation would also be great so I can hopefully get my head around how this all works.

Thanks

size_button.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
    android:id="@+id/sizeButtonSizeText"
    android:layout_width="wrap_content"
    android:layout_height="match_parent" />

<TextView
    android:id="@+id/sizeButtonSlugText"
    android:layout_width="wrap_content"
    android:layout_height="match_parent" />

</LinearLayout>

SizeButton.java

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View.MeasureSpec;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.nap.library.NapApplication;
import com.nap.library.R;

public class SizeButton extends LinearLayout {

    private TextView mSize;
    private TextView mSlug;
    private String mSizeText;
    private String mSlugText;
    private Paint mPaint;
    private boolean mSoldOut;
    private Context mContext;

    /*
    public SizeButton(Context context) {
        super(context);
        setup();
    }

    public SizeButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup();
    }
    */

    public SizeButton(Context context, String size, String slug) {
        super(context);
        mContext = context;
        mSizeText = size;
        mSlugText = slug;
        setup();
    }

    public void setSoldOut(){
        this.mSoldOut = true;
    }

    public boolean isSoldOut(){
        return mSoldOut;
    }

    public void setSizeText(String size){
        mSize.setText(size);
    }

    public void setSlugText(String slug){
        mSlug.setText(slug);
    }

    public void setup(){
        mPaint = new Paint();


        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LinearLayout buttonLayout = (LinearLayout) inflater.inflate(R.layout.size_button, null);
        mSize = (TextView) buttonLayout.findViewById(R.id.sizeButtonSizeText);
        mSize.setGravity(Gravity.CENTER);
        mSize.setTextColor(Color.BLACK);
        mSize.setText(mSizeText);
        mSize.setTypeface(NapApplication.mPorter);
        mSize.setWidth(10);
        mSlug = (TextView) buttonLayout.findViewById(R.id.sizeButtonSlugText);
        mSlug.setGravity(Gravity.CENTER);
        mSlug.setTextColor(Color.BLACK);
        mSlug.setText(mSlugText);
        mSlug.setTypeface(NapApplication.mPorter);
        invalidate();
        requestLayout();

        LinearLayout.LayoutParams layoutParams =  new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        mSize.setLayoutParams(layoutParams);
        mSlug.setLayoutParams(layoutParams);
        Log.i("button","in setup");
        Log.i("button","width = "+this.getWidth()+" height = "+this.getHeight());
        Log.i("button","width = "+mSize.getWidth()+" sizeheight = "+mSize.getHeight());
        Log.i("button","width = "+mSlug.getWidth()+" slugheight = "+mSlug.getHeight());
  }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i("button","in onMeasure");
        setMeasuredDimension(100,100);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.i("button","in ondraw");
    }


}

ProductFragment.java - where the button is added to the fragment

for (int i = 0; i < mItem.getSizes().length; i++) {
    final SizeButton sizeButton = new SizeButton(getActivity(),mItem.getSizes()[i],"hello");

    // Each size button has a sku set as its tag
    sizeButton.setTag(mItem.getSkus()[i]);
    sizeButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            if(mItem.getSizes().length > 1) {
            boolean selected = !sizeButton.isSelected();
            if (selected) {
                mCurrentSku = (String) v.getTag();
            } else {
                mCurrentSku = null;
            }
            }
        configureButtons();
        }
    });
    Log.e("button","Adding button to view");
    mSizesWrapper.addView(sizeButton);
}
Russ Wheeler
  • 2,590
  • 5
  • 30
  • 57
  • possible duplicate of [Android Custom Layout - onDraw() never gets called](http://stackoverflow.com/questions/13056331/android-custom-layout-ondraw-never-gets-called) – Simon Mar 07 '14 at 15:22

1 Answers1

2

As your are extending a ViewGroup, you should override dispatchDraw(), not onDraw()

Simon
  • 14,407
  • 8
  • 46
  • 61
  • Ok, I see that dispatchDraw is being called, but I still don't understand how I give these views a size? It all seems to be based on what I put in onMeasure, but I wish to use the values of match_parent and wrap_content. How can I apply them? – Russ Wheeler Mar 07 '14 at 15:25
  • You could not override them and just let the framework take care of it by specifying the size in the layout XML as you do with any other view. If a method is not overriden, the base class method will be called. – Simon Mar 07 '14 at 15:27
  • that is what I was trying before, as you can see from the xml I have added, but nothing is being drawn. Any idea why? – Russ Wheeler Mar 07 '14 at 16:06
  • You should not set a view size in it's constructor (which you are doing by calling setup) since the parent of the view asks it to measure itself when it's added, not when it's constructed. There are 3 ways to do it. Create it in code and set it's `LayoutParams` (not in the view, in the consumer). 2. In XML like any other view. 3. In onMeasure(). http://stackoverflow.com/questions/12266899/onmeasure-custom-view-explanation – Simon Mar 07 '14 at 16:15
  • sorry I'm just really not getting this (probably as it's 5:40pm on a Friday) I don't understand what a 'consumer' is? So if I don't set the size inside setup, then where do I do it? And where do I inflate my xml layout? – Russ Wheeler Mar 07 '14 at 17:41
  • So I've tried adding a new TextView created inside the constructor and this works. Though I need to be able to draw lines on the TextView, and onDraw is still not being called. onDispatchDraw is, but from what I read this is for when the views inside the viewgroup get drawn? Any idea why inflating the layout from xml doesn't work? – Russ Wheeler Mar 07 '14 at 17:51