2

I have a custom view with animation and I need to somehow get it in the constraint layout. Here is a little example of what I mean. I basically need a small area where I can use custom animations/bitmaps and all that stuff.

So far I've only managed to apply the view on all the screen with: setContentView(customView).

customView:

public class CrashView extends View {

private int width, height,bheight, bwidth, boxwidth, boxheight;
private float x,y,vx,vy;

private Bitmap bullet;
private Paint AA = new Paint(Paint.ANTI_ALIAS_FLAG);

public CrashView (Context context){
    super(context);

    Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);

    bullet = BitmapFactory.decodeResource(getResources(), R.drawable.bullet);
    bullet = Bitmap.createScaledBitmap(bullet, bullet.getWidth()/5, bullet.getHeight()/5, true);

    width = size.x;
    height = size.y;

    bheight = bullet.getHeight();
    bwidth = bullet.getWidth();

    boxheight = height / 4;
    boxwidth = (width / 20) * 19;

    x = (width/20)/4;
    y = boxheight-bheight/4*3;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    vy = -0.1f - (float) ((Math.pow(x / 600, 2)) / 1.25);

    x += vx;
    y += vy;

    canvas.drawBitmap(bullet, x, y, AA);
    invalidate();
}
K.Bowman
  • 77
  • 3
  • 14
  • 1
    And what is the problem exactly? Your view still extends Android View object (even indirectly) and given that it has set dimensions (as it has to have them) it can be positioned in any other ViewGroup. ConstraintLayout is no different than any other layout out there. What is your XML file? – mhenryk Mar 30 '17 at 13:45
  • @mhenryk The problem is that I can't manage to add the view to the layout with the correct dimensions and position. All I have managed to do is just overlap the layout with the view, but I need it resized like in the example. I'm quite new to the graphics and I'm pretty much clueless at the moment. Have been struggling for 2 days with this stuff. – K.Bowman Mar 30 '17 at 13:49
  • Does your view extend onMeasure? Does it inflate a layout inside it? What is the parent class of your custom View? – mhenryk Mar 30 '17 at 13:52
  • @mhenryk Haven't really done those things. I followed a few tutorials and tried to make something out of them and the result wasn't what I needed. I guess I was doing it all wrong. Could you help out and write what I need to do in order for it to work? I'd be grateful. – K.Bowman Mar 30 '17 at 14:00
  • I'm not saying it was wrong. I'm asking these questions because I'm looking for a reason why view matches parent. I need more information - like your view code. – mhenryk Mar 30 '17 at 14:01
  • @mhenryk Added the custom view code. I don't really know what's the right way to implement the custom view into my layout. – K.Bowman Mar 30 '17 at 14:14
  • I will check it later once I have access to compiler – mhenryk Mar 30 '17 at 14:31
  • I believe you may have to implement onMeasure in here to let Android know what is the size of your view. Take a look at this question: http://stackoverflow.com/questions/12266899/onmeasure-custom-view-explanation – mhenryk Mar 30 '17 at 14:33

1 Answers1

2

Combined your code with the code for onMeasure from the answer I mentioned in comments:

public class CrashView extends View {

    private int width, height, bheight, bwidth, boxwidth, boxheight;
    private float x, y, vx, vy;

    private Bitmap bullet;
    private Paint AA = new Paint(Paint.ANTI_ALIAS_FLAG);

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

    public CrashView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CrashView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CrashView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context ctx) {

        Display display = ((Activity) ctx).getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        //REPLACE DRAWABLE HERE
        bullet = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        bullet = Bitmap.createScaledBitmap(bullet, bullet.getWidth() / 5, bullet.getHeight() / 5, true);

        width = size.x;
        height = size.y;

        bheight = bullet.getHeight();
        bwidth = bullet.getWidth();

        boxheight = height / 4;
        boxwidth = (width / 20) * 19;

        x = (width / 20) / 4;
        y = boxheight - bheight / 4 * 3;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int desiredWidth = boxwidth;
        int desiredHeight = boxwidth;

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        //Measure Width
        if (widthMode == MeasureSpec.EXACTLY) {
            //Must be this size
            width = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            //Can't be bigger than...
            width = Math.min(desiredWidth, widthSize);
        } else {
            //Be whatever you want
            width = desiredWidth;
        }

        //Measure Height
        if (heightMode == MeasureSpec.EXACTLY) {
            //Must be this size
            height = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            //Can't be bigger than...
            height = Math.min(desiredHeight, heightSize);
        } else {
            //Be whatever you want
            height = desiredHeight;
        }

        //MUST CALL THIS
        setMeasuredDimension(width, height);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        vy = -0.1f - (float) ((Math.pow(x / 600, 2)) / 1.25);

        x += vx;
        y += vy;

        canvas.drawBitmap(bullet, x, y, AA);
        invalidate();
    }
}

The XMl is as simple as:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/root">

    <com.test.myapplication.CrashView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

Here is the layout with displaying bounds on:

Rendered layout with displaying view bounds ON

Things to keep in mind:

  1. Magic numbers - you got quite a few of those here, you know best what are they for but it's better to keep them as named constants
  2. View size depends on size of a screen. This might not be a good idea. It should depend on the size of the resource you are drawing.
  3. I used relative layout but it should be no different with constraint layout.
  4. Extra constructors that appeared were needed for XML inflation
mhenryk
  • 551
  • 5
  • 13
  • I managed to create it, but now another minor question. Is there a way to control the onDraw programmatically? For example, it starts and stops drawing whenever I command it to. – K.Bowman Apr 03 '17 at 16:18
  • invalidate() causes onDraw() being called. Take a look at this answer alongside with the comments http://stackoverflow.com/a/25846243/4519492 it briefly explains how, when and why are views being drawn – mhenryk Apr 03 '17 at 16:27
  • Managed to do it my way somehow. Huge thanks to you, mate. You have saved me tons of hours and a possible project closure. Cheers! – K.Bowman Apr 03 '17 at 17:30
  • Not sure why this is an answer since he said ConstraintLayout and thats a RelativeLayout – Nick Turner Oct 25 '18 at 15:39
  • The real problem was not related to the constraint layout itself. – mhenryk Oct 26 '18 at 09:34