2017-05-24 1 views
0

Je veux afficher une fenêtre contextuelle dans mon code de sorte que, peu importe où je touche sur l'écran, la fenêtre apparaisse juste au-dessus de l'endroit où je touche . Pas sûr, comment y parvenir. Ceci est mon code actuel de fenêtre:Comment afficher une fenêtre popup juste au-dessus de l'endroit où j'ai touché l'écran

LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE); 

          View customView = inflater.inflate(R.layout.popup,null); 

          final PopupWindow popupWindow = new PopupWindow(
            customView, 
            LayoutParams.WRAP_CONTENT, 
            LayoutParams.WRAP_CONTENT); 

          // Set an elevation value for popup window 
          // Call requires API level 21 
          if(Build.VERSION.SDK_INT>=21){ 
           popupWindow.setElevation(5.0f); 
          } 
          final TextView placename = (TextView) customView.findViewById(R.id.popup_id) ; 
          Button closeButton = (Button) customView.findViewById(R.id.directions); 
          placename.setText(place.getName()); 
          popupWindow.setBackgroundDrawable(new BitmapDrawable()); 
          popupWindow.setOutsideTouchable(true); 
          // Set a click listener for the popup window close button 
          closeButton.setOnClickListener(new View.OnClickListener() { 
           @Override 
           public void onClick(View view) { 
            // Dismiss the popup window 

            popupWindow.dismiss(); 

           } 
          }); 
          popupWindow.setFocusable(true); 

          popupWindow.showAtLocation(mapInsideContainer, Gravity.CENTER, 0, 0); 
          popupWindow.showAsDropDown(customView); 

Ceci est mon popup.xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" 
    android:background="@android:color/background_light"> 
    <LinearLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:layout_margin="1dp" 
     android:background="@android:color/white"> 
     > 
     <LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      android:layout_margin="20dp"> 
      <TextView 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:textColor="#000000" 
       android:id="@+id/popup_id" /> 
      <Button 
       android:id="@+id/directions" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:background="@color/black_overlay" 
       android:textColor="@android:color/white" 
       android:text="Directions" /> 
     </LinearLayout> 
    </LinearLayout> 
</LinearLayout> 

Actuellement, il montre au centre de l'écran en raison de Gravity.CENTER, mais je voudrais montrer juste au-dessus de l'endroit où je touche dynamiquement à l'écran. Des idées? Merci

points bonus si vous pouviez me guider à travers la création d'une bulle de chat comme pop-up avec le titre sur le dessus et un bouton « endroits » en bas avec le pointeur de la bulle à la position cliqué sur l'écran

Répondre

0

Au lieu d'utiliser popupWindow , essayez de créer une activité transparente, similaire à this.

Ensuite, vous pouvez créer des tirages personnalisés pour les bulles de discussion (puisque le pointeur de bulle devra être à différents endroits en fonction de l'endroit où l'utilisateur a cliqué). Remplacez onTouchEvent() et obtenez les coordonnées des utilisateurs, puis lancez l'activité transparente et transmettez-lui les coordonnées dans l'intention, de sorte que vous puissiez placer la vue bulle à l'endroit approprié.

Cela ajoute une surcharge supplémentaire car vous lancez une nouvelle activité, mais elle vous donne toute la puissance pour personnaliser l'apparence et le comportement comme vous le souhaitez.

Voici quelques détails. C'est ce que j'ai fait quand je veux des menus contextuels personnalisés.

Pour l'activité transparente, créer une nouvelle activité et attribuer un thème dans le manifeste:

<activity 
     android:name=".PopupActivity" 
     android:theme="@style/Transparent" /> 

Et styles.xml:

<style name="Transparent" parent="Theme.AppCompat.NoActionBar"> 
    <item name="android:windowIsTranslucent">true</item> 
    <item name="android:windowBackground">@color/translucent</item> 
</style> 

Vous pouvez définir @color/translucent être complètement transparent, j'y ajoute du gris pour que la vue apparaisse en sourdine lorsque la fenêtre apparaît.

Dans la mise en page de l'activité:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/activity_popup" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@color/colorPrimary" 
    android:layout_margin="60dp"> 

J'utilise ici RelativeLayout, mais vous pouvez utiliser ce que la mise en page que vous voulez, l'important est les marges. Maintenant, l'activité se présente comme suit, où l'activité de fond est visible derrière celui-ci:

Ensuite, vous allez utiliser la touche coordonnées pour modifier dynamiquement les marges pour faire apparaître le rectangle où vous voulez.

Nous aurons besoin de connaître la taille de l'écran et de la densité et la hauteur de la barre d'état en haut de l'écran, donc dans la méthode onCreate() de votre activité principale, ajouter:

//Determine the screen dimensions and density 
DisplayMetrics metrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metrics); 
screenWidth = metrics.widthPixels; 
screenHeight = metrics.heightPixels; 
screenDensity = metrics.density; 
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 
int statusBarHeight = (int) (24 * density); 
if (resourceId > 0) { 
    statusBarHeight = getResources().getDimensionPixelSize(resourceId); 
} 

Ces valeurs ne changeront pas, alors stockez-les dans des variables statiques afin que les autres classes puissent les obtenir en cas de besoin.

Maintenant, dans le procédé onCreate() de l'activité transparente, calculer les marges sur la base des coordonnées événement tactile:

int popupSize = 100; 
int rMargin, lMargin, tMargin, bMargin; 

lMargin = xCoord - popupSize; 
rMargin = screenWidth - xCoord - popupSize; 
tMargin = yCoord - popupSize; 
bMargin = screenHeight - yCoord - popupSize - statusBarHeight; 

RelativeLayout layout = (RelativeLayout) findViewById(R.id.activity_popup); 
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) layout.getLayoutParams(); 
params.setMargins(lMargin, tMargin, rMargin, bMargin); 
layout.setLayoutParams(params); 

Cela crée un carré centré sur les coordonnées tactile. Par exemple, étant donné x = 700 et y = 1500, je reçois:

enter image description here

Et pour x = 150 et y = 200, je reçois:

enter image description here

Vous pouvez voir que dans ce cas, si les coordonnées sont trop proches du bord, vous obtiendrez une marge négative et le carré sera rogné. Il faudra plus de maths pour corriger cela. Ce que je ferais est de diviser la zone de l'écran en quatre quadrants et calculer quel quadrant l'événement tactile était. Ensuite, par exemple si le toucher était dans le quadrant supérieur gauche, aligner le coin supérieur gauche du carré avec le coordonnées tactiles. De cette façon, le carré ne sera jamais recadré par le bord de l'écran.

En ce qui concerne la création d'une bulle avec un pointeur, créez 4 tirages personnalisés de la bulle, chacun avec le pointeur sur un angle différent. Puis, en fonction du quadrant de l'événement tactile, chargez le dessinable approprié afin que le pointeur soit toujours dans la bonne direction.

Ce post devient un peu trop long pour ça.

+0

si vous pouvez aider avec des détails qui seront utiles que l'activité transparente partie est source de confusion et je ne sais pas comment cela pourrait résoudre le problème de fenêtre ne pas afficher à droite au-dessus du point de toucher –

+0

@JusticeBauer J'ai édité ma réponse pour fournir quelques détails. Je vais éditer plus ce soir mais je dois y aller maintenant. –

+0

@JusticeBauer J'ai ajouté plus de détails. –

0

c'est ce que je l'ai fait, vous aider espoir

customView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 

popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, (int)event.getX(), (int)event.getY() - customView.getMeasuredHeight()); 

Et Override public boolean onTouchEvent(MotionEvent event)

@Override 
    public boolean onTouchEvent(MotionEvent event) { 
     popup(event); 
     return super.onTouchEvent(event); 
    } 

EDIT: Mon écriture comme suit, et c'est un travail pour moi.

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     popup(event); 
     return super.onTouchEvent(event); 
    } 

    private void popup(MotionEvent event) { 
     LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE); 

     View customView = inflater.inflate(R.layout.popup,null); 

     final PopupWindow popupWindow = new PopupWindow(
       customView, 
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.WRAP_CONTENT); 

     // Set an elevation value for popup window 
     // Call requires API level 21 
     if(Build.VERSION.SDK_INT>=21){ 
      popupWindow.setElevation(5.0f); 
     } 
     final TextView placename = (TextView) customView.findViewById(R.id.popup_id) ; 
     Button closeButton = (Button) customView.findViewById(R.id.directions); 
     placename.setText("Name"); 
     popupWindow.setBackgroundDrawable(new BitmapDrawable()); 
     popupWindow.setOutsideTouchable(true); 
     // Set a click listener for the popup window close button 
     closeButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       // Dismiss the popup window 

       popupWindow.dismiss(); 

      } 
     }); 
//  popupWindow.setFocusable(true); 
     popupWindow.setOutsideTouchable(true); 
     customView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 
     popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, (int)event.getX(), (int)event.getY() - customView.getMeasuredHeight()); 

     getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       return false; 
      } 
     }); 
    } 

} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 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" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/parent" 
    android:background="@color/colorAccent" 
    android:fitsSystemWindows="true"> 


</android.support.constraint.ConstraintLayout> 
+0

(int) event.getY() et (int) event.getX(), quel est l'événement ici? Il apparaît comme une erreur –

+0

Je ne connais pas la vue cible dont vous avez réellement besoin, qui la touche pour afficher la fenêtre contextuelle, donc je remplace l'activité 'public boolean onTouchEvent (événement MotionEvent)', donc l'événement param est celui event dans '(int) event.getX()', si votre vue cible est 'mapInsideContainer', vous pouvez utiliser' public void setOnTouchListener (OnTouchListener l) '. – VictorPanda

+0

ne fonctionne pas non plus. est-il un moyen plus facile de calculer –