在 Android Lollipop 中扩展 Preference 类 = 丢失动画
Posted
技术标签:
【中文标题】在 Android Lollipop 中扩展 Preference 类 = 丢失动画【英文标题】:Extending Preference classes in Android Lollipop = losing animation 【发布时间】:2015-07-31 22:20:46 【问题描述】:仅用于在 android Lollipop 上扩展 CheckBoxPreference 或 SwitchPreference,小部件(复选框或开关)将不再有动画。
我想扩展 SwitchPreference 以强制 api
我正在使用新的AppCompatPreferenceActivity 和appcompat-v7:22.1.1
,但这似乎不会影响开关。
问题是只扩展这些类,而不添加任何自定义布局或小部件资源布局,动画就消失了。
我知道我可以编写我的preference.xml 的两个实例(在内部值-v21 上)并且它会工作......但我想知道为什么会发生这种情况,如果有人知道没有两个偏好的解决方案.xml。
代码示例:
public class SwitchPreference extends android.preference.SwitchPreference
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
super(context, attrs, defStyleAttr, defStyleRes);
public SwitchPreference(Context context, AttributeSet attrs)
super(context, attrs);
public SwitchPreference(Context context)
super(context);
CheckBoxPreference 或相同,然后使用:
<com.my.package.SwitchPreference />
将使棒棒糖设备中的动画消失。
--
我为 SwitchPreference(我可以使用 CheckBoxPreference)尝试的另一件事是提供一个具有默认 id 的布局,但 @android:id/switchWidget
is not public 而 @android:id/checkbox
是。我也知道我可以使用 <CheckBoxPreference />
并提供一个实际上是 SwitchCompat 的小部件布局,但我想避免这种情况(混淆名称)。
【问题讨论】:
您找到解决方案了吗? 不,我没有。实际上,我在 Lollipop 之前有一个材料偏好库:github.com/ferrannp/material-preferences,它唯一的错误是这个:github.com/ferrannp/material-preferences/issues/9 code.google.com/p/android/issues/detail?id=85392 是相关的。 有一个很好的答案here 对我有用。 【参考方案1】:我设法像这样修复它,并且动画在它直接进入没有动画的状态之前工作:
修复:
CustomSwitchCompat.class
public class CustomSwitchCompat extends SwitchCompat
public CustomSwitchCompat(Context context)
super(context);
public CustomSwitchCompat(Context context, AttributeSet attrs)
super(context, attrs);
public CustomSwitchCompat(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
public boolean isShown()
return getVisibility() == VISIBLE;
在你的布局中这样做:preference_switch_layout.xml
<com.example.CustomSwitchCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@android:id/checkbox"
android:layout_
android:layout_
android:background="@null"
android:clickable="false"
android:focusable="false"
app:switchMinWidth="55dp"/>
并在您的preference.xml 中执行以下操作:
<CheckBoxPreference
android:defaultValue="false"
android:key=""
android:widgetLayout="@layout/preference_switch_layout"
android:summary=""
android:title="" />
【讨论】:
【参考方案2】:有时从类扩展并不是最好的解决方案。为了避免丢失动画,您可以改为 Compose 它,我的意思是创建一个具有 SwitchPreference 字段变量的类并将新逻辑应用于它。这就像一个包装。这对我有用。
【讨论】:
【参考方案3】:看来我找到了解决您问题的方法。
详尽的解释
在SwitchCompat中,当切换开关时,它会在播放动画之前测试一些功能:getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown()
。
完整方法:
@Override
public void setChecked(boolean checked)
super.setChecked(checked);
// Calling the super method may result in setChecked() getting called
// recursively with a different value, so load the REAL value...
checked = isChecked();
if (getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown())
animateThumbToCheckedState(checked);
else
// Immediately move the thumb to the new position.
cancelPositionAnimator();
setThumbPosition(checked ? 1 : 0);
通过使用扩展SwitchCompat 的自定义视图,我发现isShown()
总是返回false
,因为while
的第三次迭代parent == null
。
public boolean isShown()
View current = this;
//noinspection ConstantConditions
do
if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE)
return false;
ViewParent parent = current.mParent;
if (parent == null)
return false; // We are not attached to the view root
if (!(parent instanceof View))
return true;
current = (View) parent;
while (current != null);
return false;
有趣的是,第三个父级是 Preference 中传递给 getView(View convertView, ViewGroup parent)
的第二个属性,这意味着 PreferenceGroupAdapter 没有将父级传递给它自己的 getView()
.为什么会发生这种情况以及为什么只会发生在自定义首选项类中,我不知道。
出于测试目的,我使用 CheckBoxPreference 和 SwitchCompat 作为widgetLayout
,我也没有看到动画。
修复
现在解决问题:只需让您自己的视图扩展 SwitchCompat,然后像这样覆盖您的 isShown()
:
@Override
public boolean isShown()
return getVisibility() == VISIBLE;
将此SwitchView 用于您的widgetLayout
样式,并且动画再次起作用:D
样式:
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
…
<item name="android:checkBoxPreferenceStyle">@style/Preference.SwitchView</item>
…
</style>
<style name="Preference.SwitchView">
<item name="android:widgetLayout">@layout/preference_switch_view</item>
</style>
小部件布局:
<de.Maxr1998.example.preference.SwitchView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/checkbox"
android:layout_
android:layout_
android:background="@null"
android:clickable="false"
android:focusable="false" />
【讨论】:
这听起来很有希望!但是,我确实在我的库(github.com/ferrannp/material-preferences)中尝试了它,但我没有让它工作(在棒棒糖之前没有动画)。你可能有一个工作回购吗? .顺便说一句,我在前棒棒糖上没有得到动画,无论是在开关上还是在复选框上。 动画适用于 Lollipop 及之前的版本。我没有为此设置存储库,无论如何它只是此处列出的代码。顺便说一句,这个解决方案也有一个错误,因为有时会在滚动列表时播放动画。此外,虽然显示正确的颜色,但有时开关的拇指在错误的一侧。..【参考方案4】:公共类 SwitchPreference 扩展 android.preference.SwitchPreference
public SwitchPreference(Context context)
this(context, null);
public SwitchPreference(Context context, AttributeSet attrs)
this(context, attrs, android.R.attr.checkBoxPreferenceStyle);
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr)
this(context, attrs, defStyleAttr, 0);
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
super(context, attrs, defStyleAttr, defStyleRes);
try
Field canRecycleLayoutField = Preference.class.getDeclaredField("mCanRecycleLayout");
canRecycleLayoutField.setAccessible(true);
canRecycleLayoutField.setBoolean(this, true);
catch (NoSuchFieldException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
【讨论】:
您好,您能详细说明一下吗?我试过了,我收到了java.lang.NoSuchFieldException: mCanRecycleLayout
错误。以上是关于在 Android Lollipop 中扩展 Preference 类 = 丢失动画的主要内容,如果未能解决你的问题,请参考以下文章
HttpResponseCache 在 Android Lollipop 中不起作用
Android Studio - 如何在 webview Lollipop 中上传文件 (Android 5.0)
在 Android 5.0 Lollipop 上不支持 calendarViewShown
在 Lollipop 崩溃前使用 android vector Drawables
Android onChange 事件未在 contentObserver 中触发,用于 android 5 (Lollipop) 上的 chrome 历史记录