Это вторая часть рассказа о библиотеке ActionBar Sherlock, реализующей UI-паттерн ActionBar для Android-приложений, а также еще ряд дополнительных возможностей. В этой части речь пойдет о том, как можно реализовать навигацию в приложении с использованием ActionBar и какие для этого есть возможности в ActionBar Sherlock.

Кастомная навигация

В ActionBar Sherlock есть возможность разместить свой View внутри ActionBar и использовать его для навигации. Так, например, можно разместить RadioGroup и при нажатии на RadioButton внутри нее переходить на нужную страницу в UI.
Пример такого XML-файла для контрола навигации ниже:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:gravity="left|center_vertical"
    android:orientation="horizontal"
    >
    <RadioGroup
        android:id="@+id/radio_nav"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <RadioButton
            android:id="@+id/nav_page_a"
            android:text="Page A"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <RadioButton
            android:id="@+id/nav_page_b"
            android:text="Page B"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </RadioGroup>
</LinearLayout>

В коде Activity необходимо вызвать метод getSupportActionBar().setCustomView() и нужній контрол будет размещен в ActionBar.

public class ActionBarSherlockTestActivity extends SherlockActivity {
	
	static final int [] pages = {
		R.layout.page_a,
		R.layout.page_b
	};
	
	private void setPage(int page_index) {
		setContentView(pages[page_index]);
	}

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	setTheme(R.style.Theme_Sherlock);
        super.onCreate(savedInstanceState);
        View customNav = getLayoutInflater().inflate(R.layout.cusom_navigation, null);
        
        ((RadioGroup)customNav.findViewById(R.id.radio_nav)).setOnCheckedChangeListener(new OnCheckedChangeListener() {
            public void onCheckedChanged(RadioGroup group, int checkedId) {
            	int page_index = checkedId == R.id.nav_page_a ? 0 : 1;
            	setPage(page_index);
            }

        });
        
        getSupportActionBar().setCustomView(customNav);
        getSupportActionBar().setDisplayShowCustomEnabled(true);
        setPage(0);
    }
}

На вид получится так:

Вкладки (Tabs)

Возможность работы с вкладками сама по себе очень полезна для отображения ограниченного количества страниц в интерфейсе пользователя (напомню что “ограниченное количество страниц”, согласно UI Design Guidelines это максимум 4 страницы).
Для того, чтобы иметь возможность отображать вкладки в ActionBar нужно указать для ActionBar режим NAVIGATION_MODE_TABS. Делается это посредством метода getSupportActionBar().setNavigationMode(). Затем нужно создать нужное количество объектов Tab с помощью getSupportActionBar().newTab(), заполнить в них информацию о вкладке (например заголовок и listener) и добавить в ActionBar с помощью getSupportActionBar().addTab(tab):

public class TabNavigation extends SherlockActivity i
		mplements ActionBar.TabListener {
    
	private TextView mSelected;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        setContentView(R.layout.tab_navigation);
        mSelected = (TextView)findViewById(R.id.text);

        getSupportActionBar().setNavigationMode(
			ActionBar.NAVIGATION_MODE_TABS);
        for (int i = 1; i <= 3; i++) {
            ActionBar.Tab tab = getSupportActionBar().newTab();
            tab.setText("Tab " + i);
            tab.setTabListener(this);
            getSupportActionBar().addTab(tab);
        }
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction transaction) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction transaction) {
        mSelected.setText("Selected: " + tab.getText());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction transaction) {
    }
}

В listener’е можно получать уведомления о переходе на вкладку и выходе с вкладки.
По поводу же смены layout’а, то этот функционал надо реализовывать самостоятельно.
Очень полезной является возможность отображать вкладки второй строкой в ActionBar в портретном режиме и встраивать их в ActionBar в ландшафтном режиме для экономии места.

Навигация списком

Навигацию с помощью выпадающего списка есть смысл использовать для переходов между страницами, когда их больше 4х. Для того, чтобы с помощью ActionBar Sherlock реализовать выпадающий список в ActionBar нужно сделать следующее:

  • Указать Navigation Mode равным NAVIGATION_MODE_LIST
  • Установить адаптер с элементами навигации и listener для получения сообщений о навигации с помощью getSupportActionBar().setListNavigationCallbacks()

В коде это будет выглядеть как-то так:

public class ListNavigation extends SherlockActivity 
		implements ActionBar.OnNavigationListener {
    private TextView mSelected;
    private String[] mLocations;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setTheme(SampleList.THEME); //Used for theme switching in samples
        super.onCreate(savedInstanceState);

        setContentView(R.layout.list_navigation);
        mSelected = (TextView)findViewById(R.id.text);

        mLocations = getResources().getStringArray(R.array.locations);

        Context context = getSupportActionBar().getThemedContext();
        ArrayAdapter<CharSequence> list = ArrayAdapter.createFromResource(
        		context, R.array.locations, R.layout.sherlock_spinner_item);
        list.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);

        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
        getSupportActionBar().setListNavigationCallbacks(list, this);
    }

    @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
        mSelected.setText("Selected: " + mLocations[itemPosition]);
        return true;
    }
}

Визуально все это выглядит так:

Функционал по смене лайаута надо тоже реализовывать руками.

Кнопка возврата

Есть также возможность отображения кнопки возврата в предыдущую activity в левой части ActionBar. Для этого использается метод getSupportActionBar().setDisplayHomeAsUpEnabled(). В результате получаем такой внешний вид ActionBar:

Исходный код всех примеров можно скачать вместе с дистрибутивом библиотеки. Примеры, которые идут в поставке покрывают абсолютно все аспекты использования ActionBar Sherlock и, хотя не блещут элегантностью и богатством реализации дополнительных фич, не связанных с API самой библиотеки, позволяют понять что и как можно использовать в своем приложении.

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

Leave a Reply

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

Ж.

Жесть какая! .NET для iPhone!

И вот такое бывает… живут себе люди, и тут БДЫЩЬ! и такая вещь случается, после которой “Ваш мир уже никогда не будет таким как раньше” (с).

Компания Novell после полуторамесячного бета-тестирования выпустила финальную версию среды разработки MonoTouch 1.0.

Теперь приложения на .NET можно запускать и на iPod/iPhone.

К сожалению, для того чтобы разрабатывать с использованием MonoTouch, все еще необходимым требованием является наличие Mac машины и установленного iPhone SDK. В комплект MonoTouch включены утилиты и библиотеки, необходимые для интеграции с iPhone SDK  и XCode IDE, а также с MonoDevelop IDE.

.NET для iPhone – это чудесно. Но MonoTouch – штука платная, персональная лицензия стоит $399, Enterprise лицензия на 5 пользователей – $3999.

И.

Интегрируем оплату через PayPal в Android-приложение

С некоторых пор PayPal предлагает возможность добавления функционала, связанного с оплатой, непосредственно в Android-приложения. Пользователям, в этом случае, нет необходимости заходить на сайт PayPal, все происходит непосредственно в программе. Для этих целей доступен SDK. О том, как его использовать я расскажу в этот раз.

Настройка приложения

Для начала качаем SDK с официального сайта.

Затем создаем Android-приложение в Eclipse.

В архиве с PayPal SDK есть jar-файл PayPal_MPL.jar, который нам необходимо положить в подкаталог lib внутри каталога с исходным кодом нашего приложения (подкаталог lib создаем руками, никто за нас автоматически этого не сделает).

Затем идем в настройки проекта в раздел Java Build Path и на вкладке Libraries с помощью кнопки Add JARs… добавляем эту библиотеку в список используемых в нашем проекте.

В созданном приложении в манифесте необходимо добавить следующие строки:

<activity android:name="com.paypal.android.MEP.PayPalActivity"
                    android:theme="@android:style/Theme.Translucent.NoTitleBar"
                    android:configChanges="keyboardHidden|orientation"/>

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

После этого можно приступать к написанию кода.

Кодинг

SDK позволяет создавать брендированные кнопки для вызова окна оплаты. И вот при создании activity (в методе onCreate()) мы создадим такую кнопку и добавим в layout.

private static final String PAYPAL_APP_ID = "APP-80W284485P519543T";
PayPal mPayPal;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mPayPal = PayPal.initWithAppID(
				MainActivity.this.getBaseContext(),
				PAYPAL_APP_ID,
				PayPal.ENV_SANDBOX);
    CheckoutButton payButton = mPayPal.getPaymentButton(PayPal.BUTTON_278x43, this, PayPal.PAYMENT_TYPE_HARD_GOODS);
   payButton.setOnClickListener(mPayButtonListener);
   LinearLayout mainLayout = (LinearLayout)findViewById(R.id.main_layout);
   mainLayout.addView(payButton,
       		new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}

Как видно из кода, у нас используется строка с PayPal Application ID. В примере используется тестовый ID приложения. Его можно посмотреть на странице аккаунта разработчика после регистрации на X.com.

Также хотелось бы отметить, что PayPal позволяет тестировать приложения с использованием “песочницы” (sandbox), а уже после тестирования можно настроить все так, чтобы приложение работало с реальным сайтом. В тестовом приложении мы указываем тип подключения PayPal.ENV_SANDBOX, который указывает что мы используем “песочницу”.

После того, как мы выполнили указанные выше действия, у нас должно получиться что-то вроде этого:

Отлично, кнопку мы добавили, но это всего лишь кнопка, она ничего не делает. Для того, чтобы она что-то делала, необходимо к ней добавить обработчик нажатия:

OnClickListener mPayButtonListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			PayPalPayment newPayment = new PayPalPayment();

			newPayment.setAmount("5.00");
			newPayment.setCurrency("USD");
			newPayment.setRecipient("zombie_1285772993_biz@wxwidgets.info");
			newPayment.setItemDescription("My Super Item");
			newPayment.setMerchantName("John Doe");

			Intent paypalIntent = new Intent(MainActivity.this, PayPalActivity.class);
			paypalIntent.putExtra(PayPalActivity.EXTRA_PAYMENT_INFO, newPayment);
			MainActivity.this.startActivityForResult(paypalIntent, 1);
		}
	};

E-mail получателя платежа можно получить в песочнице, предварительно создав аккаунт продавца в разделе Test Accounts.

После нажатия на кнопку на экране появляется activity, в которой можно произвести оплату:

E-mail отправителя платежа можно также получитьв “песочнице” после создания тестового аккаунта.

После завершения оплаты нам необходимо как-то узнать результат (оплата может быть отменена пользователем, может произойти ошибка отправки средств и т.д.). Для этого нам необходимо реализовать метод onActivityResult():

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    	String label = "";
    	String transactionID = data.getStringExtra(PayPalActivity.EXTRA_TRANSACTION_ID);
    	switch(resultCode) {
    		case Activity.RESULT_OK:
    			label = "OK";
    			break;
    		case Activity.RESULT_CANCELED:
    			label = "Cancelled";
    			break;
    		case PayPalActivity.RESULT_FAILURE:
    			label = "Failure";
    			break;
      	}
    	TextView resultLabelView = (TextView)findViewById(R.id.result_label);
    	resultLabelView.setText(label + ": " + transactionID);
}

Вместе с SDK поставляется неплохая документация, так что все вопросы решаются довольно быстро. В принципе, работа с PayPal MPL оставила только положительные ощущения, все просто и понятно, не глючит. Примеры, которые идут в поставке тоже работают нормально. Видно что SDK – цельный продукт.

Ну вот, собственно и все.

Напоследдок несколько ссылок:

Исходные коды тестового приложения.