Дизайн виджетов не менее важен, чем дизайн приложения, поэтому кроме информативности виджет должен быть ещё и красивым. Однако при разработке виджетов можно столкнуться с тем, что возможности кастомизации по сравнению с кастомизацией приложения ограничены. Например, нет возможности задать тексту на виджете какой-нибудь нестандартный шрифт или назначить обработчики событий на элементы списка (о том, как можно вывести список с виджете, вы можете почитать в этой статье).
По этой причине люди стараются изобретать обходные пути, с помощью которых можно достичь желаемого результата. В этой статье мы рассмотрим, как можно добавить на виджет текст со своим шрифтом на примере нашего приложения “Эвдик“. В этом приложении на карточках используется кастомный шрифт, попробуем использовать его для виджета.
О том, как создать виджет для приложения, написано много, в том числе это затрагивается в этой статье, поэтому перейдём сразу к созданию дизайна виджета. В приложении используется два виджета, для словаря и для разговорника, их дизайн идентичен за исключением наличия кнопки озвучивания фразы.
В коде разметки виджета нам нужно добавить ImageView, который будет выступать в роли контейнера для текста. Код разметки будет выглядеть следующим образом:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/widget_bg" android:orientation="vertical" android:padding="4dp" > <Button android:id="@+id/widget_btn_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:background="@null" android:text="@string/btn_back" android:textSize="18sp" /> <Button android:id="@+id/widget_btn_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:background="@null" android:text="@string/btn_next" android:textSize="18sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="4dp" android:orientation="vertical" > <ImageView android:id="@+id/iv_dic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="6dp" /> </LinearLayout> </RelativeLayout>
Теперь перейдём в класс, реализующий обновление виджета, и добавим в него следующий код:
public static Bitmap drawMultilineTextToBitmap(String text, Context context) { // 1 Bitmap bitmap = Bitmap.createBitmap(400, 300, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); // 2 Typeface tf = Typeface.createFromAsset(context.getAssets(), "a_BosaNova Regular.ttf"); // 3 TextPaint textPaint = new TextPaint(TextPaint.LINEAR_TEXT_FLAG | TextPaint.ANTI_ALIAS_FLAG); textPaint.setTypeface(tf); textPaint.setStyle(Paint.Style.FILL); textPaint.setColor(Color.BLACK); textPaint.setTextSize(40); // 4 StaticLayout staticLayout = new StaticLayout(text, textPaint, bitmap.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); staticLayout.draw(canvas); return bitmap; }
Рассмотрим поэтапно, что здесь происходит:
- Создаём экземпляр объекта Bitmap нужного размера, который в результате выполнения работы вернём в ImageView виджета, и передаём его в экземпляр Canvas, на котором будем рисовать текст.
- Берём шрифт из папки Assets, этот шрифт мы будем устанавливать для текста на виджете.
- Создаём экземпляр объекта TextPaint. Этот класс является подклассом Paint, который предоставляет некоторые дополнительные возможности при работе с текстом. Флаг LINEAR_TEXT_FLAG обеспечивает плавное линейное масштабирование текста, а флаг ANTI_ALIAS_FLAG производит сглаживание при рисовании. После создания объекта выставляем ему необходимые параметры для текста и, что самое главное, шрифт с помощью метода setTypeface().
- Создаём экземпляр объекта StaticLayout. Этот класс создаёт разметку для текста, который не будет редактироваться после создания. Основным его преимуществом перед стандартным рисованием текста на Canvas является то, что он поддерживает перенос слов в больших текстах. В параметры нужно передать:
- собственно текст, который нужно нарисовать;
- экземпляр TextPaint;
- ширина холста;
- выравнивание текста;
- высота строки;
- количество элементов, которые добавляются в строку;
- дополнительный отступ.
После того, как экземпляр будет создан, рисуем его на Canvas.
Теперь всё что осталось, это вызвать метод выше в onUpdate() виджета, чтобы загрузить в ImageView нарисованный текст.
String s = mCursor.getString(mCursor.getColumnIndex("rus_word")) + "<br/><br/>" + mCursor.getString( mCursor.getColumnIndex("ev_word")); widgetView.setImageViewBitmap(R.id.iv_dic, drawMultilineTextToBitmap(Html.fromHtml(s).toString(), ctx));
С помощью такого трюка мы смогли добиться, чтобы у текста на виджете был кастомный шрифт.