10
votes

Android Dingerpaint Annuler / Refaire mise en œuvre

Je travaille sur un projet de test qui est similaire à digitalpaint code> exemple dans les démos de SDK Android. J'essayais de mettre en œuvre des fonctionnalités d'annulation / de redo dans mon projet, mais les choses que j'ai essayées ne fonctionnaient pas comme je m'attends. Je trouve des questions similaires à celles-ci sur Internet et ici, mais elles ne m'a pas aidées, c'est pourquoi je pose une nouvelle question.

Voici une idée de ce que je fais en fait: P>

    public class MyView extends View {

    //private static final float MINP = 0.25f;
    //private static final float MAXP = 0.75f;



    private Path    mPath;
    private Paint   mBitmapPaint;

    public MyView(Context c) {
        super(c);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        mCanvas = new Canvas(mBitmap);
        mCanvas.drawColor(Color.WHITE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }
    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);

        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }
    private void touch_up() {

        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }
}


2 commentaires

Quelles solutions avez-vous déjà essayées?


Celui-ci: Stackoverflow.com/Questtions/7633282/...


5 Réponses :


0
votes

Je pense que dans ce cas, vous pouvez utiliser deux toiles. Vous savez quand l'utilisateur commence à dessiner et lors de la fin. Donc, dans tactile_start Vous pouvez créer une copie de votre canvas actuelle. Lorsque l'utilisateur clique sur Annuler, vous remplacez votre toile actuelle avec précédemment enregistrée.

Cela devrait garantir que vous aurez l'état d'image précédent, mais je ne suis pas sûr de la performance.


0 commentaires

4
votes

La meilleure solution est que vous implémentez votre propre moteur d'annulation / redro.

  1. Enregistrez dans une matrice chaque action que vous effectuez dans une matrice (c.-à-d. Cercle [0] en position X1, Y1, [1] ligne de X2, Y2 à X3, Y3, etc.)

  2. dessiner

  3. Si vous avez besoin d'annuler, effacez la toile et repeindre toutes les actions N - 1 de [0] à [N-1]

  4. Si vous annulez plus, il suffit de peindre de [0] à [n-2], etc.

    J'espère que cela vous donne un indice

    Cheer!


1 commentaires

En fait, c'était mon idée, mais je veux savoir si c'est la meilleure chose à faire pour faire cela.



13
votes

Je ne sais pas si c'est ce que vous aviez à l'esprit, mais c'est comme ça que je le fais. Au lieu de la stocker dans un seul chemin, vous stockez un tableau avec tous les chemins, comme celui-ci, l'utilisateur peut dessiner de nombreuses lignes, avec une petite modification que vous pouvez ajouter multi-touch aussi.

Pour faire annuler et refaire, il suffit de supprimer ou ajoutez le dernier chemin de chemin à partir de la variable PATHS et stockez-les dans un nouveau tableau. Quelque chose comme: xxx

Voici mon panneau modifié, je ne peux pas l'essayer maintenant, mais les méthodes ci-dessus doivent fonctionner! J'espère que ça aide! (Il y a peu de variables supplémentaires simplement les supprimer :) xxx


14 commentaires

Merci mec! Cette mise en œuvre fonctionne comme un charme !!!! Juste besoin d'ajouter invalider (); dans oncclickundo () et onclickredo (); afin que vous puissiez obtenir le résultat juste après avoir cliqué sur le bouton .


Content d'aider :) J'ai ajouté la réponse! À votre santé!


Je viens de voir un problème en fait. Lorsque vous utilisez mpain.setxfermode (nouveau PorterSduffXFermode (PorterDuff.Mode.Clear)); avec votre code, le résultat est des lignes noires, elle n'agit pas comme une brosse. Et l'autre chose est si j'essaie de définir un effet sur l'accident vasculaire cérébral, cela change toutes les vieilles lignes aussi.


Eh bien, c'est parce que vous définissez un effet dans la peinture utilisée pour toutes les lignes que je suppose. Je ne sais vraiment pas comment vous aider à ce sujet, peut-être mettre à jour votre réponse avec plus de détails, puis nous pouvons essayer de trouver quelque chose de spécifique sur ce dont vous avez besoin!


@gameower: Hey je viens d'essayer ce code. Et cela me quitte de mon problème. Maintenant je veux une dernière chose. Je veux avoir une toile avec un bitmap de fond. J'ai fatigué plusieurs façons mais pas réussi. Pouvez-vous me dire où écrire cette méthode dessinée?


@HARDIKTRIVEDI Je vous suggère fortement de poser une question dans le forum et de laisser toute la communauté vous aider! J'ai besoin de voir une partie de votre source de sorte que je peux vous guider. Ajoutez le lien à votre question ici et je ferai de mon mieux pour vous aider!


@gameower Utilisation de votre code J'ai essayé d'implémenter une fonctionnalité d'annulation - Redo, mais je ne reçois toujours pas de solution de, au premier clic de l'annulation, la fonctionnalité ne fonctionne pas. J'ai utilisé Invalidate () Néanmoins, il ne fonctionne pas.


@anddev Veuillez ouvrir une nouvelle question pour cela, expliquer quel est votre problème et nous donner du code. Cette mise en œuvre fonctionne définitivement!


Yeh le code u fourni fonctionne bien. Mais supposons que je souhaite montrer aux images de sauvegarde sur la toile, puis je dois faire ce canevas.Drawbitmap (bitmaptocanvas, 0f, 0f, null); À l'intérieur de la méthode ONDRAW (Canvas Toivas). Donc, dès que j'ai utilisé ce code, l'annulation et le redo arrêtent de travailler, pourquoi cela se produit et comment résoudre ceci.


Le tableau stocke uniquement les chemins, pas des bitmaps. Vous devez garder une trace des deux. Postez-le comme une nouvelle question et je suis sûr que la communauté vous aidera davantage.


@ Android-Droid Bonjour Peut-on avoir une solution de ce problème?


@Dhavalkhant quel problème?


@gameower lors de l'utilisation de MPAIN.STEXFERMODE (Nouveau PorterDuffXFermode (PorterDuff.Mode.Clear)); Avec ce code, le résultat est des lignes noires. au niveau de l'API <11 pour niveau API> 11 setlayertype (vue.layer_type_software, null); Cela fonctionnera


Qu'est-ce que Circleradius?



4
votes

Un moyen d'implémenter une fonctionnalité DO / REDO consiste à encapsuler un appel de méthode et toutes les infos nécessaires à l'appel dans un objet afin que vous puissiez le stocker et l'appeler plus tard - le modèle de commande .

Dans ce modèle, chaque action a son propre objet: DrawcirCommand, DrawPathCommand, FillcolorCommand, etc. dans chaque objet le tirage au sort ( ) La méthode est implémentée de manière unique, mais est toujours appelée dessinée (toile de toile) qui permet au CommandManager de parcourir les commandes. Pour annuler, vous appelez sur les objets appelant la méthode annulation ();

Chaque objet de commande implémente une interface xxx

un objet ressemblerait à: xxx

}

Vos commandes sont ajoutées à la commande CommandManager: xxx

et pour annuler une commande juste appeler: xxx

Le commandmanager stocke les commandes dans une structure de données, par exemple liste qui lui permet d'itératif sur les objets de commande.

Vous pouvez trouver un tutoriel complet Ici sur la manière d'implémenter le modèle de commande avec do / annuler pour le dessin de toile sur Android.

ici est un autre tutoriel sur la manière dont la mise en oeuvre du modèle de commande en Java;


0 commentaires

1
votes

Heureusement, j'ai résolu ceci aujourd'hui. Je trouve un moyen de faire cela. Questions comme: xxx

dans l'activité. xxx

in xml xxx

Si vous avez une meilleure solution, vous pouvez me contacter.

[Voici mon blog que j'écris dans

http://blog.csdn.net/sky_pjf/article/details/51086901]


0 commentaires