web-dev-qa-db-fra.com

Android PopupWindow altitude ne montre pas d'ombre

Android Fenêtre contextuelle n'affiche pas les ombres lorsque l'altitude est définie. Il semble le supporter de la documentation. J'utilise 5.0 Lollipop. 

Créer la popup comme suit:

    popupWindow = new PopupWindow(context);
    popupWindow.setOutsideTouchable(true);
    popupWindow.setFocusable(true);
    popupWindow.setElevation(10);
    popupWindow.setContentView(rootView);
    popupWindow.showAtLocation(anchorView, Gravity.NO_GRAVITY, xPos, yPos);
23
Patrick

Comme répondu par un développeur Android

Si la vue gonflée n’a pas d’arrière-plan défini, ou le popup La fenêtre elle-même n’a pas d’arrière-plan défini (ou a un arrière-plan transparent ), vous n’obtiendrez pas d’ombre.

ce qui était mon cas et semble être le vôtre, puisque vous n'utilisez pas setBackgroundDrawable.

Cela a fonctionné pour moi

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));

J'ai ouvert un nouveau problème suggérant qu'ils mettent à jour la documentation ( https://code.google.com/p/Android/issues/detail?id=174919 )

19
Maragues

Pour les autres qui visitent cette réponse et qui ont raté ce que le PO avait déjà, vous devez définir l’altitude pour créer une ombre:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
    popupWindow.setElevation(20);
}

PopupWindow with shadow

En fonction de la vue de votre contenu, vous devrez peut-être également définir l’arrière-plan dessinable, bien que cela ne soit pas toujours nécessaire. Si nécessaire, vous pouvez faire ce que @Maragues a suggéré:

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));

Pour prendre en charge les périphériques pré-Lollipop, vous pouvez utiliser un patch de 9 ou une image incluant l’ombre.

Code

C'est le code de l'image ci-dessus.

LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = inflater.inflate(R.layout.popup_window, null);
int width = LinearLayout.LayoutParams.WRAP_CONTENT;
int height = LinearLayout.LayoutParams.WRAP_CONTENT;
boolean focusable = true;
final PopupWindow popupWindow = new PopupWindow(popupView, width, height, focusable);
popupView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        popupWindow.dismiss();
        return true;
    }
});

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
    popupWindow.setElevation(20);
}

popupWindow.showAtLocation(anyView, Gravity.CENTER, 0, 0);

Remarque:

L'élévation est en pixels si elle est définie dans le code, mais généralement dans dp si elle est définie dans xml. Vous devez convertir une valeur dp en pixels lorsque vous la définissez dans le code.

2
Suragch
  • setElevation ne montrait pas d'ombre, car mon conteneur était transparent
  • Mon conteneur était transparent car j'avais besoin de rembourrage de chaque côté 

Capture d'écran du code ci-dessous

  • J'ai fait trois containers
  • Le conteneur le plus extérieur est transparent
  • Le prochain conteneur à l'intérieur a un fond dessinable avec l'ombre
  • Le conteneur suivant contient le contenu réel
  • La largeur minimale du bouton à l'intérieur de la variable xml permet de dicter la largeur. Idem avec le 12dp de remplissage du second conteneur.

Classe de fenêtre contextuelle personnalisée écrite en Kotlin:

class CustomPopupWindow(
    private val context: Context
) : PopupWindow(context) {

  init {
    val view = LayoutInflater.from(context).inflate(R.layout.popup_window_layout, null)
    contentView = view

    height = ListPopupWindow.WRAP_CONTENT
    width = ListPopupWindow.MATCH_PARENT
    isOutsideTouchable = true

    setTouchDismissListener()

    // set the background of the second container to the drawable
    // with the shadow to get our shadow
    contentView.findViewById<LinearLayout>(R.id.outer_content_container).setBackgroundDrawable(context.resources.getDrawable(R.drawable.background_shadow))
  }

  // Add a listener to dismiss the popup Window when someone
  // clicks outside of it
  private fun setTouchDismissListener() {
    setTouchInterceptor { _, event ->
      if (event != null && event.action == MotionEvent.ACTION_OUTSIDE) {
        dismiss()
        return@setTouchInterceptor true
      }
      false
    }
  }

  // this anchor view can be ANY view
  fun show(anchor: View) {

    // Remove the default background that is annoying
    setBackgroundDrawable(BitmapDrawable())

    // Grab the pixel count for how far down you want to put it.
    // toolbar_height is 56dp for me
    val yOffSetInPixels = context.resources.getDimensionPixelSize(R.dimen.toolbar_height)

    // Animation to make it appear and disappear like a Dialog
    animationStyle = Android.R.style.Animation_Dialog

    // Show it
    showAtLocation(anchor, Gravity.TOP, 0, yOffSetInPixels)
  }
}

  • XML pour PopupWindow personnalisé:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
  xmlns:app="http://schemas.Android.com/apk/res-auto"
  Android:layout_width="match_parent"
  Android:layout_height="wrap_content"
  Android:background="@Android:color/transparent"
  Android:orientation="vertical">

  <Android.support.constraint.ConstraintLayout
    Android:id="@+id/transparent_container"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_gravity="center"
    Android:background="@Android:color/transparent"
    Android:padding="12dp">

    <LinearLayout
      Android:id="@+id/outer_content_container"
      Android:layout_width="match_parent"
      Android:layout_height="wrap_content"
      Android:background="@color/white"
      Android:orientation="vertical"
      app:layout_constraintBottom_toBottomOf="@+id/transparent_container"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/transparent_container">

      <LinearLayout
        Android:id="@+id/content_container"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        Android:padding="12dp">

        <TextView
          Android:layout_width="match_parent"
          Android:layout_height="wrap_content"
          Android:text="Header" />

        <LinearLayout
          Android:layout_width="match_parent"
          Android:layout_height="match_parent"
          Android:layout_gravity="center_vertical"
          Android:layout_marginTop="8dp"
          Android:orientation="horizontal">

          <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_gravity="center_vertical"
            Android:paddingEnd="0dp"
            Android:paddingStart="8dp"
            Android:text="Message" />

        </LinearLayout>

        <TextView
          Android:id="@+id/add_to_bag_button"
          Android:layout_width="match_parent"
          Android:layout_height="wrap_content"
          Android:layout_marginTop="16dp"
          Android:height="48dp"
          Android:background="@color/gray"
          Android:gravity="center"
          Android:minWidth="350dp"
          Android:text="BUTTON"
          Android:textAllCaps="true" />

      </LinearLayout>

    </LinearLayout>

  </Android.support.constraint.ConstraintLayout>

</LinearLayout>

  • Custom Drawable qui montre une ombre:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">

  <!-- Drop Shadow Stack -->
  <item>
    <shape>
      <padding
        Android:bottom="1dp"
        Android:left="1dp"
        Android:right="1dp"
        Android:top="0dp" />

      <solid Android:color="#00CCCCCC" />

      <corners Android:radius="3dp" />
    </shape>
  </item>
  <item>
    <shape>
      <padding
        Android:bottom="1dp"
        Android:left="1dp"
        Android:right="1dp"
        Android:top="0dp" />

      <solid Android:color="#10CCCCCC" />

      <corners Android:radius="3dp" />
    </shape>
  </item>
  <item>
    <shape>
      <padding
        Android:bottom="1dp"
        Android:left="1dp"
        Android:right="1dp"
        Android:top="0dp" />

      <solid Android:color="#20CCCCCC" />

      <corners Android:radius="3dp" />
    </shape>
  </item>
  <item>
    <shape>
      <padding
        Android:bottom="1dp"
        Android:left="1dp"
        Android:right="1dp"
        Android:top="0dp" />

      <solid Android:color="#30CCCCCC" />

      <corners Android:radius="3dp" />
    </shape>
  </item>
  <item>
    <shape>
      <padding
        Android:bottom="1dp"
        Android:left="1dp"
        Android:right="1dp"
        Android:top="0dp" />

      <solid Android:color="#50CCCCCC" />

      <corners Android:radius="3dp" />
    </shape>
  </item>

  <!-- Background -->
  <item>
    <shape>
      <solid Android:color="@Android:color/white" />

      <corners Android:radius="0dp" />
    </shape>
  </item>

</layer-list>

  • Tout utiliser: 
val popupWindow = CustomPopupWindow(activity);
popupWindow.show(anyViewInYourActivity);
0
caseta