#android #android-layout
#Android #android-layout
Вопрос:
Я разработчик. Мне нужно реализовать дизайн, показанный ниже. У меня уже есть функциональное приложение, но интересно, как вообще к этому подойти? В частности, меня интересует, как показать количество «новых» элементов во вкладках. Что я ЗНАЮ, как сделать — это создавать новые значки с красными точками и просто отображать их, когда новые материалы доступны.
Но я понятия не имею, как заставить эти круглые круги всплывать поверх заголовка И показывать номер внутри. У кого-нибудь есть предложения о том, что тоже искать? Образцы? Как добраться?
Второй вопрос о разделении действий. Должен ли я создать элемент управления для объединения подобных кнопок и просто увеличить его для действий? В противном случае я могу создать действие с вкладками, но я не уверен, возможно ли изменить его стиль, чтобы оно выглядело следующим образом.
Ответ №1:
Сделайте свой значок a TextView
, что позволит вам присвоить числовому значению все, что вам нравится, позвонив setText()
. Установите фон изображения TextView
в виде XML <shape>
-файла, с помощью которого вы можете создать сплошной или градиентный круг с рамкой. XML-чертеж будет масштабироваться в соответствии с представлением по мере увеличения размера текста.
res/drawable/badge_circle.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#F00" />
<stroke
android:width="2dip"
android:color="#FFF" />
<padding
android:left="5dip"
android:right="5dip"
android:top="5dip"
android:bottom="5dip" />
</shape>
Однако вам придется взглянуть на то, как овал / круг масштабируется с большими числами из 3-4 цифр. Если этот эффект нежелателен, попробуйте использовать метод со скругленным прямоугольником, как показано ниже. С небольшими числами прямоугольник все равно будет выглядеть как круг, поскольку радиусы сходятся вместе.
res/drawable/badge_circle.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="10dip"/>
<solid
android:color="#F00" />
<stroke
android:width="2dip"
android:color="#FFF" />
<padding
android:left="5dip"
android:right="5dip"
android:top="5dip"
android:bottom="5dip" />
</shape>
Создав масштабируемый фон, вы просто добавляете его на фон TextView
, вот так:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10"
android:textColor="#FFF"
android:textSize="16sp"
android:textStyle="bold"
android:background="@drawable/badge_circle"/>
Наконец, эти TextView
значки можно разместить в вашем макете поверх соответствующих кнопок / вкладок. Я бы, вероятно, сделал это, сгруппировав каждую кнопку с ее значком в RelativeLayout
контейнере, вот так:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@ id/myButton"
android:layout_width="65dip"
android:layout_height="65dip"/>
<TextView
android:id="@ id/textOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/myButton"
android:layout_alignRight="@id/myButton"
android:text="10"
android:textColor="#FFF"
android:textSize="16sp"
android:textStyle="bold"
android:background="@drawable/badge_circle"/>
</RelativeLayout>
Надеюсь, этой информации достаточно, чтобы, по крайней мере, направить вас в правильном направлении!
Комментарии:
1. Возможно ли сделать что-то подобное с TableLayout? У меня сетка кнопок 2×2, и относительный макет сложнее настроить, чем относительный макет, однако я не могу использовать такие атрибуты, как aligntTop и alignRight
2. NM Я решил это, просто поместив относительный макет в строку таблицы! Спасибо, код отлично работает
3. @FelipeMosso Используйте
oval
версию примера и добавьте<size>
элемент, чтобы обеспечить пропорции для ширины / высоты4. В моем случае значок количества скрывается за этой кнопкой. На Android 5.0. Не знаю, что не так. В графическом макете это выглядит хорошо, но не на устройстве.
5. Если я использую кнопку для значка count, все работает нормально, но если я использую Textview, он скрывается за главной кнопкой, а не отображается сверху!
Ответ №2:
Android ViewBadger
Простой способ «добавить значок» к любому заданному представлению Android во время выполнения без необходимости учитывать его в макете.
Добавьте .jar
файл в свою папку libs
Нажмите, чтобы загрузить пример
смотрите Пример на github
Простой пример:
View target = findViewById(R.id.target_view);
BadgeView badge = new BadgeView(this, target);
badge.setText("1");
badge.show();
Комментарии:
1. Эта библиотека устарела.
Ответ №3:
Простейший взлом, задав стиль только TextView
.
<TextView
android:id="@ id/fabCounter"
style="@style/Widget.Design.FloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:padding="5dp"
android:text="10"
android:textColor="@android:color/black"
android:textSize="14sp" />
Ответ №4:
Просто для добавления. Если кто-то хочет реализовать пузырь с заполненным кругом, используя форму кольца вместо овала, вот пример кода добавления количества пузырьков к кнопкам панели действий. Но это может быть добавлено к любой кнопке.
(назовите это bage_circle.xml
):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:useLevel="false"
android:thickness="9dp"
android:innerRadius="0dp"
>
<solid
android:color="#F00"
/>
<stroke
android:width="1dip"
android:color="#FFF" />
<padding
android:top="2dp"
android:bottom="2dp"/>
</shape>
Возможно, вам придется отрегулировать толщину в соответствии с вашими потребностями.
Результат будет примерно таким:
Вот макет кнопки (назовите ее badge_layout.xml
):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.joanzapata.iconify.widget.IconButton
android:layout_width="44dp"
android:layout_height="44dp"
android:textSize="24sp"
android:textColor="@color/white"
android:background="@drawable/action_bar_icon_bg"
android:id="@ id/badge_icon_button"/>
<TextView
android:id="@ id/badge_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/badge_icon_button"
android:layout_alignRight="@id/badge_icon_button"
android:layout_alignEnd="@id/badge_icon_button"
android:text="10"
android:paddingEnd="8dp"
android:paddingRight="8dp"
android:paddingLeft="8dp"
android:gravity="center"
android:textColor="#FFF"
android:textSize="11sp"
android:background="@drawable/badge_circle"/>
</RelativeLayout>
В меню создать элемент:
<item
android:id="@ id/menu_messages"
android:showAsAction="always"
android:actionLayout="@layout/badge_layout"/>
В onCreateOptionsMenu
получите ссылку на пункт меню:
itemMessages = menu.findItem(R.id.menu_messages);
badgeLayout = (RelativeLayout) itemMessages.getActionView();
itemMessagesBadgeTextView = (TextView) badgeLayout.findViewById(R.id.badge_textView);
itemMessagesBadgeTextView.setVisibility(View.GONE); // initially hidden
iconButtonMessages = (IconButton) badgeLayout.findViewById(R.id.badge_icon_button);
iconButtonMessages.setText("{fa-envelope}");
iconButtonMessages.setTextColor(getResources().getColor(R.color.action_bar_icon_color_disabled));
iconButtonMessages.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (HJSession.getSession().getSessionId() != null) {
Intent intent = new Intent(getThis(), HJActivityMessagesContexts.class);
startActivityForResult(intent, HJRequestCodes.kHJRequestCodeActivityMessages.ordinal());
} else {
showLoginActivity();
}
}
});
После получения уведомления о сообщениях установите количество:
itemMessagesBadgeTextView.setText("" count);
itemMessagesBadgeTextView.setVisibility(View.VISIBLE);
iconButtonMessages.setTextColor(getResources().getColor(R.color.white));
В этом коде используется Iconify-fontawesome.
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1. '
Ответ №5:
для людей, которые ищут Xamarin Android, можно использовать этот код
public class CountDrawable : Drawable
{
private float mTextSize;
private Paint mBadgePaint;
private Paint mTextPaint;
private Rect mTxtRect = new Rect();
private String mCount = "";
private bool mWillDraw = false;
public CountDrawable(Context context)
{
float mTextSize = context.Resources.GetDimension(Resource.Dimension.badge_count_textsize);
mBadgePaint = new Paint();
// mBadgePaint.SetCol(ContextCompat.GetColor(context.ApplicationContext, Resource.Color.background_color));
mBadgePaint.Color = new Color(Color.Red);
mBadgePaint.AntiAlias = true;
mBadgePaint.SetStyle(Paint.Style.Fill);
mTextPaint = new Paint();
mTextPaint.Color = new Color(Color.White);
mTextPaint.SetTypeface(Typeface.DefaultBold);
mTextPaint.TextSize = mTextSize;
mTextPaint.AntiAlias = true;
mTextPaint.TextAlign = Paint.Align.Center;
}
public override void Draw(Canvas canvas)
{
if(!mWillDraw)
{
return;
}
Rect bounds = GetBounds;
float width = bounds.Right - bounds.Left;
float height = bounds.Bottom - bounds.Top;
float radius = ((Math.Max(width, height) / 2)) / 2;
float centerX = (width - radius - 1) 5;
float centerY = radius - 5;
if (mCount.Length <= 2)
{
// Draw badge circle.
canvas.DrawCircle(centerX, centerY, (int)(radius 5.5), mBadgePaint);
}
else
{
canvas.DrawCircle(centerX, centerY, (int)(radius 6.5), mBadgePaint);
}
mTextPaint.GetTextBounds(mCount, 0, mCount.Length, mTxtRect);
float textHeight = mTxtRect.Bottom - mTxtRect.Top;
float textY = centerY (textHeight / 2f);
if (mCount.Length > 2)
canvas.DrawText("99 ", centerX, textY, mTextPaint);
else
canvas.DrawText(mCount, centerX, textY, mTextPaint);
}
public Rect GetBounds { get; set; }
public void setCount(String count)
{
mCount = count;
// Only draw a badge if there are notifications.
// mWillDraw = !count.equalsIgnoreCase("0");
mWillDraw = !string.Equals(count, "0", StringComparison.OrdinalIgnoreCase);
// invalidateSelf();
}
public override void SetAlpha(int alpha)
{
}
public override void SetColorFilter(ColorFilter colorFilter)
{
}
public override int Opacity
{
get;
}
}
И в MainActivity
public override bool OnCreateOptionsMenu(IMenu menu)
{
// return base.OnCreateOptionsMenu(menu);
MenuInflater.Inflate(Resource.Menu.actionmenu, menu);
// var dd = menu.FindItem(Resource.Id.icon_group);
IMenuItem item = menu.FindItem(Resource.Id.ic_group);
LayerDrawable icon = item.Icon as LayerDrawable;
// LayerDrawable icon = (LayerDrawable)item.Icon;
CountDrawable badge;
Drawable reuse = icon.FindDrawableByLayerId(Resource.Id.ic_group_count);
if (reuse != null amp;amp; reuse is CountDrawable)
{
badge = (CountDrawable)reuse;
}
else
{
badge = new CountDrawable(this);
}
badge.setCount("8");
badge.GetBounds=icon.Bounds;
icon.Mutate();
icon.SetDrawableByLayerId(Resource.Id.ic_group_count, badge);
return true;
}
Комментарии:
1. как мне уменьшить круг?
2. @khalil попробуйте создать с помощью SkiaSharp