2012-06-13 22 views
30

我想要顯示一個活動選擇器,其中顯示了所有可以查看和/或的應用程序編輯一些數據。有沒有簡單的方法來做到這一點,還是我必須實現我自己的活動選擇器對話框?或者,也許我可以繼承Intent?謝謝。如何使用多個動作來製作目標

+0

結帳的代碼示例:https://gist.github.com/gelldur/9c199654c91b13478979 –

回答

55

我找到了部分解決方案通過使用EXTRA_INITIAL_INTENTS:

Intent viewIntent = new Intent(Intent.ACTION_VIEW); 
Intent editIntent = new Intent(Intent.ACTION_EDIT); 
viewIntent.setDataAndType(uri, type); 
editIntent.setDataAndType(uri, type); 
Intent chooserIntent = Intent.createChooser(editIntent, "Open in..."); 
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { viewIntent }); 
startActivity(chooserIntent); 

我說的部分,因爲如果一個應用程序同時支持ACTION_VIEW和ACTION_EDIT它會顯示在列表中了兩次,其中之一將打開該文件進行查看另一個用於編輯,你不一定知道哪個是哪個。 Tim認爲,我認爲完整的解決方案需要定製應用程序選擇器。

EDIT(完整的解決方案!):

我發現,不涉及編寫自定義的應用程序選擇器的解決方案。爲了將ACTION_EDIT應用程序與ACTION_VIEW應用程序區分開來,我找到了一種方法,通過使用Tim提供的代碼行將「(for editing)」字符串附加到其中一個(在我的例子中爲ACTION_EDIT)的標籤上。此外,爲了確保附加的字符串不似乎是應用程序名稱的一部分,我改變了顏色的它青色:

PackageManager pm = kyoPrint.getPackageManager(); 
Intent viewIntent = new Intent(Intent.ACTION_VIEW); 
Intent editIntent = new Intent(Intent.ACTION_EDIT); 
viewIntent.setDataAndType(uri, type); 
editIntent.setDataAndType(uri, type); 
Intent openInChooser = Intent.createChooser(viewIntent, "Open in..."); 

// Append " (for editing)" to applicable apps, otherwise they will show up twice identically 
Spannable forEditing = new SpannableString(" (for editing)"); 
forEditing.setSpan(new ForegroundColorSpan(Color.CYAN), 0, forEditing.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
List<ResolveInfo> resInfo = pm.queryIntentActivities(editIntent, 0); 
Intent[] extraIntents = new Intent[resInfo.size()]; 
for (int i = 0; i < resInfo.size(); i++) { 
    // Extract the label, append it, and repackage it in a LabeledIntent 
    ResolveInfo ri = resInfo.get(i); 
    String packageName = ri.activityInfo.packageName; 
    Intent intent = new Intent(); 
    intent.setComponent(new ComponentName(packageName, ri.activityInfo.name)); 
    intent.setAction(Intent.ACTION_EDIT); 
    intent.setDataAndType(uri, type); 
    CharSequence label = TextUtils.concat(ri.loadLabel(pm), forEditing); 
    extraIntents[i] = new LabeledIntent(intent, packageName, label, ri.icon); 
} 

openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents); 
startActivity(openInChooser); 

enter image description here

編輯2:BUG

如果第一個意圖沒有找到任何活動,則將顯示NO活動,包括第二個意圖發現的任何活動。我結束了寫我自己的選擇器。我只爲每種意圖類型的標題填充了一個ExpandableListView,並將它們各自的活動作爲子項(作爲單獨的LabeledIntents存儲)。

+0

很好的答案!我想做一個帶有來自幾種不同類型甚至是應用內活動的Intents的Chooser,這讓我可以將它們全部合併到一個Chooser中。 – nobre

+0

這是優秀的!我希望啓動儘可能多的瀏覽器,以使用我發現的所有不同意圖來查看本地HTML文件。這很好,謝謝。 – daveD

+0

@Ken是否可以避免選擇器中的重複項?我在談論從一個意圖和另一個意圖中存在的項目?我正在嘗試創建一個分享選擇器,並希望將該消息設置爲短消息,但我無法找到如何執行此操作。 –

4

取決於您的數據。但通常使用ACTION_VIEW和附加的一些數據,您可以使用IntentChoooser爲用戶填充選項列表。

Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setType("text/plain"); 
intent.putExtra(Intent.EXTRA_TEXT, "some data"); 
startActivity(Intent.createChooser(intent, "Open with")); 

請務必正確設置您的類型,以便應用程序知道您希望打開他們可能能夠處理的內容。

編輯:我認爲你將不得不使用的軟件包管理器查詢,讓您的兩個列表,然後將它們組合成一個,使自己的活動/對話框會彈出,並逐漸加入包含在數據的組合名單。

這是使查詢的例子:

List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(intent, 0); 

因此,如果你讓你的兩個意圖,並呼籲這兩次,通過在每個意圖,你應該能夠得到的名單相結合,讓你的全套可能性。然後創建一個活動或對話框來顯示它們。

+0

我想表明支持ACTION_VIEW所有的應用程序** **或ACTION_EDIT,不只是ACTION_VIEW – Ken

+0

啊,我明白了。然後我想,你必須自己做更多的工作。看我的編輯。 – FoamyGuy

相關問題