How to pass variables to custom View before onDraw

2019-02-21 00:39发布

What I am trying to achieve:

  • measure a container View in my layout, mainContainer, that is defined in the XML
  • pass the mainContainer's width and height to a different custom View before onDraw() is called
  • I want to pass the width and height so the custom View knows where to draw canvas.drawBitmap using coordinates
  • The custom view will be programmatically created from code

How can I pass the measured int width and int height to my custom View before onDraw() is called?

Custom View

public class AvatarView extends ImageView {

private Bitmap body;
private Bitmap hat;

public AvatarView(Context context) {
    super(context);
    init();
}

public AvatarView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public AvatarView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

private void init() {
    body = BitmapFactory.decodeResource(getResources(), R.drawable.battle_run_char);
    hat = BitmapFactory.decodeResource(getResources(), R.drawable.red_cartoon_hat);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(body, x, y, null);
    canvas.drawBitmap(hat, x, y, null);
}
}

Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_customize_avatar, container, false);
    final RelativeLayout mainContainer = (RelativeLayout) view.findViewById(R.id.main_container);
    TwoWayView inventoryList = (TwoWayView) view.findViewById(R.id.inventory);

    inventoryList.setAdapter(null);

    inventoryList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

        }
    });

    mainContainer.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @SuppressLint("NewApi")
        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {
            // Retrieve the width and height
            containerWidth = mainContainer.getWidth();
            containerHeight = mainContainer.getHeight();

            // Remove global listener
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
                mainContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            else
                mainContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    });

    return view;
}

XML

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clickable="true"
android:background="#fff" >

<com.walintukai.lfdate.CustomTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:textStyle="bold"
    android:textColor="#fff"
    android:textSize="20sp"
    android:textAllCaps="true"
    android:text="@string/customize_avatar"
    android:background="#009BFF" />

<RelativeLayout
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

<org.lucasr.twowayview.TwoWayView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/inventory"
    style="@style/HorizontalListView"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:drawSelectorOnTop="false"
    android:background="#f3f3f3" />

</LinearLayout>

1条回答
劫难
2楼-- · 2019-02-21 01:01

What you need to do is add a flag inside your AvatarView that checks if are you going to render this or not in your onDraw method.

sample:

   public class AvatarView extends ImageView {

    private Bitmap body;
    private Bitmap hat;
    private int containerHeight;
    private int containerWidth;
    private boolean isRender = false;

    public AvatarView(Context context) {
        super(context);
        init();
    }

    public AvatarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AvatarView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public void setMeasure(int containerWidth, int containerHeight )
    {
        this.containerHeight = containerHeight;
        this.containerWidth = containerWidth;
    }

    private void init() {
        body = BitmapFactory.decodeResource(getResources(), R.drawable.battle_run_char);
        hat = BitmapFactory.decodeResource(getResources(), R.drawable.red_cartoon_hat);
    }

    public void setRender(boolean render)
    {
       isRender = render;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(isRender )
        {
            canvas.drawBitmap(body, x, y, null);
            canvas.drawBitmap(hat, x, y, null);
        }

    }
    }

Now it wont render when you dont call setRender and set it to true. And just call setMeasure to pass the value.

First you need to call setMeasure and after you set the measure you then call setRender(true) and call invalidate() to call the onDraw method to render the images

查看更多
登录 后发表回答