создать / изменить / удалить / отменить количество различных фигур на холсте, onClick () кнопки - PullRequest
0 голосов
/ 26 октября 2018

Я создаю приложение для Android для фигур на холсте. Нажмите кнопку .

Что я хочу:

У меня есть три кнопки «Квадрат», «Круг», «Треугольник». Каждый раз, когда я нажимаю на кнопку, объект этой формы будет создаваться и отображаться в случайной позиции на одном холсте. (Готово)

При нажатии каждой фигуры она станет другой. постукивание по квадрату сделает его кругом постукивание по кругу сделает его треугольником нажатие на треугольник превратит его в квадрат (готово)

При длинном нажатии на фигуру можно удалить фигуру. (Сделано)

Как реализовать функцию отмены!

Проб и ошибка: Для достижения этой функциональности я попытался до сих пор следующий код, в котором я могу создать одну фигуру по нажатию кнопки, используя растровое изображение в Java и представление изображения в XML.

Update_29 / 10: Я работаю над одним и тем же кодом и создаю несколько фигур на холсте, используя динамический относительный макет, добавляя виды.

Мой вопрос:

Это правильный способ (растровое изображение и изображение), чтобы создать форму на холсте, нажав на кнопку?

Теперь я могу создавать несколько фигур на холсте, но каждый раз, когда я создаю новый экземпляр холста, есть ли другой способ добиться этого?

Update_29_10:

Как получить щелчок формы, чтобы я также мог удалять функции и отменять функции.

XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity">

<RelativeLayout
    android:id="@+id/relative4"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:layout_above="@+id/btnCircle"
    android:background="@color/colorAccent">

</RelativeLayout>
<Button
    android:id="@+id/btnSquare"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:text="@string/square" />

<Button
    android:id="@+id/btnCircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_toRightOf="@+id/btnSquare"
    android:text="@string/circle" />


<Button
android:id="@+id/btnTriangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
    android:layout_toRightOf="@+id/btnCircle"
    android:text="@string/triangle" />

<Button
    android:id="@+id/btnUndo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/btnTriangle"
    android:layout_alignParentBottom="true"
    android:text="@string/undo" />

MainActivity.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private Resources mResources;
    private RelativeLayout mRelativeLayout;
    private Button btnSquare, btnCircle, btnTriangle,btnUndo,btnState;
    private int mSuareCount=0,mCircleCount=0,mTriangelCount=0;


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

    private void initViews() {
        mContext = getApplicationContext();
        mResources = getResources();
        mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
        btnSquare = (Button) findViewById(R.id.btnSquare);
        btnCircle = (Button)findViewById(R.id.btnCircle);
        btnTriangle = (Button)findViewById(R.id.btnTriangle);
        btnUndo=(Button)findViewById(R.id.btnUndo);
        setOnClickListeners();
    }

    private void setOnClickListeners() {
        btnSquare.setOnClickListener(this);
        btnCircle.setOnClickListener(this);
        btnTriangle.setOnClickListener(this);
        btnUndo.setOnClickListener(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnSquare:
                drawSquare(null);
                mSuareCount++;
                break;

            case R.id.btnCircle:
                drawCircle(null);
                mCircleCount++;
                break;

            case R.id.btnTriangle:
                drawTriangle(null);
                mTriangelCount++;
                break;

            case R.id.btnUndo:

                break;

        }
    }

    private void drawSquare(ImageView imageView) {
        Bitmap bitmap = Bitmap.createBitmap(
                50, // Width
                50, // Height
                Bitmap.Config.ARGB_8888 // Config
        );

        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.LTGRAY);
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.YELLOW);
        paint.setAntiAlias(true);

        int padding = 50;
        Rect rectangle = new Rect(
                padding, // Left
                padding, // Top
                canvas.getWidth() - padding, // Right
                canvas.getHeight() - padding // Bottom
        );
        canvas.drawRect(rectangle, paint);
        addViews(bitmap,imageView,1);

        // Display the newly created bitmap on app interface
        if (imageView == null) {
            imageView = new ImageView(this);
        }
        imageView.setImageBitmap(bitmap);

        final ImageView finalImageView = imageView;
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawCircle(finalImageView);
                mSuareCount--;
                mCircleCount++;
            }
        });
    }

    private void drawCircle(ImageView imageView) {
        Bitmap bitmap = Bitmap.createBitmap(
                50, // Width
                50, // Height
                Bitmap.Config.ARGB_8888 // Config
        );

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);

        int radius = Math.min(canvas.getWidth(), canvas.getHeight() / 2);
        int padding = 5;
        canvas.drawCircle(
                canvas.getWidth() / 2, // cx
                canvas.getHeight() / 2, // cy
                radius - padding, // Radius
                paint // Paint
        );

        addViews(bitmap,imageView,2);

        // Display the newly created bitmap on app interface
        if (imageView == null) {
            imageView = new ImageView(this);
        }
        imageView.setImageBitmap(bitmap);

        final ImageView finalImageView = imageView;
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawTriangle(finalImageView);
                mCircleCount--;
                mTriangelCount++;
            }
        });

    }

    private void drawTriangle(ImageView imageView) {
        Bitmap bitmap = Bitmap.createBitmap(
                500, // Width
                500, // Height
                Bitmap.Config.ARGB_8888 // Config
        );

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(),
                bitmap.getHeight());


        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.YELLOW);
        paint.setAntiAlias(true);
        Point point1_draw = new Point(90, 0);
        Point point2_draw = new Point(0, 180);
        Point point3_draw = new Point(180, 180);

        Path path = new Path();
        path.moveTo(point1_draw.x, point1_draw.y);
        path.lineTo(point2_draw.x, point2_draw.y);
        path.lineTo(point3_draw.x, point3_draw.y);
        path.lineTo(point1_draw.x, point1_draw.y);
        path.close();
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#3F51B5"));
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        //addViews(bitmap,imageView);

        addViews(bitmap,imageView,3);

        if (imageView == null) {
            imageView = new ImageView(this);
        }
        imageView.setImageBitmap(bitmap);
        final ImageView finalImageView = imageView;
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawSquare(finalImageView);
                mSuareCount++;
                mTriangelCount--;
            }
        });

    }

    private void addViews(Bitmap bitmap, ImageView imageView, final int value) {
        final int min = 20;
        final int max = 80;


        Drawable d = getResources().getDrawable(R.mipmap.ic_launcher_round);
        final int w = d.getIntrinsicWidth();
        final int random = new Random().nextInt((max - min) + 1) + min;

        RelativeLayout relative4 = (RelativeLayout) findViewById(R.id.relative4);
        int width = relative4.getMeasuredWidth();
        int height = relative4.getMeasuredHeight();
        if (imageView == null) {
            imageView = new ImageView(this);
        }
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
        params.setMargins(new Random().nextInt((width - 0) + 1), new Random().nextInt((height - 0) + 1), 10, 10);
        imageView.setLayoutParams(params);
        imageView.setImageBitmap(bitmap);


        if (imageView != null) {
            ViewGroup parent = (ViewGroup) imageView.getParent();
            if (parent != null) {
                parent.removeView(imageView);
            }
        }

        relative4.addView(imageView);

        final ImageView finalImageView = imageView;


        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                switch (value) {
                    case 1:
                        drawCircle(finalImageView);
                        mSuareCount--;
                        mCircleCount++;
                        break;

                    case 2:
                        drawTriangle(finalImageView);
                        mCircleCount--;
                        mTriangelCount++;
                        break;

                    case 3:
                        drawSquare(finalImageView);
                        mTriangelCount--;
                        mSuareCount++;
                        break;

                }

            }
        });

        imageView.setOnLongClickListener(new View.OnLongClickListener(){


            @Override
            public boolean onLongClick(View v) {
                  switch (value) {
                case 1:
                    relative4.removeView(finalImageView);
                    mSquareCount--;
                    break;

                case 2:
                    relative4.removeView(finalImageView);
                    mCircleCount--;
                    break;

                case 3:
                    relative4.removeView(finalImageView);
                    mTriangleCount--;
                    break;
            }
            return true;
        });
    }

}

enter image description here

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Хотя решение aanshu, вероятно, является более эффективным способом сделать это, его решение затрудняет распознавание щелчков по отдельным фигурам.

Вместо создания одного большого подкласса ImageView и переопределения onDraw и рисования каждого изпод-формы, вы можете сделать подкласс ImageView для каждого класса квадрата, круга и треугольника.Примерно так:

public class SquareView extends ImageView {
    @Override
    protected void onDraw(Canvas canvas) {
        //draw your Square on the canvas given
    }
}

То же самое для круга и треугольника.Затем просто создайте одно из этих представлений, как вы создавали представления изображений ранее, но не устанавливайте растровое изображение.Вы можете добавить их в макет, и он вызовет функцию onDraw и предоставит ему холст.Теперь вы можете зарегистрировать свой onClickListener для каждого из этих представлений, как и раньше.При нажатии на представление вы заменяете его экземпляром другого класса, например, заменяете SquareView на CircleView.

Для операций отмены вы можете просто сделать это.Это очень похоже на псевдокод, я также могу смешивать некоторые языки программирования, но идея везде одинакова.Если что-то неясно, пожалуйста, спросите.

Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();

Немного предыстории о вашем коде, потому что я думаю, что это поможет вам понять. Этот является источником Android ImageView.Когда вы вызываете setImageBitmap (bitmap), он передает растровое изображение экземпляру BitmapDrawable, который он вызывает mDrawable.Затем в методе ImageViews onDraw (Canvas canvas) он вызывает mDrawable.draw (canvas), который в случае BitmapDrawable ( source here ) после множества других вещей вызывает canvas.drawBitmap (bitmap).Итак, в основном то, что делает ваш код: он создает растровое изображение из холста, а затем через ImageView и BitmapDrawable растровое изображение рисуется обратно на холст.Мое решение и решение Ааньшу опираются непосредственно на этот последний холст.Вот почему они лучше, чем ваше текущее решение.

Редактировать: В поисках чего-то другого я наткнулся на ресурсы рисованной формы .Как и для любого нарисованного ресурса, вы можете просто передать его в ImageViews.Таким образом, вам, вероятно, не придется переопределять функцию onDraw.Но я никогда не работал с ними, поэтому я просто оставлю это здесь.

0 голосов
/ 06 ноября 2018

Вы можете реализовать эту функциональность, используя следующий подход (псевдокод):

Шаг 1:

interface ShapeInfo {
void drawShape(Canvas canvas);
}

Шаг 2: Реализуйте 3 различных класса (Rect, Triangle, Circle) с этим интерфейсом

Шаг 3. Установите фон для RelativeLayout

Шаг 4. Добавьте CustomView в RelativeLayout сделать этот пользовательский вид прозрачным.

    public class CustomView extends ImageView{

    ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
            public CustomView(Context context) {
                super(context);
                // TODO Auto-generated constructor stub
            }

            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                for ( ShapeInfo s:alShapesInfo)
                  s.drawShape(canvas);

            }
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}

public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
        }

Спте 5: В основном действии по нажатию кнопки добавления треугольника, круга, прямоугольного вызова customview.addshapeinfo

Шаг 6: отменить вызов

customview.undo
...