Для одного из текущих проектов понадобилось сделать контрол для множественного выбора элементов из списка.
Делать это отдельной 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 в этом топике. Ответ, который помечен как решение проблемы, хоть и описывает суть проблемы, но не предлагает реального решения. Зато добавление конструктора реально помогает.

Выглядит все это как-то так:
multi-spinner-screenshot

Previous Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

О.

О сверхдешевых ноутбуках и о том как не надо делать бизнес – Часть I

Вот я вам сейчас расскажу такую историю, вернее начну рассказывать, т.к. она не закончилась еще…

Еще два месяца назад, в августе, попалась на глаза новость о том что вот, браться-китайцы выпустили в свет самый дешевый-предешевый в мире ноутбук, стоимостью $99 и что счастлив тот компьютерный гик, у которого этот ноутбук есть. Я заинтересовался, штука интересная, на Windows CE, пошел искать где же это добро можно приобрести, нашел в единственном месте, на Alibaba.com. Найти-то я нашел, но… в общем, ресурс это для оптовых покупателей и оптовых продавцов и по поводу покупки чего бы там ни было в розницу договориться почти невозможно. По крайней мере компания, которая эти вот самый субноутбуки производит, со мной общаться не захотела (то ли они английского не знают, то ли им было лень мне отказ написать, но они даже не ответили мне на письмо, но ладно, это уже не важно). Ну не захотели они и ладно, порыскал в сети еще, нашел модель чуть подороже, Impulse NPX-9000 за $129. На вид неплохо, X-Scale’овский процессор, на борту Linux кастомной сборки. Да, собственно, вот они, характеристики-то:

  • 400 MHz Intel / Marvell X-Scale CPU
  • Super Slim and Light – 21.3 cm x 14.2 cm x 3.3 cm and only 725 g
  • 7″ TFT LCD ( analog )
  • 128 MB SDRAM
  • MSystems MDOC 1GB NAND Fast Flash
  • 80 Key Keyboard with Touch Pad
  • Optional 10/100 Mbps LAN Dongle and WiFi
  • Interfaces: 1 x VGA, 3 x USB 2.0, 1 x Mic
  • 1 x Headphone Jack, 1 x Line-in
  • SD / MMC Memory Card Reader / Writer Slot
  • Battery: 2100 mA/h Li-Polymer Battery
  • Power: AC 110~24- V, 3.0 A, 10.0 V DC

Ну ладно, это хоть и не $99, а на целых 30% дороже от того что я планировал изначально, но и на вид лучше, вон Wi-Fi модуль есть внешний и сеть (тоже внешняя, но это, в принципе, не страшно).

Написал компании-производителю, ответили, оказалось что у них можно заказать мм.. ну, скажем, мелким оптом (минимальный размер партии на портале Alibaba 100 единиц, я договорился на 5… это что-то  типа “технологического образца” получилось).

Тут мне пришлось огорчиться еще раз, если покупать мелким оптом, то стоимость каждого устройства возрастает до $150 да еще и $12 стоит USB Wi-Fi модуль и LAN модуль, за них прийдется платить отдельно. Подумав немного решил остановиться на Wi-Fi, т.к. мобильность, хотелось бы не привязываться к шнуркам чтобы в сети посидеть. Итого получается $162 за каждое устройство, а это на 60% больше чем я ожидал вначале… как-то это.. странно что ли, где же обещанная “доступность ну просто для всех”?

Подумав денек, решил что покупать я их все же буду, 5 устройств: одно себе, куда определить остальные 4, думаю, найду.

О том как проходила покупка расскажу в следующем посте, прям эпопея какая-то.

У.

Установка Android SDK 1.0 на HTC Touch/Vogue

Давно уже пора счастливым обладателям ряда телефонов от HTC (в частности на процессорах MSM7500, к примеру Touch) начать наслаждаться прелестями Андроида не в эмуляторах, а буквально в своих руках — на экранах своих же телефонов. Как? Совершенно не сложно!

Основную работу по портировании андроида на плафторму в данный момент ведет вот этот товарищ. На его же странице можно скачать архив с последней сборкой Андроида (а инструкции по установке читайте чуть ниже).
Еще один вариант — скачать установочный .cab файл вот с этой страницы. Тут все просто — запустили файл и готово. Далее андроид запускается из Start->Programs->harret. Минусы этого варианта — каб файл собирается из того, что выкладывают по предыдущей ссылки — что частенько является свежее и стабильнее.

Оба метода установки абсолютно безопасны для вашей Windows Mobile 6.1 и текущих данных на телефоне, так что можете спокойно проводить эксперименты. Основное требование — 256 мб свободного места на карточке после копирования файлов.

Установка вручную:

  • Скачать http://it029000.massey.ac.nz/vogue/android-new.zip раззипить.
  • Разархировать вручную все три .gz файла (initrd.gz, system.gz и data.gz). Удалите оставшиеся *.gz файлы.
  • В итоге мы получим initrd, system.img, data.img
  • В файле default.txt поменять «initrd.gz» на «initrd»
  • Как-нибудь скопируйте все получившиеся файлы с компьютера в корневую директорию SD карточки (к примеру через Bluetooth)
  • Запускайте андроид — SDCard/harret.exe, и жмите Run.

Телефоны работающие с этой сборкой:
Несколько моделей от HTC, работающие на процессоре MSM7500:
HTC Libra 100: HTC S720, HTC 5800, Verizon SMT5800 / XV5800,
HTC Titan 100: Verizon XV6800, HTC/PPC 6800, HTC P4000
HTC Vogue 100: HTC Touch P3050
HTC Vogue: Verizon Touch XV6900
HTC Iris 100: HTC S640
HTC Touch Diamond

(информация с www.pdadb.net)
Нет гарантии что на этих телефонах эта сборка андроида заведется — она заточена именно под Vogue, но попробывать определенно стоит.
Для менее удачливых обладателей HTC Elf (он же европейский Touch с процессором OMAP850) обладающих базовыми знаниями ARM Linux — проходите, читайте, пробуйте 🙂

Что в итоге можно получить:
Вполне себе работающую систему, очень похожую на то что показывали нам в видео о G1.

Maps — полноценный гугл мапс. Довольно отполированный — я не нашел никаких недочетов. Разве что у моего не было street view. В остальном — отменно работает. Пользоваться, лично мне, приятнее чем на браузером айфона — нет необходимости двумя пальцами менять зум 🙂 А еще режим My Location показывает точечку какую-то в Поло Альто, она на тот момент ехала по дороге. Интересно — чья-то жизнь!

Браузер — очень приятно пользоваться. Шустрый, с классным и функциональным зумом, интересными находками в интерфейсе. Действительно приятные эффекты. Поддержка большого количества окошек–табов (имплементация примерно как в мобайл-сафари).
В принципе нареканий нет. Странички типа главной Лепры (большая и тяжеленная страница с кучей больших картинок) не тормозят, плавно скролятся по движению пальцем, зумятся, и так далее. Интернетом пользоваться приятно и интересно!

Оно посылает смски, они доходят — ура!

В моей сборке что–то не так с извещениями. К примеру, приходит смска — включается вибрация и больше ее не выключишь кроме как перезагрузкой. То же самое с входящими звонками. Всё исходящее — работает нормально. Звуки тоже, так что проблема именно в вибрации не вызванной напрямую пользователем.

Так же у меня там были установлены следующие приложения: камера (как в эмуляторе, так же не работает), калькулятор, ssh клиент (ура!), девелоперская информация и настройки, глобус с тенью ползущей, будильник (очень классный, с разными «скинами»), аудио плеер, смотрелка картинок.

Так как почему–то не работает sd карточка (странно!) — музыку и смотрелку картинок тестировать нечем.

Из глюков — тач–клавиутура выглядит не очень (но пользоваться вполне можно) и вибрирует при нажатии на кнопочки, что довольно странно и уверен будет очень скоро исправлено. Шрифты не всегда помещаются на кнопочки. Ну а кроме того что описал выше — особых багов в системе пока не заметил.

Еще тут говорят что на эту сборку можно ставить приложения без особых проблем — а их в сети уже буквально сотни и сотни.

Взято с хабра