HoloEverywhere

    Вот признайтесь: читая Android Interface Guidelines, вам не приходила мысль, что это все, конечно, офигенно, но на старые (2.3 <) Андроиды приходиться перелопачивать половину стилей, чтобы смахивало на Holo интерфейс?

    Или так: в последнем Андроиде есть ну просто офигенная фича, а вам вот нужно ее использовать?

    Самое первое, что приходит на ум: ActionBar и ActionBarSherlock.
    ABS — это замечательно, но одним ActionBar не отделаешься. Мы хотим Holo тему, а не только Holo бар, блин.

    Эх, такой привлекательный ActionMode на списках чего стоит…

    Позвольте представить вам HoloEverywhere — проект, целью которого является портирование Holo стиля, Holo виджетов и других фишек на Android 1.6 и старше.






    Все эти скриншоты сделаны на Android 2.1 (минимальная версия Андроида для ABS, но HoloEverywhere работает и на 1.6 с отключением ABS).

    Собственно, что уже сделано:
    • Стилизованы многие виджеты, такие как Button, ToggleButton, RadioButton, CheckBox, Spinner, (Multi)AutoCompleteTextView, RatingBar, ProgressBar, SeekBar и другие производные. Так-же есть и портированные: Switch, NumberPicker, CalendarView, DatePicker, TimePicker
    • Портирован AlertDialog, ProgressDialog, стилизован обычный Dialog (к сожалению, внутренности AlertDialog слишком закрыты для простого портирования темы, пришлось тянуть весь его код и создавать несовместимую со стандартным AlertDialog версию)
    • Портирован весь Preference Framework, создан SupportSharedPreferences, который умеет писать различные Set и JSON объекты/массивы (это уже как плюшка :))
    • Небольшой велосипед помощник для переключения тем для Activity
    • Везде используется еще один велосипед свой LayoutInflater, который может инфлейтить ваши вьюхи по короткому имени. Например, раньше вы писали так:
      <com.myapppackage.widgets.MySuperView ... />
      А теперь, если на старте приложения вызвать правильный метод с правильными параметрами, вы можете писать просто MySuperView, и это будет работать везде, где используется HE (в рамках текущего приложения, естественно).
      Из этого так-же следует, что вы можете подменить системные виджеты на свои, абсолютно не меняя разметок, в том числе и системных. Но если виджеты создаются из кода — тут уж ничего не поделаешь.
    • Собственно, ActionMode, про который я упоминал в начале поста. Дополненная реализация ListView, позволяет стартовать ActionMode из ABS


    Репозиторий проекта: github.com/ChristopheVersieux/HoloEverywhere
    Там-же инструкция по подключению к проекту.
    Скачать apk демки.

    В принципе, пока все, но вы можете помочь проекту — либо самым прямым путем (форкнуть проект, дополнить, отправить pull request), либо открыть feature request с описанием новой фичи, либо отправить письмо мне в личку, в конце-концов :)
    Share post

    Comments 140

      +2
      Отличный проект, не так давно пробовал — понравилось.
      Правда в самом ABS порой бывают такие косяки, что не хочется с ним лишний раз связываться
        0
        Круто, спасибо за работу! А FragmentActivity будет работать?
          0
          На скриншотах табы сделаны с abs на фрагментах, что уже как-бэ намекает…
          +1
          Количество старых все меньше и меньше…
          Проект плюсую однозначно.
          Планируете и дальше продолжать?
            0
            Меньше-то меньше, но пока на свете будет оставаться хоть 5% Android 2.3 — проект будет развиваться.
              0
              Как обстоят дела с меню? В демке нету.
                0
                Которое у ActionBar? Да нормально обстоят, работает, крутиться, нажимается. А в демке нету… Ну а зачем оно там? Это ведь даже не часть HE.
              0
              Однако все еще больше в 2 раза чем 4х. Так что еще 1-2 года есть в запасе
              0
              Ух ты! Некоторое время назад натыкался случайно на этот проект, а он, оказывается, местный-хабровский :)
              Огромное спасибо за эту работу! Скорее всего, буду использовать в будущих приложениях.
                +1
                Ага, я тоже, когда коммитил Toast в Holo стиле на 20 строчек, не думал, что стану чуть-ли не главным разрабом этого проекта :D
                  0
                  А с чего вы взяли, что он местный? Автор — Christophe Versieux.
                    +3
                    Можно оставить это здесь?
                    github.com/ChristopheVersieux/HoloEverywhere/graphs/contributors
                      0
                      Хаха, можно конечно =) Не думал, что кто-то может контрибьютить больше автора =)
                      0
                      Ну для кого местный а для кого нет, наверное как то.
                    0
                    Один здоровый минус данного проекта состоит в том что нужно наследовать от левой активности что бы использовать данную тему.

                    public class MainActivity extends com.WazaBe.HoloEverywhere.sherlock.SListActivity { ...

                    А как быть тем кто использует например RoboGuice?
                      0
                      Используйте че хотите. Просто реализуйте интерфейс Base для обычных активити и SBase для ABS. Ну, support методы (типо getSupportSharedPreferences) — по желанию.
                        0
                        Предполагаю, что также как с Sherlock Actionbar — тянуть ещё одну зависиомость: RoboguiceSherlock. Не заботятся разработчики о дизайне своих библиотек. Кстати, как выход — Roboguice можно использовать напрямую (без наследования от активитей ихних).
                          0
                          Знаю что не тема, но не могли бы вы мне в личку скинуть как использовать напрямую Roboguice ну или просто линк кинуть буду вам признателен.
                            +1
                            Можно просто посмотреть, что происходит в *SherlockActivity.

                            onCreate():
                            RoboGuice.getInjector(this).injectMembersWithoutViews(this);
                            

                            onContentChanged():
                            RoboGuice.getInjector(this).injectViewMembers(this);
                            

                              0
                              Тьфу, в *RoboguiceActivity конечно.
                          0
                          Либо взять сырцы (он же открытый?) RoboGuice и перелинковать его на нужные активити из HEE
                            0
                            Решение конечно, но гемморное нужно ведь будет все апдейты и бакфиксы в ваш проект сливать.
                              0
                              Судя по тому, что последний стейбл (2.0) вышел в мае — не очень :)
                          0
                          Отличная штука, сам использовал, но учитывайте что размер apk вырастет примерно на 1.5Мб
                            0
                            На 2 :) но сам НЕ весит 300 кб, остальное — шерлок.
                              0
                              Странно, у меня с ~300Кб выросло до 1.9Мб
                              В любом случае, проект хороший )
                                0
                                а можно использовать его без шерлока?
                                  0
                                  Ветка nosherlock пару дней назад появилась.
                              0
                              Подключил к проекту. Очень неплохо! Разве что у меня приложение с каплей функционала уже весит 30 метров :) Может это из-за дебаг версии? :)
                                0
                                … Сколько? Не, тут HE точно не причем :D
                                  0
                                  Нашел, почему такой размер большой. У меня IDEA почему-то скомпилила всю папку с демками, с гитом и т.д. Хотя по идее должна была подхватить только модуль… (
                                0
                                а все ресурсы (изображения итд) грузятся сразу все при загрузке приложения или по мере надобности?
                                  0
                                  По необходимости, ессно.
                                  0
                                  Спасибо Вам за замечательный проект. Пытаюсь подключить его к существующему приложению и возникла проблема: не отображается контекстное меню для элемента внутри ListView. Без HoloEverywhere отображается. Что поменял: фрагмент теперь наследует SFragment ну и родительский Activity наследует SActivity. Быть может я что-то упустил?
                                  Немного кода ListAdapter'а:
                                          @Override
                                          public View getView(final Photo photo, View convertView,
                                                  ViewGroup parent)
                                          {
                                              if (convertView == null)
                                              {
                                                  convertView = mInflater.inflate(
                                                          R.layout.list_item_newest_photos, parent, false);
                                              }
                                             ...
                                              final ImageView shareButton = (ImageView) convertView
                                                      .findViewById(R.id.share_button);
                                              registerForContextMenu(shareButton);
                                              shareButton.setOnClickListener(new OnClickListener()
                                              {
                                                  @Override
                                                  public void onClick(View v)
                                                  {
                                                      activePhoto = photo;
                                                      getSupportActivity().openContextMenu(shareButton);
                                                  }
                                              });
                                              return convertView;
                                          }
                                  
                                    +1
                                    Путем отладки выяснил, что onClick метод вызывается корректно, но вот метод onCreateContextMenu внутри фрагмента не вызывается.
                                      0
                                      Так как-бы это… ContextMenu вообще нигде не перезаписывается/изменяется… А просто с ActionBarSherlock оно открывается?
                                        0
                                        Открывалось. Устанавливая Holoeverywhere обновил и ABS. Может это вылезло с обновлением. Сейчас проверю
                                          0
                                          Проверил. Ревертнул изменения и если Activity наследует SherlockFragmentActivity а Фрагмент наследует SherlockFragment то все работает
                                            0
                                            Я уже и разные варианты пробовал вызова меню отсюда stackoverflow.com/questions/3722380/android-open-contextmenu-on-short-click-pass-item-clicked-details, но не один не работает если использовать SActivity и SFragment.
                                              0
                                              Только заметил, ваш SFragment не наследует SherlockFragment, может в этом причина?
                                                0
                                                Я вам больше расскажу. (S)(List)Activity, (S)(List)Fragment и все остальные — никто не наследуется от шерлоковских фрагментов/активити.
                                                  0
                                                  Да, я уже заметил. Только вот причина проблемы не ясна.
                                                    0
                                                    Может стоит открыть issue на github'е?
                                                      0
                                                      А толку? Думаете, кто-то вам поможет, кроме 16-и летнего пацана? :D
                                                      Изучаемс феномен, подождите:)
                                                        0
                                                        Стоооп, вы registerForContextMenu вызываете в Activity?
                                                          0
                                                          Нет, в фрагменте
                                                            0
                                                            а точнее даже в ListAdapter'е по событию getView
                                                              0
                                                              Ну тогда у меня для вас плохие новости:

                                                              	public void showAlertDialog(View v) {
                                                              		MainFragment.getInstance().registerForContextMenu(v);
                                                              		openContextMenu(v);
                                                              	}
                                                              

                                                              MainFragment:
                                                              	@Override
                                                              	public void onCreateContextMenu(ContextMenu menu, View v,
                                                              			ContextMenuInfo menuInfo) {
                                                              		menu.add("Label 1");
                                                              		menu.add("Label 2");
                                                              	}
                                                              

                                                              image
                                                                0
                                                                Спасибо за пример. Но, вероятно, когда объект находится внутри ListView это не хочет работать. Попробую еще покопать, может тестовый пример сделаю
                                                                  0
                                                                  Кстати, а это вполне возможно… Там немного кривоватая реализация ListView, пойду покопаю…

                                                                  Попробуйте переименовать <ListView> в разметке на <android.widget.ListView>
                                                                    0
                                                                    Кстати, я сейчас как-раз работаю над стилизацией ContextMenu, можете просто пару дней подождать.
                                                                      0
                                                                      Спасибо большое, буду ждать. Ну и если выкрою время попытаюсь накатать вам тестовый проект
                                                                        0
                                                                        Вроде запилил, смотреть dev ветку :)
                                                                          0
                                                                          Спасибо, буду пробовать
                                                                            0
                                                                            вариант с getActivity().openContextMenu не работает. Пробую другие
                                                                              0
                                                                              К сожалению, другие варианты тоже не работают. onCreateContextMenu вообще не вызывается.
                                                                              Я уж по всякому пробовал, чтоб для верности:
                                                                              registerForContextMenu(v);
                                                                              list.showContextMenuForChild(v);
                                                                              getSupportActivity().openContextMenu(v);
                                                                              unregisterForContextMenu(v);
                                                                              
                                                                                0
                                                                                openContextMenu где-то в дебрях выкидывает method not implemented exception. Сейчас постараюсь дать больше инфы, т.к. в LogCat он не светится
                                                                                  0
                                                                                  В дебрях View если дебажить выскакивает исключение, но посмотреть значения переменных не удается
                                                                                  throw new IllegalStateException(«Could not find a method » +
                                                                                  handlerName + "(View) in the activity "
                                                                                  + getContext().getClass() + " for onClick handler"
                                                                                  + " on view " + View.this.getClass() + idText, e);
                                                                                  0
                                                                                  Я набросал тестовый проект, который показывает, что onCreateContextMenu не вызывается. Если в примере поменять SActivity на SherlockFragmentActivity и SFragment на SherlockFragment то все работает и в логе пишет
                                                                                  10-19 08:58:04.124: I/System.out(833): OnClick 10-19 08:58:04.124: I/System.out(833): Create context menu here 10-19 08:58:04.124: I/System.out(833): Create context menu here 2
                                                                                  Пофиксите только зависимосты, пожалуйста
                                                                                  dl.dropbox.com/u/37011471/Openphoto/ContextTestProject.zip
                                                                                    0
                                                                                    import android.view.ContextMenu;

                                                                                    Это ничего, что onCreateContextMenu с android.view.ContextMenu — final?
                                                                                    А использовать надо с тем, который лежит в com.actionbarsherlock.

                                                                                    Вообще — да, косячная реализация ListView, плюс вы использовали BaseContext, что делать ооочень не рекомендуется. Если сменить на android.widget.ListView, все работает:
                                                                                    image
                                                                                    Ну как все… Опять-же бага: onCreateContextMenu вызывается у активити, а не фрагмента, пойду колупать…
                                                                                      0
                                                                                      Ну как косячная… в одном месте вместо false стоит true…
                                                                                        0
                                                                                        Это ничего, что onCreateContextMenu с android.view.ContextMenu — final?
                                                                                        А использовать надо с тем, который лежит в com.actionbarsherlock.

                                                                                        Как же так, почему же компилятор не матерится и дает переопределить?

                                                                                        Вообще в приложении я не использую BaseContext, там кнопка берется из View созданного LayoutInflater'ом.
                                                                                          0
                                                                                          Не знаю, скорей-всего вы херово склонировали репу или аналогично перелючились на dev ветку.

                                                                                          А по поводу некорректного вызова onCreateContextMenu — то-же нашел причину, сейчас запушаю оба фикса.
                                                                                            0
                                                                                            Готово.
                                                                                              0
                                                                                              Проверяю
                                                                                                0
                                                                                                abs тоже надо на dev версию переключиться?
                                                                                                  0
                                                                                                  Нет
                                                                                                    0
                                                                                                    тестовый проект не завелся. Как же там правильно вызвать контекстное меню для кнопки?
                                                                0
                                                                Возникла проблемка с SDialogFragment и SActivity.

                                                                Диалог создаю так:

                                                                private void showDialog() {
                                                                if (null == dialogFragment) {
                                                                dialogFragment = new AuthDialogFragment();
                                                                }

                                                                final FragmentManager fm = getSupportFragmentManager();
                                                                final FragmentTransaction ft = fm.beginTransaction();
                                                                if (dialogFragment.isVisible()) {
                                                                dialogFragment.replace(ft);
                                                                } else {
                                                                dialogFragment.show(ft);
                                                                }
                                                                }

                                                                Что странно, метод public void show(FragmentManager manager, String tag) помечен как деприкейтед… :(

                                                                Так вот диалог отображается. Но при попытке повернуть экран приложение падает с такой ошибкой:
                                                                ERROR/AndroidRuntime(23786): FATAL EXCEPTION: main
                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{mega.app/mega.app.AuthenticatorActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment mega.app.AuthenticatorActivity$AuthDialogFragment: make sure class name exists, is public, and has an empty constructor that is public

                                                                Не могу разобраться, в чем дело… видимо он пытается восстановить диалог фрагмен автоматически где-то в/или после onCreate… Но почему не удается — не ясно…

                                                                Пысы На хабре не пашут теги code и source… Забавно…
                                                                  0
                                                                  А вы проверили публичный ли класс, имеет ли пустой конструктор?
                                                                    0
                                                                    еще объявите его static
                                                                      0
                                                                      Класс публичный, внутренный, не статический, с публичным пустым конструктором, да.
                                                                        0
                                                                        статичным сделайте
                                                                          0
                                                                          А нужен статический. И вот эта конструкция:
                                                                          if (dialogFragment.isVisible()) {
                                                                            dialogFragment.replace(ft);
                                                                          } else {
                                                                            dialogFragment.show(ft);
                                                                          }
                                                                          

                                                                          излишняя, просто replace сработает корректно.
                                                                            0
                                                                            Пичалька… надо тогда как-то иначе переписать :) А то статика мне тут не совсем подходит… спасибо :)
                                                                      0
                                                                      DialogFragment.show(FragmentManager manager, String tag) является deprecated. Какой же тогда правильный способ показа диалога?
                                                                        0
                                                                        Если использую этот метод, то вылетает исключение
                                                                        10-19 10:58:35.726: E/AndroidRuntime(1117): java.lang.NullPointerException 10-19 10:58:35.726: E/AndroidRuntime(1117): at com.actionbarsherlock.internal.view.menu.ContextMenuDecorView.<init>(ContextMenuDecorView.java:54) 10-19 10:58:35.726: E/AndroidRuntime(1117): at com.WazaBe.HoloEverywhere.app.Fragment.prepareDecorView(Fragment.java:121) 10-19 10:58:35.726: E/AndroidRuntime(1117): at com.WazaBe.HoloEverywhere.app.Fragment.onCreateView(Fragment.java:89) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:871) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1083) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:635) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1431) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.os.Handler.handleCallback(Handler.java:587) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.os.Handler.dispatchMessage(Handler.java:92) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.os.Looper.loop(Looper.java:123) 10-19 10:58:35.726: E/AndroidRuntime(1117): at android.app.ActivityThread.main(ActivityThread.java:4363) 10-19 10:58:35.726: E/AndroidRuntime(1117): at java.lang.reflect.Method.invokeNative(Native Method) 10-19 10:58:35.726: E/AndroidRuntime(1117): at java.lang.reflect.Method.invoke(Method.java:521) 10-19 10:58:35.726: E/AndroidRuntime(1117): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 10-19 10:58:35.726: E/AndroidRuntime(1117): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 10-19 10:58:35.726: E/AndroidRuntime(1117): at dalvik.system.NativeStart.main(Native Method)

                                                                        Если же просто show() использую, то вылетает такое исключение

                                                                        10-19 11:02:16.095: E/AndroidRuntime(1132): java.lang.NullPointerException 10-19 11:02:16.095: E/AndroidRuntime(1132): at com.WazaBe.HoloEverywhere.app.DialogFragment.show(DialogFragment.java:303)
                                                                          0
                                                                          replace(FragmentManager)
                                                                            0
                                                                            К сожалению не работает
                                                                            10-19 11:53:27.903: E/AndroidRuntime(1166): java.lang.NullPointerException 10-19 11:53:27.903: E/AndroidRuntime(1166): at com.actionbarsherlock.internal.view.menu.ContextMenuDecorView.<init>(ContextMenuDecorView.java:54) 10-19 11:53:27.903: E/AndroidRuntime(1166): at com.WazaBe.HoloEverywhere.app.Fragment.prepareDecorView(Fragment.java:121) 10-19 11:53:27.903: E/AndroidRuntime(1166): at com.WazaBe.HoloEverywhere.app.Fragment.onCreateView(Fragment.java:89)
                                                                              0
                                                                              Обновитесь:)
                                                                                0
                                                                                Шустро вы коммиты строчите :)
                                                                                  0
                                                                                  dev ведь:)
                                                                                    0
                                                                                    Спасибо, диалоги заработали, но Facebook SDK окна убивают приложение
                                                                                    10-19 12:07:23.723: E/AndroidRuntime(1216): java.lang.ClassCastException: com.WazaBe.HoloEverywhere.widget.ProgressBar 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.app.ProgressDialog.onCreate(ProgressDialog.java:146) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.app.Dialog.dispatchOnCreate(Dialog.java:308) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.app.Dialog.show(Dialog.java:225) 10-19 12:07:23.723: E/AndroidRuntime(1216): at com.facebook.android.FbDialog$FbWebViewClient.onPageStarted(FbDialog.java:181) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:234) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.os.Handler.dispatchMessage(Handler.java:99) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.os.Looper.loop(Looper.java:123) 10-19 12:07:23.723: E/AndroidRuntime(1216): at android.app.ActivityThread.main(ActivityThread.java:4363) 10-19 12:07:23.723: E/AndroidRuntime(1216): at java.lang.reflect.Method.invokeNative(Native Method) 10-19 12:07:23.723: E/AndroidRuntime(1216): at java.lang.reflect.Method.invoke(Method.java:521)
                                                                                      0
                                                                                      Берем исходники sdk и перелинковываем на нужные классы из HE
                                                                                        0
                                                                                        Таки придется. Спасибо
                                                                        0
                                                                        На эмуляторе версии 2.1 при использовании HoloEverywhere получаю такие сообщения:

                                                                        10-22 06:44:42.368: E/ResourceType(52): Style contains key with bad entry: 0x010102f0 10-22 06:44:42.368: E/ResourceType(52): Style contains key with bad entry: 0x010102fd 10-22 06:44:42.368: E/ResourceType(52): Style contains key with bad entry: 0x01010308 10-22 06:44:42.368: E/ResourceType(52): Style contains key with bad entry: 0x0101030a 10-22 06:44:42.368: E/ResourceType(52): Style contains key with bad entry: 0x0101032c

                                                                        Т.е. где-то в holoeverywhere стилях используются атрибуты более поздних версий SDK
                                                                          0
                                                                          Я в курсе, проблема то в чем?
                                                                            0
                                                                            Не красиво, просто. Надо разделить стили по версиям. Только вот какие?..
                                                                              0
                                                                              Ну его нафиг, там еще весь builder переписать надо, который кое-как компиляет стили для v14 и для остальных, кучей регулярок, работает кое-как. А пара безобидных строчек особо не мешается:)
                                                                          0
                                                                          Что нужно сделать, чтобы стиль HoloEverywhere применился к SDialogFragment'у?
                                                                            0
                                                                            Кажись разобрался, применил тему из Holoeverywhere Holo.Theme.Light.Dialog
                                                                            0
                                                                            Не подскажите с проблемой. В проекте используется класс ApectRatioImageView взятый отсюда stackoverflow.com/a/4688335/527759
                                                                            Так вот при использовании с HoloEverywhere, в логе теперь постоянно выскакивают ошибки
                                                                            Скрытый текст
                                                                            10-25 08:52:12.031: W/System.err(501): java.lang.ClassNotFoundException: android.view.me.openphoto.android.app.ui.widget.AspectRatioImageView in loader dalvik.system.PathClassLoader@44e8d030 10-25 08:52:12.041: W/System.err(501): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243) 10-25 08:52:12.051: W/System.err(501): at java.lang.ClassLoader.loadClass(ClassLoader.java:573) 10-25 08:52:12.051: W/System.err(501): at java.lang.ClassLoader.loadClass(ClassLoader.java:532) 10-25 08:52:12.051: W/System.err(501): at android.view.LayoutInflater.createView(LayoutInflater.java:466) 10-25 08:52:12.051: W/System.err(501): at com.WazaBe.HoloEverywhere.LayoutInflater.onCreateView(LayoutInflater.java:219) 10-25 08:52:12.061: W/System.err(501): at com.WazaBe.HoloEverywhere.LayoutInflater.onCreateView(LayoutInflater.java:226) 10-25 08:52:12.061: W/System.err(501): at com.WazaBe.HoloEverywhere.LayoutInflater$HoloFactoryMerger.onCreateView(LayoutInflater.java:33) 10-25 08:52:12.061: W/System.err(501): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558) 10-25 08:52:12.061: W/System.err(501): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) 10-25 08:52:12.061: W/System.err(501): at android.view.LayoutInflater.rInflate(LayoutInflater.java:621) 10-25 08:52:12.061: W/System.err(501): at android.view.LayoutInflater.inflate(LayoutInflater.java:407) 10-25 08:52:12.061: W/System.err(501): at android.view.LayoutInflater.inflate(LayoutInflater.java:320) 10-25 08:52:12.071: W/System.err(501): at me.openphoto.android.app.HomeFragment$NewestPhotosAdapter.getView(HomeFragment.java:369) 10-25 08:52:12.071: W/System.err(501): at me.openphoto.android.app.HomeFragment$NewestPhotosAdapter.getView(HomeFragment.java:1) 10-25 08:52:12.071: W/System.err(501): at me.openphoto.android.app.ui.adapter.EndlessAdapter.getView(EndlessAdapter.java:67) 10-25 08:52:12.071: W/System.err(501): at android.widget.AbsListView.obtainView(AbsListView.java:1274) 10-25 08:52:12.071: W/System.err(501): at android.widget.ListView.measureHeightOfChildren(ListView.java:1147) 10-25 08:52:12.071: W/System.err(501): at android.widget.ListView.onMeasure(ListView.java:1060) 10-25 08:52:12.071: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.071: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.081: W/System.err(501): at com.WazaBe.HoloEverywhere.widget.LinearLayout.measureChildWithMargins(LinearLayout.java:231) 10-25 08:52:12.081: W/System.err(501): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:888) 10-25 08:52:12.081: W/System.err(501): at android.widget.LinearLayout.measureVertical(LinearLayout.java:350) 10-25 08:52:12.081: W/System.err(501): at android.widget.LinearLayout.onMeasure(LinearLayout.java:278) 10-25 08:52:12.081: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.081: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.081: W/System.err(501): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245) 10-25 08:52:12.081: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.091: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.091: W/System.err(501): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245) 10-25 08:52:12.091: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.091: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.101: W/System.err(501): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245) 10-25 08:52:12.101: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.101: W/System.err(501): at android.widget.LinearLayout.measureVertical(LinearLayout.java:464) 10-25 08:52:12.101: W/System.err(501): at android.widget.LinearLayout.onMeasure(LinearLayout.java:278) 10-25 08:52:12.111: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.111: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.121: W/System.err(501): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245) 10-25 08:52:12.121: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.121: W/System.err(501): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023) 10-25 08:52:12.121: W/System.err(501): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245) 10-25 08:52:12.121: W/System.err(501): at android.view.View.measure(View.java:7964) 10-25 08:52:12.133: W/System.err(501): at android.view.ViewRoot.performTraversals(ViewRoot.java:763) 10-25 08:52:12.133: W/System.err(501): at android.view.ViewRoot.handleMessage(ViewRoot.java:1633) 10-25 08:52:12.133: W/System.err(501): at android.os.Handler.dispatchMessage(Handler.java:99) 10-25 08:52:12.133: W/System.err(501): at android.os.Looper.loop(Looper.java:123) 10-25 08:52:12.133: W/System.err(501): at android.app.ActivityThread.main(ActivityThread.java:4363) 10-25 08:52:12.133: W/System.err(501): at java.lang.reflect.Method.invokeNative(Native Method) 10-25 08:52:12.141: W/System.err(501): at java.lang.reflect.Method.invoke(Method.java:521) 10-25 08:52:12.141: W/System.err(501): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 10-25 08:52:12.141: W/System.err(501): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 10-25 08:52:12.141: W/System.err(501): at dalvik.system.NativeStart.main(Native Method)

                                                                            View создается через Inflater
                                                                                            convertView = mInflater.inflate(
                                                                                                    R.layout.list_item_newest_photos, parent, false);
                                                                            
                                                                              0
                                                                              Должно быть исправлено в dev ветке, а вообще — я забыл про не системные виджеты.
                                                                              Можно жестко указать пакет через LayoutInflater.remap(Hard)
                                                                                0
                                                                                Спасибо, попробую
                                                                                  0
                                                                                  без изменений. Помимо этого, получаю еще кучу сообщений касательно ABS библиотеки
                                                                                  10-25 09:48:03.061: W/System.err(606): java.lang.ClassNotFoundException: android.view.com.actionbarsherlock.internal.widget.CapitalizingButton in loader dalvik.system.PathClassLoader@44e8d030
                                                                                    0
                                                                                    Интересно, что это касается виджетов и самой библиотеки. Например, когда я вызываю контекстное меню, в логе светится такое
                                                                                    10-25 09:51:40.911: W/System.err(606): java.lang.ClassNotFoundException: android.view.com.WazaBe.HoloEverywhere.internal.DialogTitle in loader dalvik.system.PathClassLoader@44e8d030 10-25 09:51:40.931: W/System.err(606): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243) 10-25 09:51:40.931: W/System.err(606): at java.lang.ClassLoader.loadClass(ClassLoader.java:573) 10-25 09:51:40.931: W/System.err(606): at java.lang.ClassLoader.loadClass(ClassLoader.java:532) 10-25 09:51:40.931: W/System.err(606): at android.view.LayoutInflater.createView(LayoutInflater.java:466) 10-25 09:51:40.931: W/System.err(606): at com.WazaBe.HoloEverywhere.LayoutInflater.onCreateView(LayoutInflater.java:214) 10-25 09:51:40.931: W/System.err(606): at com.WazaBe.HoloEverywhere.LayoutInflater.onCreateView(LayoutInflater.java:221)
                                                                                      0
                                                                                      Минуту, оно просто светится, или еще и крешится?
                                                                                        0
                                                                                        к счастью только светится. Но таких сообщений уйма. Можно как-то выключить?
                                                                                          0
                                                                                          М, минуту, девушка выкидывает из-за компа. Приду — сделаю:)
                                                                                0
                                                                                Заметил еще одну проблему. После включения Holoeverywhere в проект стал странно себя вести ABS. Дело в том, что в зависимости от того, какая вкладка выбрана я меняю видимость некоторых MenuItems. Так вот, после нескольких таких изменений видимости и включения Indeterminate Progress, кнопки могут съехать влево а то и вообще исчезнуть. Может подскажете куда копать?
                                                                                github.com/photo/mobile-android/issues/128
                                                                                  0
                                                                                  Тут я так и не нашел фикса. Пришлось добавить пустое меню, которое держит место для скрываемого чтобы кнопки не ездили туда сюда. Но зато прогрес теперь показывается посередине
                                                                                  0
                                                                                  Похоже, что AlertDialog.Builder игнорирует setTitle и показывает текст «Title» вместо переданного параметра.
                                                                                    0
                                                                                    Также, похоже, не отрабатывает setOnCancelListener для AlertDialog
                                                                                      0
                                                                                      OnDismissListener тоже не вызывается
                                                                                    0
                                                                                    В SFragment не отображается прогресбар если не указан стиль.
                                                                                      0
                                                                                      У вас прям фантастические баги.
                                                                                      Никто, кроме вас, их пока не подтверждает :)
                                                                                        0
                                                                                        Я их не придумываю. Попробуйте сами в своем демо убрать атрибут стиль у ProgressBar. По дефолту этот атрибут отсутствует у маленького индикатора. Это то я профиксил добавив стиль style="?android:attr/progressBarStyle". Но вот с AlertDialog то что делать? Я его добавляю через DialogFragment.
                                                                                          0
                                                                                          Тут код, если интересно github.com/photo/mobile-android/blob/master/app/src/me/openphoto/android/app/UploadActivity.java ищите SelectImageDialogFragment. OnCancelListener не вызывается никогда, я проверял отладчиком. Также setTitle просто игнорируется.
                                                                                            0
                                                                                            Ммм, да, багу ProgressBar признаю. А вот со всем остальным думаю одна проблема — неверный Context.
                                                                                              0
                                                                                              куда то хоть копать? Там как контекст берется getActivity() из DialogFragment
                                                                                                0
                                                                                                По диалогу: никуда не копать, у вас код немного не верный:
                                                                                                	public void onActivityCreated(Bundle savedInstanceState) {
                                                                                                		super.onActivityCreated(savedInstanceState);
                                                                                                ...
                                                                                                		mDialog.setOnCancelListener(this);
                                                                                                		mDialog.setOnDismissListener(this);
                                                                                                
                                                                                                
                                                                                                У вас и с нативным DialogFragment такая фича не прокатит. Переопределяйте методы прямо во фрагменте.
                                                                                                  0
                                                                                                  Т.е. я должен создать диалог через builder.create(). А уже потом вызывать setTitle, setOnCancelListener?
                                                                                                    0
                                                                                                    Да нет.
                                                                                                    Вот немного подправленный фрагмент из того файла, что вы дали выше:
                                                                                                        public static class SelectImageDialogFragment extends CommonDialogFragment
                                                                                                        {
                                                                                                            public static interface SelectedActionHandler extends Serializable
                                                                                                            {
                                                                                                                void cameraOptionSelected();
                                                                                                    
                                                                                                                void galleryOptionSelected();
                                                                                                            }
                                                                                                    
                                                                                                            private SelectedActionHandler handler;
                                                                                                    
                                                                                                            public static SelectImageDialogFragment newInstance(
                                                                                                                    SelectedActionHandler handler)
                                                                                                            {
                                                                                                                SelectImageDialogFragment frag = new SelectImageDialogFragment();
                                                                                                                frag.handler = handler;
                                                                                                                return frag;
                                                                                                            }
                                                                                                    
                                                                                                            @Override
                                                                                                            public void onCancel(DialogInterface dialog) {
                                                                                                              getActivity().finish();
                                                                                                            }
                                                                                                    
                                                                                                            @Override
                                                                                                            public Dialog onCreateDialog(Bundle savedInstanceState) {
                                                                                                                final CharSequence[] items = {
                                                                                                                        getString(R.string.upload_camera_option),
                                                                                                                        getString(R.string.upload_gallery_option)
                                                                                                                };
                                                                                                    
                                                                                                                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                                                                                                                builder.setTitle(R.string.upload_title);
                                                                                                                builder.setItems(items, new DialogInterface.OnClickListener() {
                                                                                                                    @Override
                                                                                                                    public void onClick(DialogInterface dialog, int item) {
                                                                                                                        if (handler == null)
                                                                                                                        {
                                                                                                                            return;
                                                                                                                        }
                                                                                                                        switch (item) {
                                                                                                                            case 0:
                                                                                                                                handler.cameraOptionSelected();
                                                                                                                                return;
                                                                                                                            case 1:
                                                                                                                                handler.galleryOptionSelected();
                                                                                                                                return;
                                                                                                                        }
                                                                                                                    }
                                                                                                                });
                                                                                                                return builder.create();
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                    
                                                                                                    

                                                                                                    А с setTitle — будем разбираться.
                                                                                                      0
                                                                                                      спасибо, сейчас попробую
                                                                                                        0
                                                                                                        Спасибо, отлично работает
                                                                                          0
                                                                                          Не работает вставка фрагментов через xml layout
                                                                                          11-01 11:45:57.178: E/AndroidRuntime(18873): Caused by: java.lang.ClassNotFoundException: Could not find class: fragment 11-01 11:45:57.178: E/AndroidRuntime(18873): at com.WazaBe.HoloEverywhere.LayoutInflater.onCreateView(LayoutInflater.java:229) 11-01 11:45:57.178: E/AndroidRuntime(18873): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
                                                                                            0
                                                                                            Ага, бага. На будущее: может таки перейдем на трекер гитхаба, он более предназначен для баг-репортов, нежели хабр ;)
                                                                                              0
                                                                                              Да, конечно. Я просто руководствовался вашим ответом на предложение.

                                                                                              Может стоит открыть issue на github'е?


                                                                                              А толку? Думаете, кто-то вам поможет, кроме 16-и летнего пацана? :D
                                                                                              Изучаемс феномен, подождите:)
                                                                                                0
                                                                                                Дык это, раз уж тут сообщили, че гитхаб терзать? Кстати, <fragment> пофикшен.
                                                                                                  0
                                                                                                  Спасибо за вашу работу
                                                                                            0
                                                                                            Не подскажете как правильно пользоваться SharedPreferences в связке с PreferenceFragment? Я обнаружил, что PreferenceFragment создает json файл. Тогда как в приложении getSharedPreferences читает из xml файла с тем же именем.
                                                                                              0
                                                                                              в PreferenceFragment.onCreate я пытался переопределить имя и тип
                                                                                              getPreferenceManager().setSharedPreferencesName(«default»);
                                                                                              getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
                                                                                                0
                                                                                                Получать объект SharedPrefernces от PreferenceManager из пакета HoloEverywhere.
                                                                                                  0
                                                                                                  Сложновато тогда будет использовать одни и те же опции одновременно в сервисе и приложении, особенно если package name у них разный. Или ошибаюсь?
                                                                                                    0
                                                                                                    Тогда просто смените используемую имплементацию на дефолтовую xml.

                                                                                                    Application.getConfig().setPreferenceImpl(PreferenceImpl.XML);

                                                                                                    Ну или что-то типо того, точно не помню, а на код пыриться лень.
                                                                                                      0
                                                                                                      Хм, а вы не думали, что надо заменить реализацию метода getSharedPreferences в com.WazaBe.HoloEverywhere.app.Application, чтобы использовались текущие настройки PreferenceImpl? А то получается используешь один контекст, создается xml, используешь другой, создается то ли json то ли xml в зависимости от настроек.
                                                                                                        0
                                                                                                        Хотя, вроде как, разобрался, что можно использовать статический метод PreferenceManager.wrap. Кастомные preferences это было так неочевидно для меня. Была куча багов, когда записывались опции в Activity а уже в сервисе прочитать их не мог.
                                                                                                          0
                                                                                                          Это еще ничего, вот новая версия выйдет...

                                                                                                          А по теме — добавлю пару нотайсов о SharedPreferences в вики.
                                                                                                          Нет, не так.
                                                                                                          Создам вики, и добавлю пару нотайсов.
                                                                                                            0
                                                                                                            Да, я уже предвкушаю последствия рефакторинга в dev ветке, где вы попереименовывали половину классов :)
                                                                                                              0
                                                                                                              Половину? Все :D
                                                                                                              Просто купили домен holoeverywhere.org, потихоньку туда переезжаем, мавен тоже.

                                                                                                              Хотя почему «купили»?
                                                                                                              Все на мои кровные, еще ни одного доната не было ведь :D
                                                                                                                0
                                                                                                                По поводу SharedPreferences, может стоит по умолчанию оставить XML реализацию? Представьте миграцию на Holoeverywhere. Половина Activities уже переведена, а половина еще стандартны (так было у меня). В одних Activities используются старые опции xml, а в других уже json. Я то уже наступил на эти далеко неочевидные грабли, но, вероятно, кто-то еще может наступить. Ну или сделайте migration guide какой-нибудь
                                                                                                                  0
                                                                                                                  Я-же грю, если в static блоке Application объекта вызвать getConfig().setPreferenceImpl(PreferenceImpl.XML), то xml реализация будет использоваться везде. Вы, скорей-всего, не там его вызвали, поэтому реализации поделились между двумя :)

                                                                                                                  Только Application должен наследоваться от org.holoeverywhere.app.Application.
                                                                                                                    0
                                                                                                                    Ну это я понял и уже решил проблему для себя. Но это стоило кучу времени найти, почему все работает не так как я думал. Если по умолчанию будет использоваться PreferenceImpl.XML то многие не наступят на эти грабли.
                                                                                                                      0
                                                                                                                      Я подумаю.
                                                                                                                    0
                                                                                                                    Упс, чутка прочитал ветку — да, getSharedPreferences в Application забыл.
                                                                                                              0
                                                                                                              -deleted-

                                                                                                  Only users with full accounts can post comments. Log in, please.