ActionBar의 오버플로 메뉴에 아이콘을 표시하는 방법
네이티브 API를 사용하는 것이 불가능하다는 것을 알고 있습니다. 그런 종류의보기를 구현하는 해결 방법이 있습니까?
이전에 게시 된 답변은 일반적으로 OK입니다. 그러나 기본적으로 Overflow 메뉴의 기본 동작을 제거합니다. 여러 화면 크기에 몇 개의 아이콘을 표시 할 수 있으며 표시 할 수없는 경우 오버플로 메뉴로 떨어집니다. 위의 작업을 수행하면 많은 중요한 기능이 제거됩니다.
더 나은 방법은 아이콘을 직접 표시하도록 오버플로 메뉴에 지시하는 것입니다. 활동에 다음 코드를 추가하여이를 수행 할 수 있습니다.
@Override
public boolean onMenuOpened(int featureId, Menu menu)
{
if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return super.onMenuOpened(featureId, menu);
}
메뉴 xml에서 다음 구문을 사용하여 메뉴를 중첩하면 아이콘이있는 메뉴가 표시됩니다.
<item
android:id="@+id/empty"
android:icon="@drawable/ic_action_overflow"
android:orderInCategory="101"
android:showAsAction="always">
<menu>
<item
android:id="@+id/action_show_ir_list"
android:icon="@drawable/ic_menu_friendslist"
android:showAsAction="always|withText"
android:title="List"/>
</menu>
</item>
이전 답변을 기반으로 이것을 시도했으며 적어도 최신 버전의 지원 라이브러리 (25.1)에서는 정상적으로 작동합니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if(menu instanceof MenuBuilder){
MenuBuilder m = (MenuBuilder) menu;
//noinspection RestrictedApi
m.setOptionalIconsVisible(true);
}
return true;
}
SpannableString을 사용할 수 있습니다.
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_tab, menu);
MenuItem item = menu.findItem(R.id.action_login);
SpannableStringBuilder builder = new SpannableStringBuilder("* Login");
// replace "*" with icon
builder.setSpan(new ImageSpan(this, R.drawable.login_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
item.setTitle(builder);
}
Simon의 대답은 나에게 매우 유용 onCreateOptionsMenu
했기 때문에 제안 된대로 -method로 구현 한 방법을 공유하고 싶습니다 .
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_action_bar, menu);
// To show icons in the actionbar's overflow menu:
// http://stackoverflow.com/questions/18374183/how-to-show-icons-in-overflow-menu-in-actionbar
//if(featureId == Window.FEATURE_ACTION_BAR && menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
//}
return super.onCreateOptionsMenu(menu);
}
위 의 @Desmond Lua의 답변을 기반으로 드롭 다운에서 XML로 선언 된 드로어 블을 사용하고 색조가 지정된 색상이 Constant Drawable 상태에 영향을 미치지 않도록하는 정적 메서드를 만들었습니다.
/**
* Updates a menu item in the dropdown to show it's icon that was declared in XML.
*
* @param item
* the item to update
* @param color
* the color to tint with
*/
private static void updateMenuWithIcon(@NonNull final MenuItem item, final int color) {
SpannableStringBuilder builder = new SpannableStringBuilder()
.append("*") // the * will be replaced with the icon via ImageSpan
.append(" ") // This extra space acts as padding. Adjust as you wish
.append(item.getTitle());
// Retrieve the icon that was declared in XML and assigned during inflation
if (item.getIcon() != null && item.getIcon().getConstantState() != null) {
Drawable drawable = item.getIcon().getConstantState().newDrawable();
// Mutate this drawable so the tint only applies here
drawable.mutate().setTint(color);
// Needs bounds, or else it won't show up (doesn't know how big to be)
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(drawable);
builder.setSpan(imageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
item.setTitle(builder);
}
}
그리고 그것을 사용하면 활동에 사용될 때 다음과 같이 보일 것입니다. 이것은 개인의 필요에 따라 훨씬 더 우아 할 수 있습니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_activity_provider_connect, menu);
int color = ContextCompat.getColor(this, R.color.accent_dark_grey);
updateMenuWithIcon(menu.findItem(R.id.email), color);
updateMenuWithIcon(menu.findItem(R.id.sms), color);
updateMenuWithIcon(menu.findItem(R.id.call), color);
return true;
}
현재 최고이지만 허용되지 않는 솔루션은 아마도 이전 플랫폼에서 작동합니다. 어쨌든 새로운 AppCompat21 +에서는 필요한 메서드가 존재하지 않고 메서드 getDeclaredMethod
가 exception을 반환합니다 NoSuchMethodException
.
따라서 나를위한 해결 방법 (4.x, 5.x 장치에서 테스트 및 작업)은 직접 변경 배경 매개 변수를 기반으로합니다. 따라서이 코드를 Activity 클래스에 넣으십시오.
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
// enable visible icons in action bar
if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Field field = menu.getClass().
getDeclaredField("mOptionalIconsVisible");
field.setAccessible(true);
field.setBoolean(menu, true);
} catch (IllegalAccessException | NoSuchFieldException e) {
Logger.w(TAG, "onMenuOpened(" + featureId + ", " + menu + ")", e);
}
}
}
return super.onMenuOpened(featureId, menu);
}
@Simon의 대답은 실제로 잘 작동하지만 AppCompat Activity를 사용하고 있습니다 ... 대신이 코드를 사용해야합니다 ... onMenuOpened ()가 appcompat-v7 : 22.x에서 더 이상 호출되지 않기 때문입니다.
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if(menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(Constants.DEBUG_LOG, "onMenuOpened", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
ActionMode와 함께 사용하는 Simon의 탁월한 솔루션에 대한 간단한 모드 :
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
if(menu != null){
if(menu.getClass().getSimpleName().equals("MenuBuilder")){
try{
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
}
catch(NoSuchMethodException e){
Log.e(TAG, "onPrepareActionMode", e);
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
return true;
}
나에 따르면 이것은 사용자 정의 도구 모음을 만들어야 만 가능합니다. 기본 ActionBar는 해당 기능을 제공하지 않기 때문입니다. 그러나 하위 메뉴를 항목의 하위 메뉴로 가져 와서 아이콘을 넣을 수 있습니다. 그리고 나보다 더 나은 해결책이 있다면 .. 그냥 알려주세요.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_menu_camera"
android:showAsAction="never"
android:title="@string/action_settings" />
<item
android:id="@+id/action_1"
android:icon="@drawable/ic_menu_gallery"
android:showAsAction="never"
android:title="Hello" />
<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_search_category_default"
android:showAsAction="never"
android:title="action_search">
<menu>
<item
android:id="@+id/version1"
android:icon="@android:drawable/ic_dialog_alert"
android:showAsAction="never"
android:title="Cup cake" />
<item
android:id="@+id/version2"
android:icon="@drawable/ic_menu_camera"
android:showAsAction="never"
android:title="Donut" />
<item
android:id="@+id/version3"
android:icon="@drawable/ic_menu_send"
android:showAsAction="never"
android:title="Eclair" />
<item
android:id="@+id/version4"
android:icon="@drawable/ic_menu_gallery"
android:showAsAction="never"
android:title="Froyo" />
</menu>
</item>
</menu>
내가 찾은 가장 쉬운 방법은 다음과 같습니다.
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.toolbar_menu,menu);
if(menu instanceof MenuBuilder) { //To display icon on overflow menu
MenuBuilder m = (MenuBuilder) menu;
m.setOptionalIconsVisible(true);
}
return true;
} `
이것은 너무 늦었지만 누군가가 내 시도에 도움이 될 수 있습니다 @Desmond Lua의 도움을 받아 누가 사용하는지 도움이됩니다. menu.xml
My answer is for dynamic menu creation here is my code:
int ACTION_MENU_ID =1;
SpannableStringBuilder builder;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//this space for icon
builder = new SpannableStringBuilder(" " + getString(R.string.your_menu_title));
builder.setSpan(new ImageSpan(this, R.drawable.ic_your_menu_icon), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//dynamic menu added
menu.add(Menu.NONE,ACTION_MENU_ID, Menu.NONE,
getString(R.string.your_menu_title))
.setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
//set icon in overflow menu
menu.findItem(ACTION_MENU_ID).setTitle(builder);
}
Add this in style:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_settings"
app:showAsAction="always"
android:icon="@drawable/ic_more_vert_white"
android:orderInCategory="100"
android:title="">
<menu>
<item
android:id="@+id/Login"
android:icon="@drawable/ic_menu_user_icon"
android:showAsAction="collapseActionView|withText"
android:title="@string/str_Login" />
<item
android:id="@+id/str_WishList"
android:icon="@drawable/ic_menu_wish_list_icon"
android:showAsAction="collapseActionView"
android:title="@string/str_WishList" />
<item
android:id="@+id/TrackOrder"
android:icon="@drawable/ic_menu_my_order_icon"
android:showAsAction="collapseActionView"
android:title="@string/str_TrackOrder" />
<item
android:id="@+id/Ratetheapp"
android:icon="@drawable/ic_menu_rate_the_apps"
android:showAsAction="collapseActionView"
android:title="@string/str_Ratetheapp" />
<item
android:id="@+id/Sharetheapp"
android:icon="@drawable/ic_menu_shar_the_apps"
android:showAsAction="collapseActionView"
android:title="@string/str_Sharetheapp" />
<item
android:id="@+id/Contactus"
android:icon="@drawable/ic_menu_contact"
android:showAsAction="collapseActionView"
android:title="@string/str_Contactus" />
<item
android:id="@+id/Policies"
android:icon="@drawable/ic_menu_policy_icon"
android:showAsAction="collapseActionView"
android:title="@string/str_Policies" />
</menu>
</item>
</menu>
public void showContextMenuIconVisible(Menu menu){
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Field field = menu.getClass().getDeclaredField("mOptionalIconsVisible");
field.setAccessible(true);
field.setBoolean(menu, true);
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
}
I used MashukKhan's suggestion but I showed the holder item as action always and used the vertical more dots from the vector assets as the icon.
<item
android:orderInCategory="10"
android:title=""
android:icon="@drawable/ic_more_vert"
app:showAsAction="always" >
<menu>
<item
android:id="@+id/action_tst1"
...and so on
</menu>
</item>
This produces the "overflow" menu effect and displays the icons in the drop down.
One can even put items ahead of it if they don't conflict with it showing.
I find MashukKhan's solution elegant and it fits in the solution rather than the work around category because it is just an implementation of a sub menu.
참고URL : https://stackoverflow.com/questions/18374183/how-to-show-icons-in-overflow-menu-in-actionbar
'Development Tip' 카테고리의 다른 글
NSURLConnection 시간 초과? (0) | 2020.11.26 |
---|---|
GIT 복원 마지막 분리 HEAD (0) | 2020.11.25 |
암호 강도 측정기 (0) | 2020.11.25 |
JDBC batch insert performance (0) | 2020.11.25 |
Swift iOS에서 기기 방향 설정 (0) | 2020.11.25 |