2015-05-12 13 views
25

Desidero realizzare un menu popup personalizzato come Twitter in Android ad esempio con articolo e immagine ma non so quale sia il componente utilizzato per quello.Come realizzare questo menu popup personalizzato con Material Design Android?

Nel sito Web di Material Design, google present this solution. Quindi penso che ci sia una soluzione nativa per raggiungere questo obiettivo.

enter image description here

ho provato con Popup menu, ma non riesco a trovare il modo di personalizzare il layout della vista come quella.

+0

Ciao Lopez, Si prega di provare il mio codice e fammi sapere se funziona o no. Grazie :) – Biswajit

risposta

24

è possibile utilizzare uno ListPopupWindow, inoltrando il proprio adattatore personalizzato, tramite il quale è possibile controllare il layout di ogni singola riga di ListPopupWindow. Come per un normale PopupWindow è necessario fornire una vista di ancoraggio e inoltre è necessario chiamare setContentWidth sull'istanza di ListPopupWindow, che imposta la larghezza della finestra popup in base alla dimensione del suo contenuto. È un piccolo prezzo che devi pagare, ma per un piccolo set di dati non è un grosso problema. Ho questo metodo di utilità per recuperare la larghezza massima della fila:

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

Come vorresti che la fila avesse quel tema materiale? –

+0

@AnubianNoob Vorrei usare styles.xml – Blackbelt

+0

Quale stile erediteresti? Sto lottando con quello, sia per le righe che per il ListView che li contiene. –

3

C'è un widget chiamato PopupMenu che è fondamentalmente un menu ancorato a una vista specifica. Uno svantaggio è che non visualizza le icone per impostazione predefinita.

Tuttavia, è possibile utilizzare la riflessione e chiamare setForceShowIcon per visualizzarli. Il codice che vi serve è:

  • Dal momento che un PopupMenu è ancorato ad una vista specifica, il vostro articolo ActionBar ha un attributo actionLayout. Il layout (action_item.xml) può essere semplice come:

    <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 stile del menu che contiene il vostro articolo con la disposizione di cui sopra

    <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> 
    
  • tuo popup_menu.xml, il layout si gonfia per la vostra 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> 
    
  • E infine codice per eseguire l'inflat ione quando un elemento ActionBar viene cliccato

    @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); 
    } 
    

nota, che per ottenere quel testo su più righe in un menu, avresti bisogno di utilizzare un actionLayout per le voci di menu a comparsa troppo.

1

Questo il codice funziona nella mia app.

Prova questo: -

<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> 

si può passare attraverso il tutorial da questi diversi fornitori

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/

Tutti loro hanno grandi esempi e il codice sorgente per aiutarvi

Spero che questo aiuto voi :)

+1

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – DaImTo

+0

@Dalm Sì, hai ragione. Ma questi sono i tutorial completi quindi è meglio controllare l'intero tutorial. Aggiungerò alcuni contenuti principali. Grazie :) – Biswajit

2

Ho stesso issue.but finalmente ho trovato la mia propria soluzione che vi sto condividendo la mia codice. Spero che ti possa aiutare.

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

Basta dd questo codice prima di popup.show(); ha funzionato perfettamentettttllyyyy :) –

0

facile soluzione. Aggiungi questo appena prima del metodo .show().

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