Android — пользователь рисует линии пальцем

Я хочу создать инструмент на Android, где пользователь может рисовать простые объекты поверх изображения (например, линию, круг или стрелку). Сначала я начал пробовать линейную часть, и мне действительно удалось ее нарисовать. Логика заключается в том, что пользователь нажимает в одной точке, а затем проводит пальцем, рисуя линию. Я использую такой класс (он основан на ответе DonGru здесь ):

public class DrawView extends View {
    Paint paint = new Paint();
    float Sx, Sy, Lx, Ly;

    public DrawView(Context context, float x1, float y1, float x2, float y2) {
        super(context);

        paint.setColor(Color.RED);
        Sx=x1;
        Sy=y1;
        Lx=x2;
        Ly=y2;   
    }

    @Override
    public void onDraw(Canvas canvas) {
            canvas.drawLine(Sx, Sy, Lx, Ly, paint);
    }
}

Из кода действия я использую прослушиватель onTouch следующим образом:

@Override
public boolean onTouch(View view, MotionEvent event) { 
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Sx1 = event.getX();
            Sy1 = event.getY();
            return true;

        case MotionEvent.ACTION_MOVE:
            Cx1 = event.getX();
            Cy1 = event.getY();
            drawLine();
            return true;

        case MotionEvent.ACTION_UP:
            Lx1 = event.getX();
            Ly1 = event.getY();
            return true;
        }
    return false;
}

public void drawLine(){

    setContentView(R.layout.show);
    ImageView myImage = (ImageView) findViewById(R.id.lastphoto);
    myImage.setImageBitmap(rotatedPic);

    dv=new DrawView(this, Sx1, Sy1, Cx1, Cy1);

    addContentView(dv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
            ViewGroup.LayoutParams.FILL_PARENT));

    RelativeLayout mRelativeLayout = (RelativeLayout) findViewById(R.id.linear);
    mRelativeLayout.setOnTouchListener((OnTouchListener) this);
    mRelativeLayout.addView(new Drawer(this));   
}

При каждом движении я воссоздаю весь вид, чтобы была видна только одна линия от начальной до конечной точки. Моя первая проблема заключается в том, что я не знаю, верна ли эта реализация. Кроме того, я хочу, чтобы эти строки после создания обрабатывались как объекты. Пользователь должен иметь возможность перемещать их, вращать, удалять и т. д. Я думаю, что могу сделать это, удерживая координаты краев каждой строки в чем-то вроде буфера, и если пользователь коснется очень близко к одному краю, я могу справиться с этим жестом. Но все это звучит слишком сложно, и я не знаю, нестабильно ли это.

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


person george    schedule 17.05.2012    source источник
comment
Ваша реализация странная. Для реализации такой программы вам нужен View, переопределить его метод onDraw, обработать движения перетаскивания пользователя и соответственно вызвать View.invalidate().   -  person neevek    schedule 17.05.2012
comment
Вы имеете в виду создать объект, который расширяет представление? Как DrawView, который у меня есть как класс, который рисует? Но вызов недействительного экземпляра этого объекта не стирает прежние строки. У вас есть ссылка на какой-нибудь пример, чтобы я мог понять, что вы имеете в виду?   -  person george    schedule 17.05.2012


Ответы (1)


Сохранение нарисованных линий и предоставление пользователю возможности манипулировать ими, на мой взгляд, является умеренно сложным.

Создайте класс Line. Включите начальные и конечные координаты, цвет и т. д. в качестве полей класса и методов для удаления, перемещения и т. д. Также добавьте метод, который принимает аргумент MotionEvent. В этом методе вы используете MotionEvent, чтобы определить, была ли затронута эта линия, и настроить ее положение по мере необходимости.

Храните ссылки на каждую нарисованную линию (созданную как экземпляр класса Line) в коллекции или списке какого-либо вида в вашем расширенном классе View, ArrayList должен это делать. Затем в событии onTouch вызовите метод обнаружения касания каждой строки и передайте MotionEvent методам.

Наконец, переопределите обратный вызов onDraw представления, чтобы отрисовывать каждую линию, перебирая коллекцию ссылок на экземпляры Line.

Вы также можете добавить больше жестов, таких как длительное нажатие для удаления и т. д. Вот (совершенно непроверенный, написанный по памяти) скелет такого подхода.

class Line

    public float x1, x2, y1, y2;

    public void detectTouch(MotionEvent motionEvent){

         // code to detect a touch and adjust the x and ys accordingly

    }

class DrawView extends View{

    private ArrayList<Line> lines = new ArrayList<Lines>();

    ....
    ....

@Override
public void onDraw(Canvas canvas) {

    super.onDraw();

    for (Line line : lines){
         canvas.drawLine(line.x1,line.y1,line.x2,line.y2);
    }
}

@Override
public boolean onTouch(View view, MotionEvent event) {

    ....
    ....

    for (Line line : lines){
        line.detectTouch(MotionEvent);
    }


}

Веселиться!

person Simon    schedule 17.05.2012
comment
это кажется очень многообещающим, спасибо! Я попробую и дам вам знать - person george; 17.05.2012
comment
основываясь на вашем совете, мне удалось заставить его работать очень хорошо до сих пор! Большое спасибо! - person george; 21.05.2012
comment
Привет, Джордж. Приятно слышать, что это помогло. Удачи,,, - person Simon; 21.05.2012
comment
Привет, можешь дать полный код демонстрации.. Чтобы переместить анимацию слева направо, добавьте новую строку слева.. - person Gautam Vasoya; 25.07.2012
comment
Я хочу развиваться так: Перейдите по этой ссылке - person Gautam Vasoya; 25.07.2012
comment
@Simon Саймон, возможно ли ограничить этот рисунок пальцем формой на заднем плане? скажем, контур алфавита «а» или «б» изображения? как мы должны это сделать? - person apostleofzion; 12.05.2016