Android: ошибка выравнивания при создании/отображении изображения 9patch

Девять Патч:

Значок корзины Изображение NinePatch

Снимок экрана:

Скриншот смещения NinePatch

XML макета:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#ffffff">

    <LinearLayout
        android:id="@+id/edit_tray"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <View
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/trash"/>

    </LinearLayout>

</RelativeLayout>

Желаемые результаты:

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

Значок корзины состоит из двух элементов: самого значка и линейного градиента позади него. Изображение NinePatch содержит три растягиваемые области и одну статическую область для размещения этих элементов. Значок корзины в середине изображения является статическим и должен отображаться прямо по центру по горизонтали и внизу экрана. Градиент должен простираться по нижней части экрана от одной стороны к другой.

Ошибка?

Изображение NinePatch содержит только один пиксель растягиваемой области с каждой стороны изображения по горизонтали. Эффект от этого должен заключаться в том, что значок корзины появляется прямо в центре (1 пиксель слева == 1 пиксель справа). Однако, как вы можете видеть на скриншоте выше, это не так. Примечание: этот снимок экрана был сделан с моего тестового телефона T-Mobile G2. Тот же эффект можно увидеть в эмуляторе. Однако в предварительном просмотре draw9patch и графическом представлении eclipse изображение распределено идеально.

Я пробовал несколько разных методов, чтобы попытаться выяснить, где находится ошибка, и попытаться исправить ее или обойти ее. В том числе: использование ImageViews вместо Views (тот же эффект), использование android:scaleType="fitXY" (та же проблема), проверка во время выполнения, что ширина экрана и ширина "edit_tray" одинаковы (они есть), использование двух разных изображений для градиента (как фон edit_tray) и значка (как ImageView src) (создает еще одну проблему, когда два изображения не накладываются друг на друга. Исправлено путем установки абсолютной высоты для обоих) и т. д.

Ответ, обходной путь и настоящий вопрос

Я провел некоторое тестирование, используя несколько простых изображений NinePatch с шестью растягиваемыми областями на каждой стороне. Я заметил, что были некоторые проблемы с их отображением по крайней мере в одном из тестовых случаев (телефон, эмулятор, draw9patch, графический макет в eclipse).

Я решил попытаться расширить изображение по горизонтали, чтобы на краях значка корзины было больше линейного градиента. Я сделал изображение 128х64 (ранее 64х64). Я сделал больше краев частью растягиваемой части, чтобы попытаться обуздать любую неверную математику (?), которая происходила с изображением. Draw9patch сообщил о плохих участках, поэтому я вернул только два пикселя, по одному с каждой стороны. Это сработало! Значок теперь находится прямо в центре экрана! Я не знаю почему, но без изменения фактической растягиваемой части изображения, только изменив ширину изображения на 128, теперь это работает.

Я попытался изменить размер изображения обратно примерно до 100 пикселей в ширину, чтобы удалить некоторые лишние пиксели, и ошибка вернулась! Он не только вернулся, но и значок был размещен точно в том же месте, смещенном от центра экрана. Я не могу понять, почему это произошло именно так.

У кого-нибудь есть идеи? Это ошибка?

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


person SubOne    schedule 20.07.2011    source источник


Ответы (4)


Создайте свой образ с 9 патчами, используя 4 points, как я сделал в этом... и он будет работать.

введите здесь описание изображения

Советы по созданию изображения из 9 патчей (не дизайнер, рассказываю вам свои принципы)

  • Поставьте точки слева и сверху
  • Если у вас есть какой-то текст или изображение между ними ... затем поместите точку слева и справа от изображения, а также сверху и снизу этого изображения или текста.
  • Всегда следите за тем, чтобы количество мест слева и количество точек с обеих сторон (слева-справа и сверху-снизу) были одинаковыми.
  • Всегда проверяйте один раз предварительный просмотр или правую сторону, прежде чем использовать регистрацию от 2 до 6 раз.
person MKJParekh    schedule 06.04.2012
comment
Я должен проверить это. Я не добавлял нижний патч, потому что хотел, чтобы мусорное ведро оставалось внизу. Мне не приходило в голову, что я могу испортить девять патчей, просто указав только 6 патчей. - person SubOne; 09.04.2012

По моему опыту работы с инструментом Draw 9-patch, есть автоматическое смещение на 1 пиксель с каждой стороны изображения. Учитывая эту информацию, если бы вы использовали только это смещение в один пиксель, ваше изображение на самом деле не растягивалось бы так, как вы себе представляли.

Это видно по тому факту, что когда вы использовали смещение в 2 пикселя, все работало идеально.

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

Изучение инструмента с 9 патчами — это, безусловно, отличная вещь, поскольку он обеспечивает большую настройку. Еще один совет, если вы хотите сделать что-то вроде замены любого андроида 9-патча своими переделками - тогда просто скопируйте 9патч который есть в SDK и переделайте его. По какой-то причине изображения 9patch в SDK имеют странные смещения. Это гарантирует, что вы не получите странных ответов от ваших 9-патчей. Пример этого - я выделяю editText красным цветом, когда дается неверный ввод.

Образы SDK можно найти в SDK->platforms->[plateform-you-want]->data->res-drawable-[you-choice]

Вы также можете просмотреть изображения 9-исправлений SDK, чтобы понять, как работает инструмент 9-исправлений.

Надеюсь, это даст немного больше понимания.

Вот несколько хороших ссылок: http://developer.android.com/guide/developing/tools/draw9patch.html http://android10.org/index.php/articlesother/279-draw-9-patch-tutorial http://jaanus.com/post/7878186745/как-делает-androids-nine-patch-tool-work-from-a

person jjNford    schedule 16.03.2012
comment
Я не знаю, что вы имели в виду под первыми двумя абзацами. Не похоже, что вы ответили на фактический вопрос или предоставили соответствующую информацию. - person SubOne; 21.03.2012
comment
Извините за попытку дать вам мое понимание. - person jjNford; 21.03.2012

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

Однако мне не нравится ваш подход к рисованию этой иконки. Вы пытаетесь позиционировать свой экранный элемент, используя что-то, что не предназначено для этой задачи.

Вы должны нарисовать это по-другому: создать представление контейнера (FrameLayout) с градиентным фоном. Затем поверх этой позиции ImageView с мусорным баком. Ни одно из этих двух изображений не обязательно должно состоять из девяти патчей, градиент заполнит весь вид, мусорная корзина будет нарисована без масштабирования. Несмотря на перерисовку в области просмотра мусора, процессорное время не тратится впустую на вычисления областей с девятью патчами.

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

person Pointer Null    schedule 02.04.2012

Как сказал @jjNford, работать с изображениями таким образом - плохая практика.

Для этой задачи лучшим решением является создание значка «корзина» с прозрачным фоном и создание shape рисуемого с градиентом. Итак, вы можете удалить ненужные LinearLayout и использовать только ImageView:

<ImageView
    android:id="@+id/edit_tray"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:src="@drawable/trash"
    android:background="@drawable/gradient_background"/>

Документы для рисования фигур.

ИЗМЕНИТЬ

Просто проверьте свое изображение — на SE Xperia 2.3.3 оно отлично крахмалится.

person Jin35    schedule 03.04.2012