Маркер строки ListView аля GMail - PullRequest
3 голосов
/ 20 мая 2011

Я заинтересован в создании ListView, где каждая строка помечается так, как это делается в GMail для 3.0+.Это создает хорошее разделение на левый и правый ListFragment.

Другие примеры включают также Календарь Google на 2.3.4, например, где цветной маркер находится слева от ListView.

GMail ListView

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

Я знаю, что я мог бы сделать что-то вроде вставки туда ImageView и затем залить его тем цветом, который я хотел бы, номне кажется, что это отвратительный взлом.

Другой вопрос также был бы, если есть обобщенный способ объединить два фрагмента ListView так, как это делают приложения GMail или Mail.

GMail ListView across two fragments

Ответы [ 3 ]

1 голос
/ 20 мая 2011

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

Вот 2 метода:

1 - Использование StateListDrawable для фона строки:

В этом случае я бы создал файл макета строки списка и установил для свойства "background" значение StateListDrawable (может бытьXML).Это позволит строке переключать визуальные состояния для выбранного и не выбранного.

Атрибутом «drawable» для StateListDrawable будет PNG из 9 патчей, один для невыбранного состояния, которое не содержит полей, и один для выбранного ... выбранный будет определять поле в пределахсам PNG, указав область содержимого / нижнюю черную линию, чтобы она не доходила полностью до левой стороны PNG, оставляя область, которая является вашим немасштабированным полем.

Для людей, которые находят это,Рэдли Маркс только что опубликовал отличный пост по 9 патчу: http://radleymarx.com/blog/simple-guide-to-9-patch/

В ListViews иногда бывает так, что вы хотите отключить «listSelector» (который представляет собой отдельную сущность, отображаемую над списком или позади).и вместо этого используйте атрибут «duplicateParentState», чтобы позволить самой строке отображать выбор (селектор списка не нужен).Это может обеспечить немного больше творческой свободы, особенно если вы хотите иметь поля переменной ширины в определенных строках или несколько типов строк, которые выглядят по-разному.Хотя всецело зависит от дизайна.

2 - Использование полей для каждой строки:

Если вы решили, что вам нужно несколько типов цветовых индикаторов и т. Д., Возможно, вам придется использовать другой подход, предоставляя атрибут margin (который, вероятно, не будет работать сразу) ... Это относится к тому, как LayoutParams используются системой макетов.Я пытаюсь вспомнить точные детали, но я думаю, что это связано с различными типами подкласса LayoutParam и свойствами MarginLayoutParam (или его подкласса), например marginLeft, может быть проигнорирован кодом макета ListView.Вы должны использовать экземпляр AbsListView.LayoutParams, который не содержит параметров для полей.Одним из способов является вложение вашей строки в контейнерное представление (подкласс), которое допускает поля в его LayoutParams *.Я уверен, что я не закончил делать это посторонним вложением, но мне придется покопаться в некотором коде, чтобы запомнить лучшее решение.

Вы упоминаете о том, что поместили ImageView и залили его цветом.Есть несколько альтернатив, на которые вы могли бы обратить внимание ... Наиболее производительным, вероятно, было бы определение собственного класса ListRow и использование onDraw () для фактического рисования содержимого строки самостоятельно, canvas.draw_xyz () для рисования маленькой вкладки цвета,и рисовать текст и т. д. для остальных, а не строить строки в составном макете.Второй метод с использованием макетов будет иметь более легкий веснапример.

* Золотое правило в макете Android: сложная иерархия пользовательского интерфейса - это смерть для производительности, особенно с такими вещами, как ListView.Часто можно избежать этого, используя другие вещи: RelativeLayout, drawableTop (и т. Д.), Изображения с 9-патчами, вместо добавления большего количества видов.

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

1 голос
/ 20 мая 2011

Если вам нужна скорость, то я бы выбрал вариант использования пользовательского класса View (например, extension RelativeLayout) для контейнера строк View и переопределение метода dispatchDraw(Canvas canvas).

The dispatchDraw метод вызывается после , когда представление извлекает свое собственное содержимое, и до рисует свои дочерние элементы - дочерние элементы рисуются, когда вы вызываете super.dispatchDraw.

Использованиечтобы сделать что-то вроде

private boolean mDrawMarker = false;

public void setShouldDrawMarker(boolean drawMarker) {
    mDrawMarker = drawMarker;
}
public boolean getShouldDrawMarker() {
    return mDrawMarker;
}

@Override
public void dispatchDraw(Canvas canvas) {
    // draw the children of our view 
    super.dispatchDraw(canvas);

    // draw our marker on top of the children if needed
    if (mDrawMarker) {
        // e.g. canvas.drawRect(...) or canvas.drawBitmap(...)
    }
}

Таким образом, вы избежите добавления каких-либо дополнительных представлений в иерархию, что означает, что вы не будете подвергаться каким-либо штрафам на этапах макета или измерения.Не забывайте повторно использовать объекты Paint и Rect, если рисуете прямоугольник, а не каждый раз создаете новый.Точно так же, если вы используете растровое изображение, вы должны совместно использовать один и тот же экземпляр растрового изображения во всех экземплярах своего просмотра, а не загружать новый каждый раз из своих ресурсов (это означает , а не означает, что они помещаются в static поля)

Для отступов элементов, так как в этом случае списки, кажется, не перекрываются, вы могли бы (от макушки головы):

  • Установить левое поле наконтейнер строк (не совсем уверен, что это будет работать)
  • Оберните контейнер строк в LinearLayout и установите для него отступ слева (если вышеописанное не работает)
  • Используйтепользовательский класс представления (если установка левого поля не работает)
  • Используйте предложение @commonsware и используйте два представления - одно слева с серым цветом фона, а другое справа от этого с цветом маркера- затем просто установите вид слева в видимый / ушедший, если вы хотите сделать отступ / нет отступа

Что касается перекрытия видов во втором примере, я отложу @commonsware ответ.

0 голосов
/ 20 мая 2011

Как можно достичь чего-то подобного?

С манжеты я бы использовал View с нужным цветом фона, видимым, когда вы этого хотите, и невидимым, когда вы этого не делаете.

Бонусом будет также переменная ширина, но я думаю, что это только меньшее изменение макета.

Я не знаю, что вы подразумеваете под "переменной шириной". Я думаю, что есть два Views с желаемым цветом фона по горизонтали LinearLayout, и только один видимый.

Я знаю, что мог бы сделать что-то вроде вставки туда ImageView, а затем залить его тем цветом, который мне хотелось бы, но мне кажется, что это безобразный хак.

Ну, ImageView немного тяжелее, чем нужно. В противном случае я не понимаю, почему это взломать. Думайте о них как о значках, которые просто бывают высокими, тонкими, серыми и не всегда нужны.

Другой вопрос будет также, если есть обобщенный способ объединить два фрагмента ListView так, как это делают приложения GMail или Mail.

Используйте RelativeLayout, чтобы правый фрагмент мог плавать над левым фрагментом.

...