Сглаживание плавного изменения пользовательской сворачиваемой панели
Я использую настраиваемую панель инструментов Collapsing, в которой есть заголовок и субтитр.
Я получил название, чтобы рухнуть и оживить по искривленному пути, но часть названия становится меньше, так как рушится, не является гладкой. Он изменяет размеры в зазубренном виде.
Это мое поведение, которое отвечает за перемещение и изменение размера заголовка:
public class ViewBehavior : CoordinatorLayout.Behavior
{
private Context mContext;
private int mStartMarginRight;
private int mEndMargintRight;
private int mMarginLeft;
private int mStartMarginBottom;
private bool isHide;
private static float SCALE_MINIMUM = 0.5f;
public ViewBehavior(Context context, IAttributeSet attrs)
{
mContext = context;
}
public override bool LayoutDependsOn(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
{
return dependency is AppBarLayout;
}
public override bool OnDependentViewChanged(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
{
ShouldInitProperties((child as HeaderView), dependency);
int maxScroll = ((AppBarLayout)dependency).TotalScrollRange;
float percentage = System.Math.Abs(dependency.GetY()) / (float)maxScroll;
float childPosition = dependency.Height
+ dependency.GetY()
- (child as View).Height
- (getToolbarHeight() - (child as View).Height) * percentage / 2;
childPosition = childPosition - mStartMarginBottom * (1f - percentage);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)(child as View).LayoutParameters;
lp.RightMargin = (int)(100 * System.Math.Sin(percentage * System.Math.PI)) + mStartMarginRight / 2 + mEndMargintRight / 2;
lp.LeftMargin = mMarginLeft;
(child as View).LayoutParameters = lp;
(child as View).SetY(childPosition);
float x = (child as HeaderView).Title.TextSize;
//Here is the algorithm for setting the text size
(child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 36 * (1 - percentage / 2));
(child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 26 * (1 - percentage / 2));
var toolbarTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 18, Application.Context.Resources.DisplayMetrics);
var toolbarSubTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 16, Application.Context.Resources.DisplayMetrics);
if ((child as HeaderView).Title.TextSize < toolbarTitleSize)
(child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 18);
if ((child as HeaderView).SubTitle.TextSize < toolbarSubTitleSize)
(child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 14);
if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
{
if (isHide && percentage < 1)
{
(child as View).Visibility = ViewStates.Visible;
isHide = false;
}
else if (!isHide && percentage == 1)
{
(child as View).Visibility = ViewStates.Gone;
isHide = true;
}
}
return true;
}
public void ShouldInitProperties(HeaderView child, View dependency)
{
if (mStartMarginRight == 0)
mStartMarginRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_right);
if (mEndMargintRight == 0)
mEndMargintRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_right);
if (mStartMarginBottom == 0)
mStartMarginBottom = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_bottom);
if (mMarginLeft == 0)
mMarginLeft = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_left);
}
public int getToolbarHeight()
{
int result = 0;
TypedValue tv = new TypedValue();
if (mContext.Theme.ResolveAttribute(Android.Resource.Attribute.ActionBarSize, tv, true))
{
result = TypedValue.ComplexToDimensionPixelSize(tv.Data, mContext.Resources.DisplayMetrics);
}
return result;
}
}
Как я могу изменить алгоритм, чтобы он изменялся более плавным образом?
Изменить - Видео:
https://youtu.be/j6LseSW6h1s
Ответы
Ответ 1
Как упоминалось другими, масштабирование через textSize не очень хорошо работает на Android в анимации, поскольку оно недостаточно точное (округляет десятичные значения до целых чисел).
Если это соответствует вашим потребностям, вы должны выполнить анимацию с атрибутами scaleX
/scaleY
, например:
float scale = 1 - percentage * SCALE_MINIMUM;
(child as HeaderView).Title.SetScaleX(scale);
(child as HeaderView).Title.SetScaleY(scale);
(child as HeaderView).SubTitle.SetScaleX(scale);
(child as HeaderView).SubTitle.SetScaleY(scale);
Ответ 2
Проблема заключается в том, что даже если вы вычисляете шкалы как демические значения, они становятся целыми значениями в TextView. Вы должны включить оба LINEAR_TEXT_FLAG и SUBPIXEL_TEXT_FLAG в вашем классе TextView Paint для обеспечения плавного масштабирования и позиционирования.
Что-то вроде этого:
yourTextView.Paint.SubpixelText = true;
yourTextView.Paint.LinearText = true;
Ответ 3
Я использую этот формат макета для свертывания панели инструментов, и он работает плавно.
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/height_300dp"
android:background="?colorPrimary">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsible_Toolbar_Layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:collapsedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:contentScrim="@color/colorDarkBlue"
app:expandedTitleMarginEnd="@dimen/margin_64dp"
app:expandedTitleMarginStart="@dimen/margin_20dp"
app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:fitsSystemWindows="true"
android:focusableInTouchMode="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorTransparent" />
<ImageButton
android:id="@+id/ib"
android:layout_width="@dimen/margin_35dp"
android:layout_height="@dimen/margin_35dp"
android:layout_gravity="right"
android:layout_marginRight="@dimen/margin_10dp"
android:layout_marginTop="@dimen/height_245dp"
android:background="@null"
android:src="@drawable/ic_launcher" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:contentInsetStart="@dimen/margin_50dp"
app:layout_collapseMode="pin">
<ImageButton
android:id="@+id/ib2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="@dimen/margin_10dp"
android:background="@null"
android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:src="@drawable/ic_launcher"
android:visibility="invisible" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
После этого в Fragment в IntializeComponents я инициализирую только этот макет и устанавливаю Text
appBarLayout = (AppBarLayout)view.findViewById(R.id.app_bar_layout);
CollapsingToolbarLayout toolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsible_Toolbar_Layout);
toolbarLayout.setTitle(yourTitle);
toolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
toolbarLayout.setExpandedTitleColor(Color.WHITE);
appBarLayout.addOnOffsetChangedListener(this);
Добавьте этот метод для обработки панели инструментов
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
int maxScroll = appBarLayout.getTotalScrollRange();
float percentage = (float) Math.abs(offset) / (float) maxScroll;
handleToolbarTitleVisibility(percentage);
}
private void handleToolbarTitleVisibility(float percentage) {
if (percentage >= PERCENTAGE_TO_SHOW_TITLE_AT_TOOLBAR) {
if(!mIsTheTitleVisible) {
imageButton.setVisibility(View.VISIBLE);
ib.setVisibility(View.INVISIBLE);
mIsTheTitleVisible = true;
}
} else {
if (mIsTheTitleVisible) {
imageButton.setVisibility(View.INVISIBLE);
ibMap.setVisibility(View.VISIBLE);
mIsTheTitleVisible = false;
}
}
}
Надеюсь, это вам поможет:)
Ответ 4
Нет, если вы используете customTextview, тогда он также будет работать, потому что я также использую только customTextView.
Вы разместите код customtextview здесь? Таким образом, все может увидеть проблему в вашем customTextview.