0

I want to create a custom view that will act as a container for other custom views. The user will be able to move the view you want to move by dragging it.

For the container, I implement it by extending ViewGroup:

public class MyContainer extends ViewGroup {

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

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

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

    private void init(Context context) {
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        
    }

    public void addItem(AbstractView view) {
        addView(view);
    }
}

For the custom view, I create an AbstractView class and create two views RectView and CircleView by extending it:

abstract public class AbstractView extends View {
    protected float mX, mY;
    protected int mWidth, mHeight;
    protected final Paint mShapePaint;

    public AbstractView(Context context, float x, float y, int width, int height) {
        super(context);
        mShapePaint = new Paint();
        mShapePaint.setColor(Color.BLACK);
        mShapePaint.setStyle(Paint.Style.STROKE);
        mX = x;
        mY = y;
        mWidth = width;
        mHeight = height;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure the view
        int width = resolveSize(mWidth, widthMeasureSpec);
        int height = resolveSize(mHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                // Update the position of the item when it is moved
                mX = event.getX();
                mY = event.getY();
                invalidate();
                break;
        }
        return true;
    }
}

public class CircleView extends AbstractView {

    public CircleView(Context context, float x, float y) {
        super(context, x, y, 100, 100);
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawCircle(mX, mY, mWidth/2f, mShapePaint);
    }
}

public class RectView extends AbstractView {

    public RectView(Context context, float x, float y) {
        super(context, x, y, 100, 40);
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawRect(mX, mY, mX + mWidth, mY + mHeight, mShapePaint);
    }
}

Here is the code for MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyContainer myContainer = findViewById(R.id.myContainer);

        myContainer.addItem(new RectView(this, 50, 50));
        myContainer.addItem(new CircleView(this, 200, 200));
    }
}

Finally here is the xml file:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.my.package.name.MyContainer
        android:id="@+id/myContainer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

When I run this code nothing visible on the screen, but when I extend FrameLayout instead of ViewGroup (as someone suggests) and remove onLayout method from the code, the view is now visible but I can only drag the last added view to this groupView (only able to move the topmost View). My question is: how can I make the views visible and be able to move them? (I think the problem is because I need to implement onMesure and onLayout for the groupView but I don't know how to implement them in this case) or at least How can I move the other views (not just the top most view) in the case of extending FrameLayout ?

Abdo21
  • 498
  • 4
  • 14

0 Answers0