2010-07-20 19 views
156

¿Es posible establecer la posición absoluta de una vista en Android? (Sé que hay una AbsoluteLayout, pero ha DEPRECATED ...)Establecer la posición absoluta de una vista

Por ejemplo, si tengo una pantalla de 240x320px, ¿cómo podría añadir una ImageView que es 20x20px que su centro está en la posición (100,100) ?

+3

también ven 'view.setTranslationX()' 'o view.offsetLeftAndRight()' –

+0

Acabo de liberar una biblioteca que puede haber sido de interés aquí. github.com/ManuelPeinado/ImageLayout – Manuel

+1

Esto es muy difícil porque el 99.9% del tiempo el posicionamiento absoluto es una mala idea en Android. Si está escribiendo una aplicación que * SOLO * se ejecutará en un dispositivo físico, esto podría funcionar, pero generalmente no es una suposición segura. Por ejemplo, no cargue esto a google play.Funciona bien en iOS porque solo hay un puñado de dispositivos de hardware, y puedes construir un guión gráfico personalizado para cada uno. – edthethird

Respuesta

231

Puede usar RelativeLayout. Digamos que usted quería una ImageView de 30x40 en la posición (50,60) dentro de su diseño. En algún lugar de su actividad:

// Some existing RelativeLayout from your layout xml 
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout); 

ImageView iv = new ImageView(this); 

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 50; 
params.topMargin = 60; 
rl.addView(iv, params); 

Más ejemplos:

coloca dos 30x40 ImageViews (uno amarillo, uno rojo) en (50,60) y (80,90), respectivamente:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout); 
ImageView iv; 
RelativeLayout.LayoutParams params; 

iv = new ImageView(this); 
iv.setBackgroundColor(Color.YELLOW); 
params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 50; 
params.topMargin = 60; 
rl.addView(iv, params); 

iv = new ImageView(this); 
iv.setBackgroundColor(Color.RED); 
params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 80; 
params.topMargin = 90; 
rl.addView(iv, params); 

Lugares uno 30x40 ImageView amarilla al (50,60) y otro ImageView rojo 30x40 < 80,90>relativa a ImageView amarilla:

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout); 
ImageView iv; 
RelativeLayout.LayoutParams params; 

int yellow_iv_id = 123; // Some arbitrary ID value. 

iv = new ImageView(this); 
iv.setId(yellow_iv_id); 
iv.setBackgroundColor(Color.YELLOW); 
params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 50; 
params.topMargin = 60; 
rl.addView(iv, params); 

iv = new ImageView(this); 
iv.setBackgroundColor(Color.RED); 
params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 80; 
params.topMargin = 90; 

// This line defines how params.leftMargin and params.topMargin are interpreted. 
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView. 
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id); 

rl.addView(iv, params); 
+1

Voy a probar eso esta noche, esa es una muy buena idea, no sé por qué no pensé en eso. Como tengo varios 'ImageView' para poner, ¿no sería mejor usar un' FrameLayout'? – Sephy

+0

De hecho, esto parece funcionar, sin embargo, solo funciona cuando se agrega una imagen de esta manera. si trato de agregar un 2º, el primero simplemente desaparece ... – Sephy

+1

Las dos imágenes están una encima de la otra. Agregaré un código a mi solución anterior para explicar. –

15

Sólo para añadir a la respuesta de Andy Zhang anterior, si lo desea, se puede dar a rl.addView parámetro, a continuación, hacer cambios en él más tarde, así:

params = new RelativeLayout.LayoutParams(30, 40); 
params.leftMargin = 50; 
params.topMargin = 60; 
rl.addView(iv, params); 

también se podría escrita como:

params = new RelativeLayout.LayoutParams(30, 40); 
rl.addView(iv, params); 
params.leftMargin = 50; 
params.topMargin = 60; 

Así que si no conserva la variable params, se puede cambiar el diseño de iv en cualquier momento después de añadirlo a RL.

+0

amaba esta muestra. ¿Puede sugerirme cómo puedo establecer el eje x, y cuando estoy teniendo la imagen en el diseño xml. (Estoy tratando de cambiar el tamaño de la imagen y tengo que configurar la imagen en alguna posición) –

+0

Me temo que no entiendo muy bien lo que estás preguntando ¿Está intentando acceder al objeto LayoutParams asociado con un objeto que se ha posicionado utilizando el diseño XML? No estoy seguro de cómo se hace eso. Podría valer la pena establecer una nueva pregunta para que se responda, si no puede encontrar la respuesta en otro lugar. – Excrubulent

+0

tenga una mirada a esta pregunta http://stackoverflow.com/questions/12028404/resizing-the-imageview-makes-it-change-its-place/12028508#comment16054261_12028508 –

5

Un modo más limpio y más dinámico sin codificar cualquier valor de píxel en el código.

yo quería colocar un cuadro de diálogo (que inflè sobre la marcha) exactamente por debajo de un botón se hace clic.

y resolverse de esta manera:

// get the yoffset of the position where your View has to be placed 
    final int yoffset = < calculate the position of the view > 

    // position using top margin 
    if(myView.getLayoutParams() instanceof MarginLayoutParams) { 
     ((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset; 
    } 

Sin embargo, usted tiene que asegurarse de la disposición de los padres de myView es una instancia de RelativeLayout.

Código más completo:

// identify the button 
    final Button clickedButton = <... code to find the button here ...> 

    // inflate the dialog - the following style preserves xml layout params 
    final View floatingDialog = 
     this.getLayoutInflater().inflate(R.layout.floating_dialog, 
      this.floatingDialogContainer, false); 

    this.floatingDialogContainer.addView(floatingDialog); 

    // get the buttons position 
    final int[] buttonPos = new int[2]; 
    clickedButton.getLocationOnScreen(buttonPos);   
    final int yOffset = buttonPos[1] + clickedButton.getHeight(); 

    // position using top margin 
    if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) { 
     ((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset; 
    } 

De esta manera usted todavía puede esperar que la vista de destino para ajustar a cualquier parámetro Establecer diseño utilizando archivos XML diseño, en lugar de codificar esos píxeles/dps en el código Java.

41

En general, puede agregar una Vista en una posición específica usando un FrameLayout como contenedor especificando los atributos leftMargin y topMargin.

el ejemplo siguiente se colocará un ImageView 20x20px en la posición (100,200) usando un FrameLayout como recipiente de pantalla completa:

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/root" 
    android:background="#33AAFF" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 
</FrameLayout> 

vista Actividad/Fragmento/Custom

//... 
FrameLayout root = (FrameLayout)findViewById(R.id.root); 
ImageView img = new ImageView(this); 
img.setBackgroundColor(Color.RED); 
//..load something inside the ImageView, we just set the background color 

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20); 
params.leftMargin = 100; 
params.topMargin = 200; 
root.addView(img, params); 
//... 

Esto hará el truco porque los márgenes se pueden usar como bsoluta (X, Y) coordina sin RelativeLayout:

enter image description here

+1

¡Brillante! Vale la pena las 500! +1 –

1

Check screenshot

Place cualquier vista de su deseo X & Y punto

archivo de diseño

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.test.MainActivity" > 

    <AbsoluteLayout 
     android:id="@+id/absolute" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" > 

     <RelativeLayout 
      android:id="@+id/rlParent" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" > 

      <ImageView 
       android:id="@+id/img" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:background="@drawable/btn_blue_matte" /> 
     </RelativeLayout> 
    </AbsoluteLayout> 

</RelativeLayout> 

Java Clase

public class MainActivity extends Activity { 

    private RelativeLayout rlParent; 
    private int width = 100, height = 150, x = 20, y= 50; 

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

     AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams(width, height, x, y); 
     rlParent = (RelativeLayout)findViewById(R.id.rlParent); 
     rlParent.setLayoutParams(param); 
    } 
} 

Hecho

-1

Trate a continuación código para programar una vista de la ubicación específica: -

  TextView textView = new TextView(getActivity()); 
      textView.setId(R.id.overflowCount); 
      textView.setText(count + ""); 
      textView.setGravity(Gravity.CENTER); 
      textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); 
      textView.setTextColor(getActivity().getResources().getColor(R.color.white)); 
      textView.setOnClickListener(new OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // to handle click 
       } 
      }); 
      // set background 
      textView.setBackgroundResource(R.drawable.overflow_menu_badge_bg); 

      // set apear 

      textView.animate() 
        .scaleXBy(.15f) 
        .scaleYBy(.15f) 
        .setDuration(700) 
        .alpha(1) 
        .setInterpolator(new BounceInterpolator()).start(); 
      FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
        FrameLayout.LayoutParams.WRAP_CONTENT, 
        FrameLayout.LayoutParams.WRAP_CONTENT); 
      layoutParams.topMargin = 100; // margin in pixels, not dps 
      layoutParams.leftMargin = 100; // margin in pixels, not dps 
      textView.setLayoutParams(layoutParams); 

      // add into my parent view 
      mainFrameLaout.addView(textView); 
0

Mi código para Xamarin, estoy usando FrameLayout para este fin y que sigue es mi código:

   List<object> content = new List<object>(); 

     object aWebView = new {ContentType="web",Width="300", Height = "300",X="10",Y="30",ContentUrl="http://www.google.com" }; 
     content.Add(aWebView); 
     object aWebView2 = new { ContentType = "image", Width = "300", Height = "300", X = "20", Y = "40", ContentUrl = "https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4" }; 
     content.Add(aWebView2); 
     FrameLayout myLayout = (FrameLayout)FindViewById(Resource.Id.frameLayout1); 
     foreach (object item in content) 
     { 

      string contentType = item.GetType().GetProperty("ContentType").GetValue(item, null).ToString(); 
      FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(Convert.ToInt32(item.GetType().GetProperty("Width").GetValue(item, null).ToString()), Convert.ToInt32(item.GetType().GetProperty("Height").GetValue(item, null).ToString())); 
      param.LeftMargin = Convert.ToInt32(item.GetType().GetProperty("X").GetValue(item, null).ToString()); 
      param.TopMargin = Convert.ToInt32(item.GetType().GetProperty("Y").GetValue(item, null).ToString()); 

      switch (contentType) { 
       case "web":{ 
         WebView webview = new WebView(this); 

         //webview.hei; 
         myLayout.AddView(webview, param); 
         webview.SetWebViewClient(new WebViewClient()); 
         webview.LoadUrl(item.GetType().GetProperty("ContentUrl").GetValue(item, null).ToString()); 

         break; 
        } 
       case "image": 
        { 
         ImageView imageview = new ImageView(this); 

         //webview.hei; 
         myLayout.AddView(imageview, param); 
         var imageBitmap = GetImageBitmapFromUrl("https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4"); 
         imageview.SetImageBitmap(imageBitmap); 


         break; 
        } 

      } 

     } 

era útil para mí porque necesitaba la propiedad de vista a superponerse entre sí en base a su apariencia, por ejemplo las vistas reciben apiladas una encima de otra.

0

Sólo en caso de que puede ayudar a alguien, también puede intentar este animador ViewPropertyAnimator como a continuación

myView.animate().x(50f).y(100f); 

myView.animate().translateX(pixelInScreen) 

Nota: Este píxel no es relativa a la vista. Este píxel es la posición de píxel en la pantalla.

créditos a bpr10 answer

Cuestiones relacionadas