Поделиться через


Фирменное оформление ListView

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. В случае разработки приложений для Windows 10 см. раздел последняя документация]

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

Здесь мы поговорим о том, как настроить целевую страницу вашего приложения с помощью следующих методов.

  • Изменение шаблонов элементов ListView
  • Изменение размеров элементов ListView
  • Добавление анимации элементов ListView

В этой теме показано, как начать с шаблона Приложение таблицы Visual Studio и изменить его, чтобы создать целевые страницы наподобие следующих.

Целевая страница Contoso Bakery

Пример Contoso Food Truck

Требования к читателю

Использование ListView

Прежде всего нужно решить, какие элементы управления вы будете использовать на своей целевой странице. Список элементов управления для HTML-кода и библиотеки Windows для JavaScript см. в разделе Список элементов управления.

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

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

Макет сетки CSS3 и система сетки Windows 8

Система сетки является важной частью внешнего вида и удобства использования Windows 8. Она помогает добиться визуального единства среди различных приложений и функций. С помощью макета сетки вы можете разделить пространство страницы для элементов и легко выровнять их по вертикали и горизонтали.

В нашем примере мы также используем Макет «Сетка» каскадных таблиц стилей третьего поколения (CSS3), отличающийся от ListView макета сетки элемента управления. Макет "Сетка" CSS3 предоставляет стили сетки общего назначения для широкого спектра применения, тогда как ListView используется только для отображения наборов данных. С помощью макета "Сетка" CSS3 вы можете легко выровнять элементы вашего приложения на сетке.

Пример Contoso French Bakery

Рассмотрим шаблон Grid App Visual Studio по умолчанию и сравним его с примером Contoso French Bakery из статьи Создание фирменной символики в приложениях Магазина Windows. Вот снимок экрана шаблона Grid App:

Приложение, использующее шаблон “Приложение таблицы”

Сравним его с целевой страницей Contoso French Bakery из статьи Создание фирменной символики в приложениях Магазина Windows. Элементы приложения Contoso French Bakery располагаются настраиваемым способом, подчеркивающим торговую марку Contoso.

Целевая страница Contoso Bakery

Хотя внешний вид целевой страницы Contoso French Bakery существенно отличается от шаблона Grid App, отличия заключаются в нескольких изменениях HTML или CSS. В этом примере мы предполагаем, что элементы являются интерактивными и что при выборе элемента пользователь попадает на страницу группы, на которой можно выбрать тип макарон, кексов и т. д. Элемент управления ListView, использующий макет сетки, хорошо подходит для этой целевой страницы.

Чтобы преобразовать шаблон Grid App в целевую страницу Contoso, нам нужно изменить размер шаблонов элементов, увеличить размеры изображений и добавить описания элементов.

  1. В Visual Studio создайте новое приложение, использующее шаблон Grid App.

  2. Обновите itemtemplate для HTML-кода в groupedItems.html. Основное отличие от шаблона itemtemplate по умолчанию заключается в добавлении третьего элемента заголовка для отображения описания всех элементов.

        <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
            <div class="item">
                <img class="item-image" src="#" 
                     data-win-bind="src: backgroundImage; alt: title" />
                <div class="item-text">
                    <h3 class="item-title" data-win-bind="textContent: title"></h3>
                    <h6 class="item-subtitle win-type-ellipsis" 
                        data-win-bind="textContent: subtitle"></h6>
                    <h6 class="item-detail" data-win-bind="textContent: description"></h6>
                </div>
            </div>
        </div>
    
  3. Теперь мы обновим стили в groupedItems.css. Основное отличие от groupedItems.css заключается в помещении текста div под изображением вместо наложения его поверх изображения, а также в добавлении еще одной строки к сетке для описания элемента.

    .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface {
            margin-bottom: 60px;
            /* Decreased margin */
            margin-left: 35px;
            margin-right: 115px;
    }   
    .groupeditemspage .groupeditemslist .item {
           /* Changed row size and item size, centered text and changed text color */ 
            -ms-grid-columns: 1fr;
            -ms-grid-rows: 1fr 1280px;
            display: -ms-grid;
            height: 600px500px;
            width: 350px;
            text-align: center;
            color: rgb(160,160,160);
    
        }
    
            .groupeditemspage .groupeditemslist .item .item-image {
                   /* Increased image size and altered padding */
                height: 340px;
                width: 340px;
                padding: 0px 5px 20px 5px;
            }
    
            .groupeditemspage .groupeditemslist .item .item-text {
                /* Added a row to the grid and changed height and padding */
                -ms-grid-row: 2;
                -ms-grid-rows: 30px 21px 1fr;
                display: -ms-grid;
                padding: 30px 15px 2px 15px;
                height: 150px;
            }
    
                .groupeditemspage .groupeditemslist .item .item-text .item-title {
                    /* Changed font color */
                    -ms-grid-row: 1;
                    overflow: hidden;
                    font-size: 16pt;
                    color: rgb(200,200,200);
                }
    
                .groupeditemspage .groupeditemslist .item .item-text .item-subtitle {
                    -ms-grid-row: 2;
                }
                .groupeditemspage .groupeditemslist .item .item-text .item-detail {
                    /* All new CSS for the detail text */
                    -ms-grid-row: 3;
                    overflow:hidden;
                    padding-top: 20px;
                    height: 60px;
                    margin-left: 30px;
                    margin-right: 30px;
                }
    
  4. Удалите заголовки групп из data.js. Проще всего просто удалить заголовок каждой группы.

После этих изменений ваше приложение будет выглядеть следующим образом:

Обновленное приложение

Добавьте изображения, а также измените фон и заголовок. Целевая страница Contoso French Bakery готова!

Пример Contoso Food Truck

В следующем примере мы создадим целевую страницу Contoso Food Truck из шаблона Grid App.

Пример Contoso Food Truck

Целевая страница Contoso Food Truck привлекает внимание пользователя эффектными изображениями различных размеров.

В отличие от предыдущего примера для этой целевой страницы нужно добавить к шаблону некоторый код на JavaScript, главным образом, добавить логику для поддержки различных размеров элементов в ListView. Мы опять подразумеваем, что элементы на целевой странице являются интерактивными и что при выборе элемента пользователь попадает на страницу с подробными сведениями об этом элементе. Для этой работы хорошо подходит элемент управления ListView, использующий макет сетки. Мы снова используем шаблон Grid App в качестве отправной точки.

Чтобы использовать элементы различных размеров, мы сначала должны определиться с минимальной базовой единицей измерения. С помощью этой единицы мы будем создавать все элементы сетки, таким образом размеры всех элементов сетки будут кратны размеру сетки. Минимальный размер одного из элементов на следующем изображении является высотой элементов в разделе "Рядом", составляющей около 80 пикселей. Горизонтальные размеры допускают большую гибкость. Для простоты мы будем также использовать 80 пикселей для горизонтальных размеров.

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

Размер базовой единицы

Размер каждого элемента должен быть кратен базовой единице, включая заполнение между единицами. Формула:

item sizeₓ = m * base unit sizeₓ + (m -1) * item padding

item sizey = m * base unit sizey + (m -1) * item paddingy

где m — положительное целое число, а x и y означают размеры элемента по осям x и y и заполнение элемента.

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

  1. В Visual Studio создайте новое приложение, использующее шаблон Grid App.

  2. В groupedItems.html создайте новый шаблон элемента с именем multisizebaseitemtemplate. Этот шаблон элемента похож на шаблон элемента по умолчанию, но снабжен заголовком с описанием элемента, что позволяет нам добавить описание элемента к заголовку и подзаголовку целевой страницы.

      <!-- Template tutorial HTML -->
        <div class="multisizebaseitemtemplate" data-win-control="WinJS.Binding.Template">
            <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
            <div class="item-overlay">
                <h4 class="item-title" data-win-bind="textContent: title"></h4>
                <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
                <h6 class="item-description" data-win-bind="textContent: description"></h6>
            </div>
        </div>
    
  3. В groupedItems.js создайте функцию формирования шаблонов с именем multisizeItemTemplateRenderer перед определением PageControl (ui.Pages.define).

    Мы используем эту функцию, чтобы преобразовать для просмотра элементы ListView. Именно эта функция определяет, какие элементы используют тот или иной шаблон. Мы назначаем его свойству itemTemplate элемента управления ListView на более позднем этапе.

     function multisizeItemTemplateRenderer(itemPromise) {
            return itemPromise.then(function (currentItem) {
                var content;
                // Grab the default item template used on the groupeditems page.
                content = document.querySelector(".multisizebaseitemtemplate");
                var result = content.cloneNode(true);
    
                // Change the CSS class of the item depending on the group, then set the size in CSS.
                switch (currentItem.groupKey) {
                    case "group1":
                        {
                            // For the first item, use the largest template.
                            if (currentItem.index == 0) {
                                result.className = "largeitemtemplate"
                            }
                            // Use the mediumlarge template for the second item
                            else if (currentItem.index == 2) {
                                result.className = "mediumlargeitemtemplate"
                            }
                            // Use the medium template for the third item, and any other items
                            else {
                                result.className = "mediumitemtemplate"
                            }
                            break;
                        }
                    default:
                        {
                            // Use the small template for the second group
                            result.className = "smallitemtemplate"
                        }
                }
                // Because we used a WinJS template, we need to strip off some attributes 
                // for it to render.
                result.attributes.removeNamedItem("data-win-control");
                result.attributes.removeNamedItem("style");
                result.style.overflow = "hidden";
    
                // Because we're doing the rendering, we need to put the data into the item.
                // We can't use data binding.
                result.querySelector(".item-image").src = currentItem.data.backgroundImage;
                result.querySelector(".item-title").textContent = currentItem.data.title;
                result.querySelector(".item-subtitle").textContent = currentItem.data.subtitle;
                result.querySelector(".item-description").textContent = currentItem.data.description;
                return result;
            });
        }
    
  4. В groupedItems.js добавьте функцию groupInfo также вне определения страницы. Эта функция позволяет ListView использовать в представлении элементы различных размеров и указывает базовый размер элементов. Базовый размер — это наименьший элемент, представленный в списке. Чтобы макеты работали должным образом, другие элементы должны быть кратны этому размеру.

     function groupInfo() {
        return {
            enableCellSpanning: true,
            cellWidth: 80,
            cellHeight: 80
        };
     }
    
  5. Теперь нам нужно прицепить эти новые функции к элементу управления ListView.

    1. В groupedItems.js измените функцию _initializeLayout, чтобы отображать плоский список групп.

      // Add the itemTemplate parameter as shown.
      _initializeLayout: function (listView, viewState, itemTemplate) {
          if (viewState === appViewState.snapped) {
              listView.itemDataSource = Data.groups.dataSource;
              listView.groupDataSource = null;
      
              // Add the following line of code.
              listView.itemTemplate = itemTemplate;
      
              listView.layout = new ui.ListLayout();
          } else {
      
                      listView.itemDataSource = Data.items.dataSource;
                      listView.groupDataSource = Data.groups.dataSource;
                      listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
      
              // Add the following two lines of code.
              listView.itemTemplate = multisizeItemTemplateRenderer;
              listView.layout = new ui.GridLayout({ groupInfo: groupInfo, groupHeaderPosition: "top" });
          }
      },
      
    2. Удалите строку, назначающую шаблон элемента для ListView, и внесите изменения, указанные в примечаниях кода.

      ready: function (element, options) {
          var listView = element.querySelector(".groupeditemslist").winControl;
      
          // Add the next line of code to retrieve the item template. 
          var itemTemplate = element.querySelector(".itemtemplate");
      
          listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
      
          listView.oniteminvoked = this.itemInvoked.bind(this);
              listView.itemTemplate = element.querySelector(".itemtemplate");
      
          // Change the last argument of the _initializeLayout function to itemTemplate.
          this._initializeLayout(listView, appView.value, itemTemplate);
          listView.element.focus();
       },
      
      // This function updates the page layout in response to viewState changes.
      updateLayout: function (element, viewState, lastViewState) {
          var listView = element.querySelector(".groupeditemslist").winControl;
      
          // Add the next line of code to retrieve the item template.
          var itemTemplate = element.querySelector(".itemtemplate");
      
          if (lastViewState !== viewState) {
              if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
                  var handler = function (e) {
                      listView.removeEventListener("contentanimating", handler, false);
                      e.preventDefault();
                  }
                  listView.addEventListener("contentanimating", handler, false);
      
                  // Change this line to pass through the item template.
                  this._initializeLayout(listView, viewState, itemTemplate);
              }
          }
      },
      
      
  6. Затем нам нужно добавить к groupedItems.css стили для элементов. Чтобы оформить элементы так, как показано на предыдущем изображении, нам понадобятся 4 класса CSS для 4 различных шаблонов элементов на целевой странице. Назовите 4 класса smallitemtemplate, mediumitemtemplate, mediumlargeitemtemplate и largeitemtemplate. Следующий код CSS в основном позиционирует наложение и текст относительно изображения и устанавливает размеры для каждого элемента. В некоторых случаях определенные элементы свернуты, так как не все шаблоны используют все элементы в шаблоне элемента. Добавьте этот код CSS непосредственно перед первой строкой CSS @media screen.

    /* Generic styling */
    .groupeditemspage .groupeditemslist .item-overlay {
        -ms-grid-row: 2;
    }
    .groupeditemspage .groupeditemslist .item-overlay .item-description {
        visibility:collapse;
    }
    
    /* Small item template */
    .groupeditemspage .groupeditemslist .smallitemtemplate {
        width: 440px;
        height: 80px;
        overflow: hidden;
    
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-image {
        height: 80px;
        width: 80px;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay {
       opacity: 0;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-title {
        position: absolute; 
        top: -5px;
        padding-left: 90px;
        font-size: 11pt;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-subtitle {
        position: absolute; 
        top: 15px;
        padding-left: 90px;
        font-size: 9pt;
    }
    .groupeditemspage .groupeditemslist .smallitemtemplate .item-overlay .item-description {
        position: absolute; 
        top: 35px;
        padding-left: 90px;
        font-size: 9pt;
        visibility: visible;
        width: 360px;
        overflow-wrap: normal;
        text-overflow: initial;
    }
    
    /* Medium item template */
    .groupeditemspage .groupeditemslist .mediumitemtemplate {
        width: 260px;
        height: 170px;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 30px;
        display: -ms-grid;
        overflow: hidden;
    }      
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-title {
        padding-top: 5px;
        padding-left: 10px;
    }
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-title {
        font-size: 14px;
    }
    .groupeditemspage .groupeditemslist .mediumitemtemplate .item-overlay .item-subtitle {
        visibility: collapse;
    }   
    
    /* Medium-large item template */
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate {
        width: 260px;
        height: 350px;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 30px;
        display: -ms-grid;
        overflow: hidden;
    }
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate .item-overlay .item-title {
        padding-top: 5px;
        padding-left: 10px;
        font-size: 14px;
    }
    
    .groupeditemspage .groupeditemslist .mediumlargeitemtemplate .item-overlay .item-subtitle {
        visibility: collapse;
    }   
    
    /* Large item template */
    .groupeditemspage .groupeditemslist .largeitemtemplate {
        width: 440px;
        height: 530px;
        overflow: hidden;
        -ms-grid-columns: 1fr;
        -ms-grid-rows: 1fr 90px;
        display: -ms-grid;
    }
    .groupeditemspage .groupeditemslist .largeitemtemplate .item-overlay {
        -ms-grid-row: 2;
        -ms-grid-rows: 1fr 21px;
        display: -ms-grid;
        padding: 6px 15px 2px 15px;
    }
    .groupeditemspage .groupeditemslist .largeitemtemplate .item-subtitle{
        -ms-grid-row: 2;
    }
    
    
  7. В правиле @media screen and (-ms-view-state: fullscreen-landscape), screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: filled) измените первый стиль CSS на следующий. Этот код CSS делает наложение непрозрачным и удаляет класс "item".

     .groupeditemspage .groupeditemslist .item-overlay {
            background: rgba(0,0,0,1);
        }
    
  8. Для этого измените первый стиль .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface в groupedItems.css.

        .groupeditemspage .groupeditemslist .win-horizontal.win-viewport .win-surface {
            margin-bottom: 60px;
            margin-left: 45px;
            margin-right: 115px;
        }
    

    Этот код CSS изменяет размер нижнего поля, делая его равным "50 пикселям", чтобы учесть элементы несколько большего размера.

Внеся эти изменения, запустите свое приложение. Оно будет выглядеть следующим образом:

Обновленное приложение

Добавьте рисунки, измените цвет фона, текста и наложения и вы получите целевую страницу Contoso Food Truck.

Дополнительные размеры и шаблоны

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

Еще одна настроенная целевая страница

Базовая единица измерения целевой страницы представляет собой размер наименьшего элемента. Первый элемент в каждой группе занимает 2x3 базовых единицы, а его шаблон помещает заголовок и описание под изображением. Размер следующих элементов в группе соответствует 1x1 единице, а заголовок и описание у них наложено на изображение. Третий шаблон предназначен для элементов, у которых нет изображений.

Добавление анимации элемента ListView

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

В этом примере у первого элемента целевой страницы каждые 4 секунды обновляется изображение. Тот же период времени был задан на начальном экране. Мы используем ту же анимацию из библиотеки WinJS, которая выбрана для плиток на начальном экране.

  1. В Visual Studio создайте новое приложение, использующее шаблон Grid App.

  2. В groupedItems.html измените шаблон элемента, чтобы включить в него второе изображение, которое будет участвовать в анимации.

        <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
            <div class="item">
                <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
                <img class="item-image-new" src="#" data-win-bind="src: backgroundImage; alt: title" />
                <div class="item-overlay">
                    <h4 class="item-title" data-win-bind="textContent: title"></h4>
                    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
                </div>
            </div>
        </div>
    
  3. В groupedItems.css измените стиль CSS, чтобы расположить второе изображение под начальным изображением. Это позволит нам анимировать новое изображение, начиная с нижней части элемента. Нам нужно, чтобы оба элемента имели относительное положение, допускающее изменение, прежде чем мы отключим анимацию. Первый и третий стили CSS уже существуют в groupedItems.css и требуют лишь небольшого изменения. Второй стиль CSS — новый.

            /* Update this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-image {
                -ms-grid-row-span: 2;
                position:relative;
            }
    
            /* Add this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-image-new {
                -ms-grid-row-span: 2;
                position:relative;
                top: 250px;
            }
    
            /* Update this CSS style. */
            .groupeditemspage .groupeditemslist .item .item-overlay {
                -ms-grid-row: 2;
                -ms-grid-rows: 1fr 21px;
                display: -ms-grid;
                padding: 6px 15px 2px 15px;
                position:relative;
            }
    
  4. Для запуска анимации нового элемента каждые 4 секунды в groupedItems.js добавьте этот код к функции ready.

                setInterval(function () { changeImage() } , 4000);
    
  5. В groupedItems.js добавьте этот код за пределами определения страницы. Определения первой переменной указывают на другие изображения, используемые шаблоном Grid App. Добавьте функцию peekTile для воспроизведения анимации из библиотеки Windows для JavaScript. Добавьте функцию changeImage, чтобы обновить изображения перед воспроизведением анимации. В этом примере мы воспроизводим анимацию только для первого элемента в ListView.

        // Define images
        var darkGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY3B0cPoPAANMAcOba1BlAAAAAElFTkSuQmCC";
        var lightGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
        var mediumGray = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
        // Play the Peek animation
        function peekTile(tile1, tile2) {
            // Create peek animation
            var peekAnimation = WinJS.UI.Animation.createPeekAnimation([tile1, tile2]);
    
            // Reposition tiles to their desired post-animation position
            tile1.style.top = "-250px";
            tile2.style.top = "0px";
    
            // Execute animation
            peekAnimation.execute();
        }
    
       function changeImage() {
            // Get the two image elements
            var images = document.querySelector(".item-image");
            var imagesNew = document.querySelector(".item-image-new"); 
    
            // Swap out the old image source and choose the new image source
            images.src = imagesNew.src;
            if (images.src == lightGray)
                imagesNew.src = mediumGray;
            else if (images.src == mediumGray)
                imagesNew.src = darkGray;
            else
                imagesNew.src = lightGray;
    
            // Reset the elements for the pre-animation position and trigger the animation
            images.style.top = "0px";
            imagesNew.style.top = "250px";
            peekTile(images, imagesNew);
        };
    

    Поздравляем, вы добавили пользовательскую анимацию к вашему элементу управления ListView!

Связанные разделы

ListView

Краткое руководство. Добавление элемента управления ListView

Стилизация ListView и его элементов