#android #android-layout #android-listview #android-3.0-honeycomb #android-fragments
#Android #android-макет #android-listview #android-3.0-honeycomb #android-фрагменты
Вопрос:
Я заинтересован в создании ListView, где каждая строка помечена так, как это сделано в GMail для версии 3.0 . Это создает хорошее разделение левого и правого фрагментов списка.
Другие примеры включают также Календарь Google на 2.3.4, например, где цветной маркер находится слева от ListView.
Посмотрите на серый вертикальный разделитель между двумя списками. Как достичь чего-то подобного? Бонусом была бы также переменная ширина, но я думаю, что это всего лишь меньшее изменение макета.
Я знаю, что, вероятно, мог бы сделать что-то вроде вставки ImageView туда, а затем залить его цветом, который я хотел бы, но мне кажется, что это уродливый взлом.
Другой вопрос был бы также в том, существует ли обобщенный способ каким-либо образом объединить два фрагмента ListView, как это делают приложения GMail или Mail.
Ответ №1:
Если вам нужна скорость, то я бы предпочел использовать пользовательский класс просмотра (например, extend RelativeLayout
) для представления контейнера строк и переопределить dispatchDraw(Canvas canvas)
метод.
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
, если рисуете прямоугольник, а не создаете каждый раз новый. Аналогично, если вы используете bitmap, вы должны использовать один и тот же экземпляр Bitmap во всех экземплярах вашего представления, а не загружать каждый раз новый из ваших ресурсов (это не означает размещение их в static
полях)
Для отступов элементов, поскольку в этом случае списки, похоже, не перекрываются, вы могли бы (с моей точки зрения):
- Установите левое поле в контейнере строк (не совсем уверен, что это сработает)
- Оберните контейнер строк в
LinearLayout
и установите для этого левое заполнение (если вышеупомянутое не работает) - Используйте пользовательский класс просмотра (если установка левого поля не работает)
- Воспользуйтесь предложением @commonsware и используйте два вида — один слева с серым цветом фона, а другой справа от него с цветом маркера — затем просто установите вид слева на видимый / отсутствующий, если вы хотите, чтобы отступ / без отступа
Что касается перекрытия представлений во втором примере, я отложу ответ на @commonsware.
Ответ №2:
Пожалуйста, скажите мне, правильно ли я понял проблему…. Вы хотели бы пометить определенные строки как выделенные, и выбранные строки визуально выглядят с отступом (с другим цветом и полями)?
Вот 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(), чтобы нарисовать маленькую цветную вкладку и нарисовать текст и т.д. Для всего остального, А не создавать строку в составном макете. Второй способ использования макетов заключался бы в том, чтобы иметь более легкий <View layout_height=»match_parent» layout_width=»4dip» background = «#ffff0000» /> например.
* Золотое правило верстки Android: сложная иерархия пользовательского интерфейса снижает производительность, особенно в таких приложениях, как ListView. Часто этого можно избежать, используя другие вещи: RelativeLayout, drawableTop (etc), изображения с 9 исправлениями, Вместо добавления дополнительных просмотров.
Если я неправильно понял, и вышесказанное слишком простое, пожалуйста, не могли бы вы предоставить более подробную информацию, возможно, диаграмму, указывающую точную часть, которую вам нужно воспроизвести.
Ответ №3:
Как достичь чего-то подобного?
Сразу скажу, я бы использовал a View
с желаемым цветом фона, видимым, когда вы этого хотите, и невидимым, когда вы этого не хотите.
Бонусом была бы также переменная ширина, но я думаю, что это всего лишь меньшее изменение макета.
Я не знаю, что вы подразумеваете под «переменной шириной». Я думаю, что есть два, Views
с желаемым цветом фона по горизонтали LinearLayout
, при этом виден только один.
Я знаю, что, вероятно, мог бы сделать что-то вроде вставки ImageView туда, а затем залить его цветом, который я хотел бы, но мне кажется, что это уродливый взлом.
Ну, ImageView
это немного тяжелее, чем необходимо. В противном случае я не понимаю, почему это взлом. Думайте о них как о значках, которые просто бывают высокими, тонкими, серыми и не всегда нужны.
Другой вопрос был бы также в том, существует ли обобщенный способ каким-либо образом объединить два фрагмента ListView, как это делают приложения GMail или Mail.
Используйте RelativeLayout
, чтобы правый фрагмент мог располагаться поверх левого фрагмента.
Комментарии:
1. Значит, этот белый маркер является частью правого фрагмента и просто рисуется поверх левого? Что также означает, что в этом случае я должен синхронизировать рисование правого с положением прокрутки левого.
2. Спасибо за подсказку. На самом деле, если вы выберете самый верхний элемент и прокрутите его до самого верха, вы увидите, что белый маркер исчезает. Он является частью левого фрагмента и нарисован поверх правого.
3. @Joa Ebert: «Значит, этот белый маркер является частью правого фрагмента и просто рисуется поверх левого?» — это один из подходов. Я запустил свой XOOM и более внимательно посмотрел на пользовательский интерфейс в реальном времени, в отличие от вашего фрагмента скриншота. Если вертикальная серая линия, разделяющая два фрагмента, является частью
ListFragment
слева, то наконечник стрелки также может быть частью этого фрагмента, как часть выбранной строки.