【问题标题】:Android:How to add a button in surface viewAndroid:如何在表面视图中添加按钮
【发布时间】:2011-08-12 08:40:04
【问题描述】:

我正在绘制一些图形,我想在其中添加几个按钮。但是对于表面视图,我们如何以编程方式添加这些按钮?

【问题讨论】:

    标签: android surfaceview


    【解决方案1】:

    在您的 xml 布局中使用 FrameLayout 将您的 surfaceView 括起来。然后将您的按钮添加到相同的 FrameLayout。确保将它们放置在表面视图下方,以便将它们绘制在其顶部。 (将它们捆绑在另一个布局中并将其添加到 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>
    

    【讨论】:

    • 我以编程方式创建了surfaceView,但是如何与XML中的那个链接。
    • 我不得不在xml中添加这样的东西
    • 我正在将此 xml 用于我的活动,其中我想在用户点击 imageview 时初始化 surfaceview,这是自定义的 TouchImageView,具有缩放和捏合功能到 ImageView。我想要做的是 - (1)它显示来自网络服务的图像,我已经用 AQuery 完成了。 (2) 当用户选择 CAB 的 EDIT 选项时,它会在图像上启用带有可拖动编辑文本的表面视图。 @androidika 你能帮我解决这个问题吗?
    【解决方案2】:

    非常感谢 Androidica..

    您的 xml 帮助我在不使用任何 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
        }
    }
    

    而 GameView 是;

    public class GameView extends SurfaceView {
    
        public GameView(Context context) {
            super(context);
    
            /*
             * your code
             */
        }
    }
    

    【讨论】:

    • 非常感谢这个代码版本,另一个答案中发布的 XML 让我很困惑。
    【解决方案3】:

    我们可以很容易地使用框架布局来绘制表面视图。 像这样

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

    主要活动是

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

    而绘图表面类是

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

    【讨论】:

      【解决方案4】:

      制作自己的按钮:

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

      触摸事件:

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

      或者,更好的是,如果您还想旋转按钮,它不会轴对齐,然后使用反转矩阵,而不是 mapRect 映射触摸点 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
      }
      

      【讨论】:

      • 我想在某个地方看到一篇文章,比较以这种方式为表面视图制作自己的按钮与使用按钮小部件中的 Button 对象(如 gruemeen4 的答案)的优点。我最近将我的游戏代码中所有我自己的自定义按钮都更改为 Button 对象,但它似乎在点击时表现不佳。
      • 如果你使用的是surfaceview,你应该在上面画你的东西,包括按钮。意味着你没有使用标准的布局和小部件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-11
      • 2014-01-06
      • 1970-01-01
      • 2017-02-23
      • 2017-07-16
      相关资源
      最近更新 更多