Рисуемое SeekBar не рисуется после повторного использования Адаптером - PullRequest
2 голосов
/ 14 июня 2011

Мне нужно нарисовать оверлейное изображение на SeekBar в моих ListView строках. Это не так уж сложно сделать, и код в этом вопросе выполняет это, рисуя номер строки в растровом изображении и помещая его как прорисовываемый прогресс.

Проблема, с которой я столкнулся, заключается в том, что это работает только один раз. Когда вид используется повторно для использования в другом ряду, чертеж исчезает.

enter image description here

Первые 10 просмотров (позиции от 0 до 9) сработали. Все после этого терпит неудачу. Там нет ошибки или исключения. Android просто перестает рисовать этот слой. Если я прокручиваю вниз, а затем назад, то ни один из них не работает (так как все они были переработаны).

Как заставить Android всегда рисовать это наложенное изображение? Я предполагаю, что мне нужно выполнить какое-то кэширование или аннулирование, но я просто пока не знаю, что это такое.

public class ViewTest extends ListActivity {
    // replace the progress drawable with my custom drawable
    public void setSeekBarOverlay(SeekBar seekBar, String overlayText) {
        Bitmap bitmap = Bitmap.createBitmap(100, 12, Bitmap.Config.ARGB_4444);
        new Canvas(bitmap).drawText(overlayText, 10, 12, new Paint());

        Drawable d = new BitmapDrawable(bitmap);
        ((LayerDrawable) seekBar.getProgressDrawable()).setDrawableByLayerId(android.R.id.progress, d);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setListAdapter(new ListAdapter() {

            // return the view. Recycle them if possible.
            public View getView(int pos, View v, ViewGroup vg) {
                if (v == null) {
                    v = View.inflate(ViewTest.this, R.layout.seekbar, null);
                }

                String s = String.valueOf(pos);
                ((TextView) v.findViewById(android.R.id.text1)).setText(s);
                setSeekBarOverlay((SeekBar) v.findViewById(R.id.seekbar), s);
                return v;
            }

            ... cut ...
        });
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<ListView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

seekbar.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight">

    <TextView
        android:id="@android:id/text1"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_height="wrap_content" />
    <SeekBar
        android:id="@+id/seekbar"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content" />
</LinearLayout>

1 Ответ

4 голосов
/ 14 июня 2011

Это сложный вопрос, и я не думаю, что он получит большой трафик, поэтому я собираюсь ответить на него сам, так как нашел решение.

Еще один вопрос / ответ, AndroidProgressBar.setProgressDrawable работает только один раз? , я попал на полпути, но решение не сработало для меня.В другом вопросе код пытался заменить весь progressDrawable (setProgressDrawable()).Я не делаю этого здесь, так как я просто обновляю слой в существующем progressDrawable.Поработав с похожими подходами, я нашел кое-что, что сработало.Вы должны получить границы обновляемого объекта рисования (в данном случае - один из слоев) и установить границы позже.

Похоже, ошибка в платформе, но этот обходной путь, кажется, делает этоРабота.Надеюсь, это когда-нибудь поможет кому-то еще.

public void setSeekBarOverlay(SeekBar seekBar, String overlayText) {
    LayerDrawable layerDrawable = (LayerDrawable) seekBar.getProgressDrawable();
    Drawable overlayDrawable = layerDrawable.findDrawableByLayerId(android.R.id.progress);
    Rect bounds = overlayDrawable.getBounds();

    Bitmap bitmap = Bitmap.createBitmap(100, 12, Bitmap.Config.ARGB_4444);
    new Canvas(bitmap).drawText(overlayText, 10, 12, new Paint());
    overlayDrawable = new BitmapDrawable(bitmap);

    overlayDrawable.setBounds(bounds);
    layerDrawable.setDrawableByLayerId(android.R.id.progress, overlayDrawable);
}
...