2015-05-12 50 views
25

我想在Android中實現一個像Twitter這樣的自定義彈出式菜單,例如有物品和圖片,但我不知道用於此的組件是什麼。如何使用Material Design Android實現此自定義彈出式菜單?

在Material Design網站上,google存在this solution。所以我認爲,有一個本地解決方案來實現這一點。

enter image description here

我試圖與Popup menu,但我怎麼也找不到自定義此觀點類似的佈局。

+0

嗨洛佩茲,請試試我的代碼,讓我知道它是否工作與否。謝謝:) – Biswajit

回答

24

您可以使用ListPopupWindow,提交您的自定義適配器,通過它您可以控制ListPopupWindow的每一行的佈局。至於正常的PopupWindow,您必須提供錨點視圖,而且您必須在ListPopupWindow的實例上調用setContentWidth,該實例將彈出窗口的寬度設置爲其內容的大小。這是一個小的價格,你必須支付,但對於一個小數據集並不是什麼大不了的。我有這個實用方法來檢索行的最大寬度:

public int measureContentWidth(ListAdapter adapter) { 
    int maxWidth = 0; 
    int count = adapter.getCount(); 
    final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
    final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
    View itemView = null; 
    for (int i = 0; i < count; i++) { 
     itemView = adapter.getView(i, itemView, this); 
     itemView.measure(widthMeasureSpec, heightMeasureSpec); 
     maxWidth = Math.max(maxWidth, itemView.getMeasuredWidth()); 
    } 
    return maxWidth; 
} 
+0

你將如何獲得該行的材料主題? –

+0

@AnubianNoob我會使用styles.xml – Blackbelt

+0

你會繼承什麼風格?我在爲這兩行和包含它們的ListView而煩惱。 –

3

有一個名爲PopupMenu的小部件,它基本上是一個錨定到特定視圖的菜單。一個缺點是它默認不顯示圖標。

但是,您可以使用反射並致電setForceShowIcon來揭示它們。你需要的代碼是:

  • 由於PopupMenu被固定在特定的視圖,您ActionBar項目都有一個actionLayout屬性。作爲佈局(action_item.xml)可以很簡單:

    <Button 
        xmlns:android="http://schemas.android.com/apk/res/android" 
        style="?attr/actionButtonStyle" 
        android:layout_gravity="center" 
        android:text="Show popup" 
        android:textStyle="bold" 
        android:textSize="12sp" 
        android:layout_width="wrap_content" 
        android:layout_height="match_parent"/> 
    
  • ActionBar菜單樣式,包含與上述佈局的項目

    <menu 
        xmlns:android="http://schemas.android.com/apk/res/android"> 
        <item 
         android:id="@+id/popup_item" 
         android:title="Show popup" 
         android:showAsAction="always" 
         android:actionLayout="@layout/action_item"/> 
    </menu> 
    
  • popup_menu.xml,你會誇大你的PopupMenu佈局

    <menu 
        xmlns:android="http://schemas.android.com/apk/res/android"> 
        <item 
         android:id="@+id/item1" 
         android:title="Item1" 
         android:icon="@mipmap/ic_launcher"/> 
    </menu> 
    
  • 最後,執行infla的代碼一個ActionBar項目被點擊

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
        switch (item.getItemId()) { 
         case R.id.action_add_item: 
          PopupMenu popup = new PopupMenu(this, item.getActionView()); 
          MenuInflater inflater = popup.getMenuInflater(); 
          inflater.inflate(R.menu.popup_menu, popup.getMenu()); 
    
          // Use reflection to invoke setForceShowIcon 
          try { 
           Field[] fields = popup.getClass().getDeclaredFields(); 
           for (Field field : fields) { 
            if ("mPopup".equals(field.getName())) { 
             field.setAccessible(true); 
             Object menuPopupHelper = field.get(popup); 
             Class<?> classPopupHelper = Class 
               .forName(menuPopupHelper.getClass().getName()); 
             Method setForceIcons = classPopupHelper 
               .getMethod("setForceShowIcon", boolean.class); 
             setForceIcons.invoke(menuPopupHelper, true); 
             break; 
            } 
           } 
          } catch (Exception e) { 
           e.printStackTrace(); 
          } 
    
          popup.show(); 
          return true; 
        } 
    
        return super.onOptionsItemSelected(item); 
    } 
    

注意,當獲得在一個菜單中多行文本離子,你需要使用您的彈出菜單項的actionLayout了。

1

這代碼在我的應用程序中工作。

試試這個: -

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
tools:context=".LocationDetailsActivity"> 


<item xmlns:tools="http://schemas.android.com/tools" 
    android:icon="@android:drawable/ic_menu_mapmode" 
    app:showAsAction="ifRoom" 
    android:title="@string/title_of_menu" 
    tools:context=".LocationDetailsActivity"> 
    //the menu list with icon 
    <menu> 
     <item 
      android:id="@+id/action_map_type_normal" 
      android:orderInCategory="100" 
      android:icon="some_icon" //place your icon here 
      android:title="Vacation spots" /> 
     <item 
      android:id="@+id/action_map_type_satellite" 
      android:orderInCategory="100" 
      android:icon="some_icon" //place your icon here 
      android:title="Friends and family" /> 
     <item 
      android:id="@+id/action_map_type_hybrid" 
      android:orderInCategory="100" 
      android:icon="some_icon" //place your icon here 
      android:title="Restaurants" /> 
    </menu> 
</item> 

你可以通過教程從這些不同的供應商

http://developer.android.com/guide/topics/ui/actionbar.html

http://www.vogella.com/tutorials/AndroidActionBar/article.html

http://www.androidhive.info/2013/11/android-working-with-action-bar/

他們都有很好的例子和源代碼,以幫助你

希望這有助於你:)

+1

儘管這個鏈接可能回答這個問題,但最好在這裏包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – DaImTo

+0

@達姆是的,你是對的。但是這些是完整的教程,所以它更好地檢查整個教程。我會添加一些主要內容。謝謝:) – Biswajit

2

我已經同issue.but終於讓我找到我自己的解決方案,我正在分享你我碼。希望這會幫助你。

popupWindowDogs = popupWindowDogs(); 
    button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      // popupWindowDogs.showAsDropDown(v, -5, 0); 
      popupWindowDogs().showAtLocation(v, Gravity.CENTER, 0, 0); 
     } 
    }); 
    // Detect touched area 
    detector = new SimpleGestureFilter(this, this); 

}

public PopupWindow popupWindowDogs() 
{ 

    // initialize a pop up window type 
    PopupWindow popupWindow = new PopupWindow(this); 

    // the drop down list is a list view 
    final ListView listView = new ListView(this); 
    // set our adapter and pass our pop up window contents 
    listView.setAdapter(dogsAdapter(popUpContents)); 
    // listView.setBackgroundColor(Color.DKGRAY); 
    listView.setBackgroundResource(R.drawable.ss4); 
    listView.setPadding(0, 0, 0, 10); 
    listView.setDivider(null); 
    try { 

     listView.setOnScrollListener(new OnScrollListener() { 

      @Override 
      public void onScrollStateChanged(AbsListView view, int scrollState) { 
       View c = listView.getChildAt(0); 
       String cc = listView.getChildAt(0).toString(); 
       int scrolly = -c.getTop() + listView.getFirstVisiblePosition() * c.getHeight(); 
       /* 
       * Toast.makeText(getApplicationContext(), scrolly + "", Toast.LENGTH_SHORT) 
       * .show(); 
       */} 

      @Override 
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
        int totalItemCount) { 

      } 
     }); 
    } catch (Exception e) { 
     Toast.makeText(getApplicationContext(), e.toString() + "", Toast.LENGTH_SHORT) 
       .show(); 
    } 
    listView.setOnItemClickListener(new OnItemClickListener() { 

     @Override 
     public void onItemClick(AdapterView<?> arg0, View v, int arg2, 
       long arg3) { 
      try { 

       // TODO Auto-generated method stub 
       Context mContext = v.getContext(); 
       Swipetouch mainActivity = ((Swipetouch) mContext); 
       // add some animation when a list item was clicked 
       Animation fadeInAnimation = AnimationUtils.loadAnimation(v.getContext(), 
         android.R.anim.fade_in); 
       fadeInAnimation.setDuration(10); 
       v.startAnimation(fadeInAnimation); 
       // dismiss the pop up 
       mainActivity.popupWindowDogs.dismiss(); 
       // get the text and set it as the button text 
       String val = (String) arg0.getItemAtPosition(arg2); 
       // Toast.makeText(mContext, val, Toast.LENGTH_SHORT).show(); 
       if (val.equals("Signup Now")) { 
        Intent ii = new Intent(getApplicationContext(), Registration.class); 
        startActivity(ii); 
        stopService(new Intent(Swipetouch.this, MyService.class)); 
        stopService(new Intent(Swipetouch.this, MyService.class)); 
       } else if (val.equals("Login")) { 
        Intent ii = new Intent(getApplicationContext(), MyLoginActivity.class); 
        startActivity(ii); 
        stopService(new Intent(Swipetouch.this, MyService.class)); 

       } else if (val.equals("Exit")) { 
        finish(); 
        stopService(new Intent(Swipetouch.this, MyService.class)); 
       } else if (val.equals("Friends")) { 
        Intent ii = new Intent(getApplicationContext(), MyLoginActivity.class); 
        startActivity(ii); 
       } else if (val.equals("Exit")) { 
        stopService(new Intent(Swipetouch.this, MyService.class)); 
        finish(); 
       } 

      } catch (Exception e) { 
       Toast.makeText(Swipetouch.this, e.toString(), Toast.LENGTH_SHORT).show(); 
      } 
     } 

    }); 
    // some other visual settings 
    popupWindow.setFocusable(true); 
    popupWindow.setWidth(250); 
    // popupWindow.setHeight(300); 
    popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); 

    // set the list view as pop up window content 
    // SET WALLPAPER IMAGE 
    /* 
    * popupWindow.setBackgroundDrawable(getWallpaper()); popupWindow.setHeight(300); 
    */ 
    // layout.setBackgroundResource(R.drawable.sshadow); 
    // layout.setBackgroundColor(Color.TRANSPARENT); 
    // popupWindow.setContentView(layout); 

    popupWindow.setBackgroundDrawable(new ColorDrawable(
      android.graphics.Color.TRANSPARENT)); 
    popupWindow.setContentView(listView); 

    return popupWindow; 
} 
1
try { 
        java.lang.reflect.Field[] fields = popup.getClass().getDeclaredFields(); 
        for (java.lang.reflect.Field field : fields) { 
         if ("mPopup".equals(field.getName())) { 
          field.setAccessible(true); 
          Object menuPopupHelper = field.get(popup); 
          Class<?> classPopupHelper = Class 
            .forName(menuPopupHelper.getClass().getName()); 
          Method setForceIcons = classPopupHelper 
            .getMethod("setForceShowIcon", boolean.class); 
          setForceIcons.invoke(menuPopupHelper, true); 
          break; 
         } 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
+0

只需在popup.show()之前的這段代碼; 它工作perfectttttllyyyy :) –

0

容易的解決方案。在.show()方法之前添加。

try { 
    Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup"); 
    mFieldPopup.setAccessible(true); 
    MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu); 
    mPopup.setForceShowIcon(true); 
} catch (Exception e) {}