Реализация Dynamic HorizontalScrollView с настраиваемым дочерним элементом View

Я пытаюсь реализовать собственное представление внутри родителя HorizontalScrollView. Пользовательское представление неоднократно рисует линию на своем холсте в зависимости от времени от обработчика. Прямо сейчас пользовательский вид заполняет ширину экрана (ограниченную высотой 548dp), и я хочу, чтобы линия могла выходить за пределы видимого. Кроме того, я хочу, чтобы пользователь мог затем прокручивать по горизонтали, чтобы увидеть больше строки. Я попытался установить ширину HorizontalScrollView на 1500 dp (что намного больше, чем ширина экрана), а затем попытался прокрутить по горизонтали, но он не двигался. Также было бы идеально, если бы представление прокручивалось вместе со строкой, когда она выходит за пределы видимой части экрана.

Я разрабатываю ASUS Transformer с Honeycomb.

Вот соответствующая часть макета, который я использую:

<HorizontalScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="1500dp"
    android:layout_height="548dp"
    android:fillViewport="true" >

    <maavapp.layout.CustomDraw
        android:id="@+id/custom_draw"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </maavapp.layout.CustomDraw>
</HorizontalScrollView>

А вот код класса CustomDraw:

public class CustomDraw extends View {
private static int mSelected;
private ArrayList<Coordinate> measure1;
private ArrayList<Coordinate> measure2;
private ArrayList<Coordinate> measure3;
private boolean north = false, east = true, south = true, west = false;
private DrawHandler dh = new DrawHandler();
private boolean draw = true;
private int width;
private int height;
private int m2;

public CustomDraw(Context context) {
    super(context);
    init();

}

public CustomDraw(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public CustomDraw(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public void init() {        
    measure1 = new ArrayList<Coordinate>();
    measure2 = new ArrayList<Coordinate>();
    measure3 = new ArrayList<Coordinate>();

    mSelected = Constants.MEASURE_1;
    width = 0;
    height = 0;
    m2 = 0;
}

public void setMeasure(int measure) {
    mSelected = measure;
}

public void toggleDraw() {
    draw = !draw;
    if(draw) {
        updateLine();
    }
}

public boolean isDrawing() {
    return draw;
}

public void updateLine() {
    // grab new coordinates for each measure
    /*new_coord(measure1);
    new_coord(measure2);
    new_coord(measure3);*/

    if(measure1.isEmpty() && measure2.isEmpty() && measure3.isEmpty()) {
        measure1.add(new Coordinate(0, 0));
        measure2.add(new Coordinate(0, 0));
        measure3.add(new Coordinate(0, 0));
    } else {
        Coordinate last_coord = measure1.get(measure1.size() - 1);

        measure2.add(new Coordinate(++m2, 25));

        /*if(last_coord.x >= width) {
            east = false;
            west = true;
        } else if(last_coord.x <= 0) {
            east = true;
            west = false;
        }*/

        if(last_coord.y >= height) {
            south = false;
            north = true;
        } else if(last_coord.y <= 0) {
            south = true;
            north = false;
        }

        Log.d("MAAV", "last_coord.x + 3: " + (last_coord.x + 3));
        Log.d("MAAV", "last_coord.y + 3: " + (last_coord.y + 3));

        if(south && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y + 3));
        } else if(south && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y + 3));
        } else if(north && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y - 3));
        } else if(north && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y - 3));
        }
    }

    if(draw) {
        dh.sleep(10);
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    this.width = w;
    this.height = h;
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    Paint p = new Paint();
    p.setStyle(Paint.Style.FILL);

    p.setColor(Color.WHITE);
    c.drawPaint(p);
    p.setColor(Color.BLACK);

    switch(mSelected) {
    case Constants.MEASURE_1:
        for(int i = 0; i < measure1.size(); i++) {
            Coordinate coord = measure1.get(i);
            Log.d("MAAV", "drawing coord.x, coord.y: " + (coord.x) + ", " + (coord.y));
            c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);  
        }
        break;
    case Constants.MEASURE_2:
        for(int i = 0; i < measure2.size(); i++) {
            Coordinate coord = measure2.get(i);
            c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);
        }
        break;
    case Constants.MEASURE_3:
        for(int i = 0; i < measure2.size(); i++) {
            Coordinate coord = measure2.get(i);
            c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);
        }
        break;
    }

}

class DrawHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        CustomDraw.this.updateLine();
        CustomDraw.this.invalidate();
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}
}

Спасибо за любую помощь!


comment
-1 за то, что дважды задал один и тот же вопрос через полчаса... stackoverflow.com/questions/10214244/   -  person Shankar Agarwal    schedule 18.04.2012
comment
Опять же, я объяснил вам, что это другой вопрос. Кроме того, поскольку я принял другой вопрос, я не хотел терять интерес к новому вопросу, просто редактируя старый.   -  person Jon Rubins    schedule 18.04.2012
comment
Спасибо за то, что вы были непродуктивны и сосредоточились только на том факте, что я задал аналогичный вопрос, вместо того, чтобы на самом деле понять, что я прошу о помощи и предпочел бы получить ответ, чем бесполезные комментарии. Я чувствую, что -1 должен быть для вопросов, которые показывают отсутствие отсутствия внешних исследований или усилий, которые, я думаю, я сделал. Я бы попросил вас подумать о том, почему вы что-то -1 и как это на самом деле способствует.   -  person Jon Rubins    schedule 18.04.2012


Ответы (1)


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

Чтобы заставить пользовательский вид прокручиваться, мне пришлось добавить оболочку LinearLayout вокруг моего пользовательского вида. Не уверен на 100%, почему.

Кроме того, хотя я объявляю фиксированный размер для своего пользовательского представления (в XML-файле ниже), я могу динамически обновлять его в своем коде, используя:

CustomDraw.this.setLayoutParams(new LinearLayout.LayoutParams(width + {adjust size}, height));

где «ширина» и «высота» — это ширина и высота пользовательского представления. Опять же, не уверен, почему я должен говорить "new LinearLayout.LayoutParams(...);" но это то, что, кажется, работает.

Вот xml, который я использую:

<HorizontalScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scroller"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fillViewport="true" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="548dp"
        android:orientation="vertical" >

        <maavapp.layout.CustomDraw
            android:id="@+id/custom_draw"
            android:layout_width="4800dp"
            android:layout_height="fill_parent" >
        </maavapp.layout.CustomDraw>
    </LinearLayout>
</HorizontalScrollView>

И вот соответствующие части пользовательского кода класса, который я использую:

public class CustomDraw extends View {
// member variables

public void setHSV(HorizontalScrollView hsv) {
    this.hsv = hsv;
}

public void updateLine() {
    if(measure1.isEmpty()) {
        measure1.add(new Coordinate(0, 0));
    } else {
        Coordinate last_coord = measure1.get(measure1.size() - 1);

                    // calculate south, north, east, and west

        if(((last_coord.x + 3) % 1200 == 0) 
                || ((last_coord.x + 3) % 1200 == 1) 
                || ((last_coord.x + 3) % 1200 == 2)
                || ((last_coord.x + 3) % 1200 == 3) && (last_coord.x + 3 >= 1200)) {
            hsv.smoothScrollTo(last_coord.x - 50, 0);
        }
        if(last_coord.x >= (width - 100)) {
            this.setLayoutParams(new LinearLayout.LayoutParams(width + 4800, height));
            width += 4800;
        }

        if(south && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y + 3));
        } else if(south && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y + 3));
        } else if(north && east) {
            measure1.add(new Coordinate(last_coord.x + 3, last_coord.y - 3));
        } else if(north && west) {
            measure1.add(new Coordinate(last_coord.x - 3, last_coord.y - 3));
        }
    }

    if(draw) {
        dh.sleep(10);
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    this.width = w;
    this.height = h;
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    Paint p = new Paint();
    p.setStyle(Paint.Style.FILL);

    p.setColor(Color.WHITE);
    c.drawPaint(p);
    p.setColor(Color.BLACK);

        Coordinate coord;
    for(int i = 0; i < measure1.size(); i++) {
        coord = measure1.get(i);
        c.drawRect(coord.x, coord.y, coord.x + 3, coord.y + 3, p);  
    }
}

class DrawHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        CustomDraw.this.updateLine();
        CustomDraw.this.invalidate();
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}
}
person Jon Rubins    schedule 19.04.2012