|
QuickActionWindow
How to use the QuickActionWindow library developed for Horaires TER SNCF
Featured, Phase-Implementation, Phase-Deploy Installation
That's all ! you can use Quick Action windows in your project :) UsageSample projectLook at the sample project for a full-featured example.
1. General configurationDefine a SparseIntArray that will hold the configuration of your Quick Action Window. You will use keys defined in QuickActionWindow.Config to store configuration options : SparseIntArray configuration = new SparseIntArray(); // Mandatory options configuration.put(QuickActionWindow.Config.WINDOW_LAYOUT, R.layout.quick_action_window); configuration.put(QuickActionWindow.Config.ITEM_LAYOUT, R.layout.quick_action_item); // Other options : see documentation of QuickActionWindow.Config... // ... QuickActionWindow window = QuickActionWindow.getWindow(context, configuration); Available options
Prepare your layoutAs you will see in the QuickActionWindowSample project, and corresponding to the available options listed above, there are a few elements to prepare :
2. Adding itemsThere are two ways of adding items :
Manually, with callback// Declare full item
QuickActionWindow.Item item = new QuickActionWindow.Item(context, R.string.item_label, R.drawable.item_icon, new QuickActionWindow.Item.Callback() {
public void onClick(Item item, View anchor) {
// Describe here what happens when user clicks on this item,
// when window is shown attached to specified anchor.
}
});
// When window is shown, if user clicks on this item, callback will be executed
window.addItem(item);Manually, as an activity itemIntent intent= new Intent(/* intent description */); QuickActionWindow.IntentItem item = new QuickActionWindow.IntentItem(context, R.string.item_label, R.drawable.item_icon, intent); // When window is shown, if user clicks on this item, an activity responding to this intent will be started window.addItem(item); Note that startActivity() can fail and throw ActivityNotFoundException if no activity is found responding to this intent. You can catch this case by adding an ErrorCallback : // ...
QuickActionWindow.IntentItem item = new QuickActionWindow.IntentItem(context, R.string.item_label, R.drawable.item_icon, intent, new QuickActionWindow.IntentItem.ErrorCallback() {
public void onError(ActivityNotFoundException e, IntentItem item) {
// Show error message
}
});
// ...Dynamically, by intentIntent intent = new Intent(/* intent description */); // For each activity responding to given itent, we'll add an item with activity's icon // and label. As a callback, clicking on item will launch found activity. window.addItemsForIntent(context, intent, errorCallback); Obviously, this system could be very useful for implementing plugins in your applications : declare a specific actions, and allow any activity filtering this action to be shown in the quick action window. This way, you can add your own plugins, and allow third-party plugins very easily ! This is nice, but for advertisement purpose you would like to put "fake" items that will launch to - for example - Android Market when the expected activity has not been found. And if it's found, we just remove the advertisement as the item will be here. You can do it using an additionnal array of ItemAdvertisement instances ! QuickActionWindow.Advertisement[] ads = new QuickActionWindow.Advertisement[] {
new QuickActionWindow.MarketAdvertisement("my.package", ".Activity",
getString(R.string.advertisement), getResources().getDrawable(R.drawable.advertisement),
"Android Market not found"
),
};
// If activity "my.pkg.Activity" is not found in the IntentItems added to the window,
// we'll add an item that will open Android Market to the detail page of "my.pkg"
// when user clicks on item.
window.addItemsForIntent(context, intent, errorCallback, advertisements);Caching itemsIntentItems are a nice feature, and the addItemsForIntent is even nicer. Anyway, querying system for activities could slow your application if it's done each time the window is called. To allow items to be initialized only once, you could :
All this is done for you if you use an Initializer when creating window : int windowID = WINDOW_UNIQUE_ID;
QuickActionWindow window = QuickActionWindow.getWindow(context, configuration, new QuickActionWindow.Initializer() {
public void setItems(QuickActionWindow window) {
// Define window's items here
}
}, windowID);When you specify intent items this way, you could have problems using context-dependant variables, like the clicked view's position or some other elements. There is no solution if those variables are part of the intent's description (like its Uri). In this case, you cannot use the initializer feature. Anyway it wouldn't help you at all as obviously you HAVE to re-query system for activities responding to the intent. In any other situation, the contextual data will be passed as extra, and you will be able to delay these affectations using dispatchIntentExtras, here is a full example in a ListActivity : final Context context = this;
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
// When user clicks on an item of the list
public void onItemClick(AdapterView<?> adapter, final View anchor, final int position, final long id) {
// Define intent applied to this item
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("mime/type");
// Initialize window, items will be generated only once, and later clicks on other
// list items will not execute this portion of the code.
QuickActionWindow window = QuickActionWindow.getWindow(context, configuration, new QuickActionWindow.Initializer() {
public void setItems(QuickActionWindow window) {
window.addItemsForIntent(context, intent, null);
}
}, windowID);
// Add ID of the clicked item as extra
Bundle extras = new Bundle();
extras.put("_id", id);
window.dispatchIntentExtras(extras, intent);
// Show window attached to the clicked item
window.show(anchor);
}
});Here is the same code with no items-caching : final Context context = this;
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
// When user clicks on an item of the list
public void onItemClick(AdapterView<?> adapter, final View anchor, final int position, final long id) {
// Initialize window
QuickActionWindow window = QuickActionWindow.getWindow(context, configuration)
// Intent for the clicked item
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("mime/type");
intent.putExtra("_id", id);
// Add window's items
window.addItemsForIntent(context, intent, null);
// Show window attached to the clicked item
window.show(anchor);
}
});Use one way or another, it depends on your tastes, your will for optimising little things (this is always arguable as it here has a clear impact on readability). Note that the best optimization we could do would be not to inflate layout each time, but there are a lot of issues when re-using such views when you have to show/dismiss your window twice or more. I'm working on it ;) 3. Showing windowJust call show(View anchor) and the window will appear attached to specified view. Below or above, depending on remaining space up or under the view. |
Note that the default behavior is to automatically dismiss window when an action item is clicked. You can disable this behavior using setDismissOnClick() :