2010年11月7日日曜日

Android Quick Action の Android ライブラリプロジェクトを作ってみた

Google I/O の UI design pattern で紹介されていた、Quick Action (twitter アプリや Gmail アプリで使われている) は標準の SDK の中にはありません。

# Quick Action については以前のエントリ「Android UI Design Tips」でも簡単にかきました。

leibun さんのブログのエントリがわかりやすいです。
QuickActionの使い方 - leibunのテクニカルブログ -

leibun さんのブログでも紹介されてますが、
 ・http://code.google.com/p/simple-quickactions/
 ・http://www.londatiga.net/it/how-to-create-quickaction-dialog-in-android/

とかでソースが公開されています。

http://www.londatiga.net/it/how-to-create-quickaction-dialog-in-android/ のコードを落としてきてアプリにソースや画像をコピーしてもいいのですが、コピーするの面倒だし、2つのスタイルが別々になっているし、一つのアプリで複数のスタイルの QuickAction を使えないし、Trackアニメーションを設定できないので fork してみました。

 サンプル apk はこちら

 ・スタイルを twitter 公式アプリの QuickAction っぽいの
  or シンプルなポップアップ から選択可能
 ・外枠用の layout リソースIDを指定可能
 ・中の item 用の layout リソースIDを指定可能
 ・Track アニメーションの interpolator の指定が可能












https://github.com/yanzm/QuickActionLib からダウンロードして、Eclipse に Import します。QuickActionLib の Properties で [Android] - [Library] の Is Library をチェックし、Android ライブラリプロジェクトにします。




使う方では、プロジェクトの Properties で [Android] - [Library] - [Add] から QuickActionLib を追加






こんな感じで使う


package yanzm.example.quickactiontest2;

import yanzm.products.quickaction.lib.ActionItem;
import yanzm.products.quickaction.lib.QuickAction;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class QuickActionTest2 extends Activity {

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


// 1st item
final ActionItem chart = new ActionItem();

chart.setTitle("Chart");
chart.setIcon(getResources().getDrawable(R.drawable.chart));
chart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(QuickActionTest2.this, "Chart selected" , Toast.LENGTH_SHORT).show();
}
});


// 2nd item
final ActionItem production = new ActionItem();

production.setTitle("Products");
production.setIcon(getResources().getDrawable(R.drawable.production));
production.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(QuickActionTest2.this, "Products selected", Toast.LENGTH_SHORT).show();
}
});


// 3rd item
final ActionItem budget = new ActionItem();

budget.setTitle("Budget");
budget.setIcon(getResources().getDrawable(R.drawable.budget));
budget.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(QuickActionTest2.this, "Budget selected", Toast.LENGTH_SHORT).show();
}
});

// 4th item
final ActionItem dashboard = new ActionItem();

dashboard.setIcon(getResources().getDrawable(R.drawable.dashboard));
dashboard.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(QuickActionTest2.this, "dashboard selected" , Toast.LENGTH_SHORT).show();
}
});


// 5th item
final ActionItem users = new ActionItem();

users.setIcon(getResources().getDrawable(R.drawable.users));
users.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(QuickActionTest2.this, "Products selected", Toast.LENGTH_SHORT).show();
}
});


// Default Setting
Button btn1 = (Button) this.findViewById(R.id.btn1);
btn1.setText("Default Setting");
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(chart);
qa.addActionItem(production);

qa.show();
}
});

// ANIM_AUTO
Button btn2 = (Button) this.findViewById(R.id.btn2);
btn2.setText("QuickAction.ANIM_AUTO\nmany Items");
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(chart);
qa.addActionItem(production);
qa.addActionItem(chart);
qa.addActionItem(production);
qa.addActionItem(chart);
qa.addActionItem(production);
qa.addActionItem(chart);
qa.addActionItem(production);
qa.setAnimStyle(QuickAction.ANIM_AUTO);

qa.show();
}
});


// ANIM_GROW_FROM_CENTER
Button btn3 = (Button) this.findViewById(R.id.btn3);
btn3.setText("QuickAction.ANIM_GROW_FROM_CENTER\nItems have no title\nNo Interpolator");
btn3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(dashboard);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_CENTER);
qa.setAnimTrack(R.anim.rail2, null);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn4 = (Button) this.findViewById(R.id.btn4);
btn4.setText("QuickAction.ANIM_GROW_FROM_LEFT\nItems have no title\nNo Track Animation");
btn4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(dashboard);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_LEFT);
qa.setAnimTrackEnabled(false);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn5 = (Button) this.findViewById(R.id.btn5);
btn5.setText("QuickAction.ANIM_GROW_FROM_RIGHT");
btn5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(chart);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_RIGHT);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn6 = (Button) this.findViewById(R.id.btn6);
btn6.setText("QuickAction.ANIM_REFLECT");
btn6.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(dashboard);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_REFLECT);
qa.setLayoutStyle(QuickAction.STYLE_BUTTON);

qa.show();
}
});



//////////////////////////////////////////////////////

// Default Setting + STYLE_LIST
Button btn7 = (Button) this.findViewById(R.id.btn7);
btn7.setText("QuickAction.STYLE_LIST");
btn7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(chart);
qa.addActionItem(production);
qa.setLayoutStyle(QuickAction.STYLE_LIST);

qa.show();
}
});

// ANIM_AUTO
Button btn8 = (Button) this.findViewById(R.id.btn8);
btn8.setText("QuickAction.ANIM_AUTO\nQuickAction.STYLE_LIST with Constractor");
btn8.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v, R.layout.popup2, QuickAction.STYLE_LIST);

qa.addActionItem(chart);
qa.addActionItem(production);
qa.setAnimStyle(QuickAction.ANIM_AUTO);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn9 = (Button) this.findViewById(R.id.btn9);
btn9.setText("QuickAction.ANIM_GROW_FROM_CENTER\nQuickAction.STYLE_LIST\nsetItemLayoutId()");
btn9.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(dashboard);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_CENTER);
qa.setLayoutStyle(QuickAction.STYLE_LIST);
qa.setItemLayoutId(R.layout.action_item);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn10 = (Button) this.findViewById(R.id.btn10);
btn10.setText("QuickAction.ANIM_GROW_FROM_LEFT");
btn10.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(budget);
qa.addActionItem(production);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_LEFT);
qa.setLayoutStyle(QuickAction.STYLE_LIST);
qa.setItemLayoutId(R.layout.action_item2);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn11 = (Button) this.findViewById(R.id.btn11);
btn11.setText("QuickAction.ANIM_GROW_FROM_RIGHT\ncustom layout");
btn11.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v, R.layout.popup2, QuickAction.STYLE_LIST);

qa.addActionItem(budget);
qa.addActionItem(production);
qa.setAnimStyle(QuickAction.ANIM_GROW_FROM_RIGHT);
qa.setItemLayoutId(R.layout.action_item3);

qa.show();
}
});

// ANIM_GROW_FROM_CENTER
Button btn12 = (Button) this.findViewById(R.id.btn12);
btn12.setText("QuickAction.ANIM_REFLECT");
btn12.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
QuickAction qa = new QuickAction(v);

qa.addActionItem(dashboard);
qa.addActionItem(users);
qa.setAnimStyle(QuickAction.ANIM_REFLECT);
qa.setLayoutStyle(QuickAction.STYLE_LIST);

qa.show();
}
});
}
}

 

 

5 件のコメント:

  1. Thank you very much for the lib. It is very useful.

    I just added a small functionality to the file QuickAction.java. Now one can set the popup to be ABOVE, BELOW or as OVERLAY:
    quickAction.setPosition(QuickAction.POSITION_BELOW);

    If you want I am willing to share it with you so you can add it to the library so that other people can use it.

    you can contact me over: pboos at tonchidot.com (replace at with @)

    Regards,
    Patrick Boos

    返信削除
  2. 端末を横向きにした状態でQuick Actionを呼び出すと、QuickActionクラスのshowListStyleメソッドの329行目や338行目でインスタンスフィールドscrollerを参照してNullPointerExceptionが発生します。

    修正していただけないでしょうか?

    よろしくお願いいたします。

    返信削除
  3. 書き忘れましたが、NullPointerExceptionが発生するのは、レイアウトスタイルがリストスタイルの場合です。

    よろしくお願いいたします。

    返信削除
  4. Você é do caralho maninho!!!!!!!!!!!

    muito bom mesmo, sou seu fã!!!!

    Você é zica do pantano!!!!

    http://www.astraclub.com.br/forum/style_emoticons/default/smile_venerando.gif

    返信削除
  5. QuickAction便利に使わせていただいております。
    kinmojrさんのコメントと同様の原因だと思いますが、リストスタイルの場合、QuickActionのポップアップが画面をはみ出るとNullPointerExceptionが発生します。

    QuickAction.java 193行目を以下のように修正して使用しています。
    【オリジナル】scroller = null;

    【修正】scroller = (ScrollView) rootView.findViewById(R.id.scroller);

    また、ダイアログ上のViewに対してで使用すると吹き出しの位置がずれるので、修正してみようと思います。

    返信削除