Жизнь свою этот блог начал по одной простой причине: слишком много вопросов… Задают их везде: на работе, по ICQ, знакомые и вобще разные люди. Задумывалось все это для того чтобы собрать как можно больше интересного о разработке для мобильных устройств, и чтобы весь собранный материал помог хотя бы от части этих вопросов, о которых я говорил ранее, избавиться.
Итак, блог о программировании, для программистов и людей им сочуствующих. Информация намечается разная и о разных мобильных платформах. Что из этого получится будет видно дальше.
Leave a Reply
Google запустил сайт по дизайну Android-приложений
Сегодня в Google Developers Blog появился анонс о новом разделе сайта для разработчиков, в котором будут освещаться вопросы, связанные с дизайном приложений для платформы Android.
На сайте можно найти документацию о проектировании интерфейса Android-приложений, работающих на устройствах с различными размерами и различными разрешениями экранов, описание типовых шаблонов проектирования интерфейса приложений (таких как Action Bar, Swipe Views и т.д.), узнать больше о стандартных компонентах Android и новой теме оформления в Ice Cream Sandwich.
Пишем свои компоненты для Mono for Android (Xamarin.Android) – Multi-Select Spinner
Для одного из текущих проектов понадобилось сделать контрол для множественного выбора элементов из списка.
Делать это отдельной Activity как-то не хотелось, но в Android нет готового компонента для этого. Максимум, что можно сделать, это использовать AlertDialog с множественным выбором. Обычный же Spinner позволяет выбрать только один элемент.
И вот, после гугления было найдено неплохое решение на StackOverflow, которое позволяет совместить внешний вид Spinner’а и функционал AlertDialog’а. Решение для Java можно посмотреть здесь. Это решение мне не очень понравилось из-за того, что работает только со строками + необходимо использовать дополнительный метод для установки элементов списка для выбора, вместо того, чтобы нормально испольщовать Adapter для этого.
После небольших допиливаний получился контрол, который, все-таки, можно использовать с адаптером. Правда, при этом теряется возможность хранить ссылку на объект адаптера где-то снаружи контрола и делать ему NotifyDataSetChanged()
и NotifyDataSetInvalidated()
, но для спиннера это очень редко используемый функционал, так что можно назвать решение приемлемым.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Util; namespace SampleWidgets.Android.Views { public class MultiSpinner : Spinner, IDialogInterfaceOnMultiChoiceClickListener, IDialogInterfaceOnCancelListener { public class MultiSpinnerSelectionEventArgs : EventArgs { public MultiSpinnerSelectionEventArgs(bool[] selected) { Selected = selected; } public bool[] Selected { get; private set; } } public delegate void ItemsSelectedHandler(object sender, MultiSpinnerSelectionEventArgs args); public event ItemsSelectedHandler ItemsSelected; private ISpinnerAdapter RealAdapter; private bool[] selected; public MultiSpinner(IntPtr a, JniHandleOwnership b) : base(a, b) { } public MultiSpinner(Context context) : base(context) { } public MultiSpinner(Context context, IAttributeSet attrs) : base(context, attrs) { } public MultiSpinner(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle) { } public void OnClick(IDialogInterface dialog, int which, bool isChecked) { selected[which] = isChecked; } private ISpinnerAdapter CreateLabelAdapter() { List<string> names = new List<string>(); int count = RealAdapter != null ? RealAdapter.Count : 0; for (int i = 0; i < count; i++) { if (selected[i]) names.Add(RealAdapter.GetItem(i).ToString()); } string label = string.Join(", ", names); if (label.Length == 0) label = Context.GetString(Resource.String.LabelNone); return new ArrayAdapter<string>(Context, Android.Resource.Layout.sherlock_spinner_item, new string[] { label }); } public void OnCancel(IDialogInterface dialog) { base.Adapter = CreateLabelAdapter(); if (ItemsSelected != null) ItemsSelected(this, new MultiSpinnerSelectionEventArgs(selected)); } public override bool PerformClick() { AlertDialog.Builder builder = new AlertDialog.Builder(Context); List<string> names = new List<string>(); int count = RealAdapter != null ? RealAdapter.Count : 0; if (count > 0) { for (int i = 0; i < count; i++) { names.Add(RealAdapter.GetItem(i).ToString()); } builder.SetMultiChoiceItems(names.ToArray(), selected, this); builder.SetPositiveButton(global::Android.Resource.String.Ok, delegate(object o, DialogClickEventArgs e) { (o as AlertDialog).Cancel(); }); builder.SetOnCancelListener(this); builder.Show(); } return true; } public override ISpinnerAdapter Adapter { get { return RealAdapter; } set { selected = new bool[value.Count]; RealAdapter = value; base.Adapter = CreateLabelAdapter(); } } } }
В коде можно заметить странного вида конструктор public MultiSpinner(IntPtr a, JniHandleOwnership b)
. Без него Mono for Android не хочет компилировать этот компонент т.к. в нем переопределены виртуальные методы и свойства. Решение проблемы с компиляцией было найдено на том же StackOverflow в этом топике. Ответ, который помечен как решение проблемы, хоть и описывает суть проблемы, но не предлагает реального решения. Зато добавление конструктора реально помогает.
С почином!
Надеюсь, будеш писать полезно:)
Веб 2 ноль прям забубенил)
Клево