Обновить анимацию элемента меню в ActionBarSherlock
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return true;
case R.id.searchIcon:
return true;
case R.id.startRefresh:
refreshItem = item;
refresh();
return true;
case R.id.stopRefresh:
if (refreshItem != null && refreshItem.getActionView() != null) {
refreshItem.getActionView().clearAnimation();
refreshItem.setActionView(null);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void refresh() {
if (FeedActivity.this != null) {
/*
* Attach a rotating ImageView to the refresh item as an ActionView
*/
LayoutInflater inflater = (LayoutInflater) FeedActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageView iv = (ImageView) inflater.inflate(
R.layout.refresh_action_view, null);
Animation rotation = AnimationUtils.loadAnimation(
FeedActivity.this, R.anim.clockwise_refresh);
rotation.setRepeatCount(Animation.INFINITE);
iv.startAnimation(rotation);
refreshItem.setActionView(iv);
}
}
До щелчка:
![enter image description here]()
После нажатия:
![enter image description here]()
Здесь значок анимируется (вращается).
Проблема:
почему он смещается влево?
как только он сдвинется влево, значок становится неактивным и, как ни странно, кнопка возврата устройства также не работает.
EDIT:
В комментариях ниже этого ответа:
Анимированная иконка для ActionItem
Джейк Уортон говорит, что если вы используете квадратный и правильный размер значка для элемента меню, вы не получите это странное поведение, к кому-то, у кого такая же проблема.
Но я использую изображение 32x32 на устройстве, которое использует mdpi drawables. Что, как указано, должно работать: (
Спасибо
EDIT:
refresh_action_view.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.Sherlock.ActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_refresh" />
Пользовательский стиль, который я использую в своем приложении
<style name="My_solid_ActionBar" parent="@style/Widget.Sherlock.Light.ActionBar.Solid.Inverse">
<item name="background">@drawable/ab_solid_My</item>
<item name="backgroundStacked">@drawable/ab_stacked_solid_My</item>
<item name="backgroundSplit">@drawable/ab_bottom_solid_My</item>
<item name="progressBarStyle">@style/My_ProgressBar</item>
<item name="android:background">@drawable/ab_solid_My</item>
<item name="android:backgroundStacked">@drawable/ab_stacked_solid_My</item>
<item name="android:backgroundSplit">@drawable/ab_bottom_solid_My</item>
<item name="android:progressBarStyle">@style/My_ProgressBar</item>
</style>
Ответы
Ответ 1
Проблема заключается в том, что вы не обрабатываете все инфузии меню в onCreateOptionsMenu()
. Основная логика анимации обновления ActionBar
, которую я видел, используется в приложениях с открытым исходным кодом, например Andlytics (а также использовала себя в проектах), заключается в реализации флага boolean
в onCreateOptionsMenu()
, чтобы решить, показывать ли анимацию обновления.
Вы можете реализовать его следующим образом: Когда вы вызываете метод refresh()
, он устанавливает флаг boolean
isRefreshing
в true и вызывает inValidateOptionsMenu()
, который "за сценой" вызывает onCreateOptionsMenu()
, чтобы запустить анимацию
Наполните меню в onCreateOptionsMenu(...)
:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
super.onCreateOptionsMenu(menu, inflater);
//inflate a menu which shows the non-animated refresh icon
inflater.inflate(R.menu.my_ab_menu, menu);
if (isRefreshing) {
//if we're refreshing, show the animation
MenuItem item = menu.findItem(R.id.refreshMenuItem);
item.setActionView(R.layout.action_bar_indeterminate_progress);
ImageView iv = (ImageView) item.getActionView().findViewById(R.id.loadingImageView);
((AnimationDrawable) iv.getDrawable()).start();
}
}
Начните анимацию так:
public void refresh(){
isRefreshing = true;
inValidateOptionsMenu();
}
Если вы хотите, чтобы пользователь запустил анимацию, когда он нажал значок обновления, выполните следующие действия в onOptionsItemSelected()
:
case R.id.refreshMenuItem:
isRefreshing = true;
item.setActionView(R.layout.action_bar_indeterminate_progress);
ImageView iv = (ImageView) item.getActionView().findViewById(R.id.loadingImageView);
((AnimationDrawable) iv.getDrawable()).start();
//...
Чтобы остановить вызов анимации:
isRefreshing = false;
invalidateOptionsMenu();
Этот код от Fragment
, поэтому вам может потребоваться настроить, если для Activity
, но я думаю, что он передает основную идею.
Ответ 2
Я попробовал тот же самый код, который вы используете, и он отлично подходит для меня. Единственное, что может быть иначе, это две вещи:
1) макет refresh_action_view (здесь мой для сравнения):
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_menu_refresh" />
2) Параметры отображения вашей панели действий (здесь мои styles.xml для сравнения).
<resources>
<style name="AppTheme" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/Widget.ActionBar</item>
<item name="actionBarStyle">@style/Widget.ActionBar</item>
</style>
<style name="Widget.ActionBar" parent="Widget.Sherlock.Light.ActionBar.Solid.Inverse">
<item name="android:displayOptions">showHome|useLogo|showCustom</item>
<item name="displayOptions">showHome|useLogo|showCustom</item>
</style>
</resources>
Можете ли вы поделиться своим?