2011-04-25 16 views

Respuesta

39

Encierre su surfaceView con un FrameLayout en su diseño xml. A continuación, agregue sus botones al mismo FrameLayout. Asegúrate de que estén colocados debajo de la vista de la superficie para que se dibujen encima de ella. (Podría ser una buena idea para unirlos en otra disposición y añadir que a la FrameLayout.)

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <SurfaceView android:id="@+id/surfaceView1" android:layout_width="wrap_content" android:layout_height="wrap_content"></SurfaceView> 
    <LinearLayout android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content"> 
     <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> 
     <Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> 
    </LinearLayout> 
</FrameLayout> 
+0

He creado la superficieView programáticamente, pero cómo vincularla con la de XML. – m4n07

+1

Tuve que agregar algo como esto en el xml – m4n07

+0

estoy usando este xml para mi actividad, en la cual desea inicializar la vista de superficie cuando el usuario toque en la vista de la imagen que se personaliza TouchImageView con zoom y pellizcar la funcionalidad de ImageView. Lo que trato de hacer es: (1) muestra la imagen de los servicios web, que he hecho con AQuery. (2) cuando el usuario selecciona la opción EDITAR de los CAB, habilita la vista de superficie con un texto editable que se puede arrastrar sobre la imagen. @androidika me puedes ayudar con esto. –

29

Muchas gracias Androidica ..

Su xml me ha ayudado a entender la siguiente solución programáticamente sin utilizar ningún xml ..

public class LudoActivity extends Activity implements OnClickListener { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 

     FrameLayout game = new FrameLayout(this); 
     GameView gameView = new GameView (this); 
     LinearLayout gameWidgets = new LinearLayout (this); 

     Button endGameButton = new Button(this); 
     TextView myText = new TextView(this); 

     endGameButton.setWidth(300); 
     endGameButton.setText("Start Game"); 
     myText.setText("rIZ..i"); 

     gameWidgets.addView(myText); 
     gameWidgets.addView(endGameButton);  

     game.addView(gameView); 
     game.addView(gameWidgets); 

     setContentView(game); 
     endGameButton.setOnClickListener(this); 
    } 

    public void onClick(View v) { 
     Intent intent = new Intent(this, LudoActivity.class); 
     startActivity(intent); 
     // re-starts this activity from game-view. add this.finish(); to remove from stack 
    } 
} 

mientras GameView es;

public class GameView extends SurfaceView { 

    public GameView(Context context) { 
     super(context); 

     /* 
     * your code 
     */ 
    } 
} 
+0

Muchas gracias por esta versión de código, el XML publicado en la otra respuesta me confundió. –

+0

es mi placer ... eres bienvenido –

3

Podemos usar el diseño de marco para el dibujo de la vista de superficie muy fácilmente. como esta actividad

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
<FrameLayout 
    android:id="@+id/frameLayout" 
    android:layout_width="fill_parent" 
    android:layout_height="430dp"/> 
    <LinearLayout 
     android:layout_width="fill_parent" 
     android:layout_height="50dp" 
     android:gravity="center_horizontal" 
     android:layout_gravity="bottom" 
     android:background="#c2300f"> 

     <Button 
      android:id="@+id/buttonColor" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Color" /> 
    </LinearLayout>  
</LinearLayout> 

Y principal es

package com.example.surfacetuto; 


import android.app.Activity; 
import android.graphics.Paint; 
import android.graphics.Point; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.FrameLayout; 
import android.widget.TextView; 
import android.widget.Toast; 

public class MainActivity extends Activity implements OnClickListener{ 
    DrawingSurface ds; 
    FrameLayout frm; 
    Button btnC; 
    int color=0xfff00000; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ds=new DrawingSurface(this); 
    setContentView(R.layout.activity_main); 


    frm=(FrameLayout)findViewById(R.id.frameLayout); 
    frm.addView(ds); 

    btnC=(Button)findViewById(R.id.buttonColor); 

    btnC.setOnClickListener(this); 
} 
@Override 
public void onClick(View v) { 
    // TODO Auto-generated method stub 
    switch (v.getId()) { 

    case R.id.buttonColor: 
     Toast.makeText(getApplicationContext(), "Color", 2).show(); 
     ds.colorNew(); 

     break; 

    default: 
     break; 
    } 
} 
    } 

Y la clase de dibujo de la superficie es

package com.example.surfacetuto; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Matrix; 
import android.graphics.Paint; 
import android.graphics.Paint.Cap; 
import android.graphics.Rect; 
import android.util.AttributeSet; 
import android.util.DisplayMetrics; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.Window; 
import android.view.WindowManager; 
import android.widget.Toast; 

    public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback { 

     Canvas cacheCanvas; 
     Bitmap backBuffer; 
     int width, height, clientHeight; 
     Paint paint; 
     Context context; 
     SurfaceHolder mHolder; 


public DrawingSurface(Context context) { 
    super(context); 
    this.context = context; 
    init(); 
} 
public DrawingSurface(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    this.context = context;  
    init(); 
} 

private void init() { 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 

} 

int lastX, lastY, currX, currY; 
boolean isDeleting; 
@Override 
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event); 
    int action = event.getAction(); 
    switch(action & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: 
     lastX = (int) event.getX(); 
     lastY = (int) event.getY(); 
     break; 
    case MotionEvent.ACTION_MOVE: 
     if(isDeleting) break; 

     currX = (int) event.getX(); 
     currY = (int) event.getY(); 
     cacheCanvas.drawLine(lastX, lastY, currX, currY, paint); 
     lastX = currX; 
     lastY = currY; 

     break; 
    case MotionEvent.ACTION_UP: 
     if(isDeleting) isDeleting = false; 
     break; 
    case MotionEvent.ACTION_POINTER_DOWN: 
     cacheCanvas.drawColor(Color.WHITE); 
     isDeleting = true; 
     break; 
    case MotionEvent.ACTION_POINTER_UP: 
     break; 
    } 
    draw(); 
    return true; 
} 

protected void draw() { 

    if(clientHeight==0) { 
     clientHeight = getClientHeight(); 
     height = clientHeight; 
     backBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
     cacheCanvas.setBitmap(backBuffer); 
     cacheCanvas.drawColor(Color.WHITE); 
    } 
    Canvas canvas = null; 
    try{ 
     canvas = mHolder.lockCanvas(null); 

     canvas.drawBitmap(backBuffer, 0,0, paint); 
    }catch(Exception ex){ 
     ex.printStackTrace(); 
    }finally{ 
     if(mHolder!=null) mHolder.unlockCanvasAndPost(canvas); 
    } 
} 

private int getClientHeight() { 
    Rect rect= new Rect();  
    Window window = ((Activity)context).getWindow();  
    window.getDecorView().getWindowVisibleDisplayFrame(rect);  
    int statusBarHeight= rect.top;  
    int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();  
    int titleBarHeight= contentViewTop - statusBarHeight; 
    return ((Activity)context).getWindowManager().getDefaultDisplay(). 
      getHeight() - statusBarHeight - titleBarHeight; 
} 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
} 

public void surfaceCreated(SurfaceHolder holder) { 

    width = getWidth(); 
    height = getHeight(); 
    cacheCanvas = new Canvas(); 
    backBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    cacheCanvas.setBitmap(backBuffer); 
    cacheCanvas.drawColor(Color.WHITE); 
    paint = new Paint(); 
    paint.setColor(Color.BLUE); 
    paint.setStrokeWidth(10); 
    paint.setStrokeCap(Paint.Cap.ROUND); 
    paint.setStrokeJoin(Paint.Join.ROUND); 
    draw(); 

} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    boolean retry = true; 
     thread.setRunning(false); 
     while (retry) { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // we will try it again and again... 
      } 
     } 
} 

public void colorNew() { 
    // TODO Auto-generated method stub 
    paint.setColor(Color.GRAY); 
} 


    } 
7

Haga su propio botón:

import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.RectF; 

    public class GButton 
    { 
     public Matrix btn_matrix = new Matrix(); 

     public RectF btn_rect; 

     float width; 
     float height; 
     Bitmap bg; 

     public GButton(float width, float height, Bitmap bg) 
     { 
      this.width = width; 
      this.height = height; 
      this.bg = bg; 

      btn_rect = new RectF(0, 0, width, height); 
     } 

     public void setPosition(float x, float y) 
     { 
      btn_matrix.setTranslate(x, y); 
      btn_matrix.mapRect(btn_rect); 
     } 

     public void draw(Canvas canvas) 
     { 
      canvas.drawBitmap(bg, btn_matrix, null); 
     } 
    } 

en caso de contacto:

float x = ev.getX(); 
float y = ev.getY(); 
if (my_button.btn_rect.contains(x, y)) 
{ 
    // handle on touch here 
} 

alternativamente, aún mejor, si quieres también girar el botón no será ejes alineados, a continuación, utilizar la matriz invertida, en lugar de mapRect mapa los puntos de contacto con x, y:

float pts[] = {x, y};    
my_button.invert_matrix.mapPoints(pts);   
if (my_button.btn_rect.contains(pts[0], pts[1]) 
{ 
    // handle on touch here 
} 
+0

gracias por tu código, espero que me ayude. –

+0

Gracias, ¡me funciona! –

+0

Me gustaría ver una publicación en algún lugar que compare las ventajas de hacer los propios botones de esta manera para una vista de superficie versus usar el objeto de botón del widget de botón como en la respuesta de gruemeen4. Recientemente cambié mis propios botones personalizados en mi código de juego a objetos Button, y parece que no funciona tan bien para los clics. – Androidcoder

Cuestiones relacionadas