`
158067568
  • 浏览: 329033 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

自定义控件(SurfaceView与view结合)

阅读更多

 

自定义控件(SurfaceViewview结合)

作者:Legend

QQ158067568

上一节小试牛刀,介绍了一个简单的SurfaceView的例子,如果用于实际开发,那还差得远呢。本节介绍SurfaceViewView结合使用的例子,SurfaceView部分与球类稍作改动,这里就不在赘述。主要介绍一下如何在View中成功的把SurfaceView添加进来,并且通过widget中默认的控件来操作自定义的SurfaceView

View中添加SurfaceView

还记得我上一节中的SurfaceViewBallSurfaceView的构造方法么?BallSurfaceView(Context context)没错就是这个,但是如果我们要在view中添加,还是用这个构造方法就会报错。感谢mars老师的Android群,里面的大虾们帮我解决了这个问题。

其实只要使用如下构造方法,然后注意几点就ok了。

      

public BallSurfaceView(Context context, AttributeSet attrs) {
		super(context,attrs);
		…..
 

就是上面的构造方法,是符合view的。AttributeSet是提供一些设置的类,可以参考API

但是值得注意的是,不要再SurfaceView中去绑定View,这样会带来意想不到的错误。

实现

我将把代码全部贴出,供大家参考。

 

package cn.edu.heut.zcl;
 
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
 
public class BallSurfaceView extends SurfaceView
implements SurfaceHolder.Callback{
//       SportActivity sportActivity ;//调用该SurfaceView的上下文引用
         private Ball ball ;//小球
         public static final int initX = 100;
         public static final int initY = 100;
         SurfaceHolder holder ;
         public int screenWidth ;
         public int screenHeight ;
         public BallSurfaceView(Context context, AttributeSet attrs) {
                   super(context,attrs);
                   ball = new Ball(initX, initY, this);
                   holder = this.getHolder();
                   holder.addCallback(this);
                     //获得屏幕尺寸
        DisplayMetrics dm = new DisplayMetrics();
    dm = context.getApplicationContext().getResources().getDisplayMetrics();
              screenWidth = dm.widthPixels;
              screenHeight = dm.heightPixels;
         }
 
         @Override
         protected void onDraw(Canvas canvas) {
                   super.onDraw(canvas);
                  
                   if(canvas == null) canvas = holder.lockCanvas();//锁定画布
                   Paint p = new Paint();
                   int c = p.getColor();
                   p.setColor(Color.WHITE);//设置背景白色
                   if(canvas != null)
                   canvas.drawRect(0, 0, screenWidth, screenHeight, p);
                   p.setColor(c);
                   ball.onDraw(canvas);
                   holder.unlockCanvasAndPost(canvas);//释放锁
         }
 
         @Override
         public void surfaceChanged(SurfaceHolder holder, int format, int width,
                            int height) {
                  
         }
 
         @Override
         public void surfaceCreated(SurfaceHolder holder) {
                   new RefreshThread().start();
         }
 
         @Override
         public void surfaceDestroyed(SurfaceHolder holder) {
                  
         }
        
         public void setStop(){
                   ball.setStop(true);
         }
         public void setStart(){
                   ball.setStop(false);
         }
         public void setRestart(){
                   ball.setPosition(initX, initY);
                   ball.setMaxHeight(initY);
         }
         private class RefreshThread extends Thread{
 
                   @Override
                   public void run() {
 
                            while(true){
                                     Canvas canvas = null;
                                     try{
                                               onDraw(canvas);
                                     }catch(Exception e){
                                               e.printStackTrace();
                                     }
                                    
                                     try {
                                               Thread.sleep(40);
                                     } catch (InterruptedException e) {
                                               e.printStackTrace();
                                     }
                            }
                   }
                  
         }
        
}
 
 
package cn.edu.heut.zcl;
 
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
 
/**
 * 球类
 * @author zcl
 *
 */
public class Ball {
          
         /**
          * 球的高
          */
         public static final int HEIGHT = 93;
         /**
          * 球的宽
          */
         public static final int WIDTH = 93;
 
         private static final int STEPLENGTH = 10;//每次运动的间距
         private static final float REDUCEPERCENTAGE =  0.35F;//递减系数
         private int stepReduce ;//每次反向运动的缩短的距离
        
         private boolean stop = false;
        
         public void setStop(boolean stop) {
                   this.stop = stop;
         }
         private float runX ;//球的位置
         private float runY ;//球的位置
         private BallSurfaceView bsv ;
         private boolean upDirection = false;//if true,up direction,or is down direction
         private float maxHeight ;//当前运动最高的高度
         private Paint paint ;
        
         Bitmap ballBitmap ;//球的图片
         public Ball(float initX , float initY , BallSurfaceView bsv){
                   this.runX  = initX;
                   this.runY = initY ;
                   maxHeight = initY;
                   this.bsv = bsv;
                   ballBitmap = BitmapFactory.decodeResource(bsv.getResources(), R.drawable.ball);//加载图片
                   paint = new Paint();
         }
        
         public void onDraw(Canvas canvas) {
                   int c = paint.getColor();//保存颜色,之后还原为之前颜色
                   if( !stop ) boundaryTest();
                   if(canvas != null) canvas.drawBitmap(ballBitmap,runX,runY,paint);
                   paint.setColor(c);
                   if( !stop ) move();
         }
         /**
          * 运动
          */
         private void move() {
                   if(maxHeight >= (bsv.screenHeight - HEIGHT)) {
                            return;
                   }
                   if(upDirection){//向上
                            runY = runY + STEPLENGTH ;
                   }else{
                            runY = runY - STEPLENGTH ;
                   }
         }
 
         /**
          * 边界检测,使球不会飞出边界
          */
         private void boundaryTest(){
 
                   if(runY > bsv.screenHeight - HEIGHT){//向下运动到头
                            upDirection = !upDirection;//方向置反
                            runY = bsv.screenHeight - HEIGHT;
                            stepReduce = (int) (maxHeight * REDUCEPERCENTAGE);
                            maxHeight = maxHeight + stepReduce ;//最大高度递减
                           
                   }
                   if(runY < maxHeight ){//向上运动到头
                            upDirection = !upDirection;//方向置反
                            if(maxHeight >= (bsv.screenHeight - HEIGHT)) return;
                            runY = maxHeight ;
                           
                   }
         }
         public void setPosition(float x,float y){
                   this.runX = x;
                   this.runY = y;
         }
         public void setMaxHeight(float y){
                   this.maxHeight = y;
         }
}
 
 
package cn.edu.heut.zcl;
 
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
 
public class SportActivity extends Activity {
        
         Button butStop;
         Button butStart;
         Button butRestart;
        
         BallSurfaceView bsv ;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        bsv = new BallSurfaceView(this);
            //下两句为设置全屏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
                   getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , 
                                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
       
        setContentView(R.layout.main);
        butStop =(Button)findViewById(R.id.butStop);
        butStop.setOnClickListener(new listener());
        butStart =(Button)findViewById(R.id.butStart);
        butStart.setOnClickListener(new listener());
        butRestart =(Button)findViewById(R.id.butRestart);
        butRestart.setOnClickListener(new listener());
        bsv = (BallSurfaceView) findViewById(R.id.ballSurfaceView);
    }
    class listener implements View.OnClickListener{
 
                   @Override
                   public void onClick(View v) {
                            Button but = (Button)v;
                            switch(but.getId()){
                            case R.id.butStop:
                                     bsv.setStop();
                                     break;
                            case R.id.butStart:
                                     bsv.setStart();
                                     break;
                            case R.id.butRestart:
                                     bsv.setRestart();
                                     break;
                            }
                           
                   }
   
    }
   
}
 
 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >
    <Button android:id="@+id/butStop"
    android:text="stop"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    >
    </Button>
    <Button android:id="@+id/butStart"
    android:text="Start"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    >
    </Button>
    <Button android:id="@+id/butRestart"
    android:text="ReStart"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    >
    </Button>
    </LinearLayout>
    <FrameLayout
       android:layout_width="fill_parent"
       android:layout_height="wrap_content">
       <cn.edu.heut.zcl.BallSurfaceView
           android:id="@+id/ballSurfaceView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
       </cn.edu.heut.zcl.BallSurfaceView>
    </FrameLayout>
</LinearLayout>
 

 

有问题的留言,篮球运动是直接修改的上一节的例子,需要代码的留下邮箱。

 

 

2
1
分享到:
评论
16 楼 小鱼小鹰 2014-09-10  
现在还能吗。。。296252344@qq.com
15 楼 再_见孙悟空 2014-01-21  
这个应该跑不动的,SurfaceView对象根本就获取不到
14 楼 valvekim 2013-06-14  
楼主, 8881816@163.com. 感谢.
13 楼 我de专属doll 2012-11-01  
  private void move() { 
162.                   if(maxHeight >= (bsv.screenHeight - HEIGHT)) { 
163.                            return; 
164.                   } 
165.                   if(upDirection){//向上 
166.                            runY = runY + STEPLENGTH ; 
167.                   }else{ 
168.                            runY = runY - STEPLENGTH ; 
169.                   } 
170.         } 
171.  


这段逻辑 没问题吗?如果方向为真的话  是向上运动 ,为什么球的位置还要加呢 ,不是该减了?求解答
12 楼 我de专属doll 2012-11-01  
18638140959@126.com 希望楼主给我发一份源码 谢谢  打成jar包也行  只要能跑起来[color=red][/co[size=small][/size]lor]
11 楼 罗幕轻寒 2012-10-08  
gooole.hi@gmail.com  谢谢大神
10 楼 sxd616616 2012-08-22  
sxd616616@163.com 楼主无私!感谢
9 楼 Awen134 2012-02-27  
awenyini@foxmail.com
8 楼 czxj2003 2011-12-08  
哈。多谢了。根据上面代码调试出来了。。
7 楼 czxj2003 2011-12-08  
czxj2003@yahoo.com.cn
试了你贴出来的代码,没有成功。请给我一份。。。
6 楼 natepan 2011-11-26  
希望给一个源码,327263944@qq.com,谢谢!
5 楼 jing_wang_2011 2011-11-03  
634069490@qq.com
哥们麻烦给我一份啊
4 楼 jing_wang_2011 2011-11-03  
634069490@qq.com
哥们麻烦给我一份啊
3 楼 jing_wang_2011 2011-11-03  
634069490@qq.com
哥们麻烦给我一份啊
2 楼 sunjunliangsunjun 2011-10-17  
565426086@qq.com
1 楼 sunjunliangsunjun 2011-10-17  
哥们呢  麻烦 给我发一份能跑起来的代码   Thank u !

相关推荐

    android 自定义控件 小球圆周运动

    自定义控件通常是通过继承`View`或`ViewGroup`类来实现的。在这个案例中,我们可以选择直接继承`View`,因为我们的目标是绘制单一的小球,而不是管理多个子视图。 1. **创建自定义View** - 创建一个新的Java类,...

    一种代替SurfaceView的自定义控件,可以缩放、无限延伸拖动

    这种自定义控件的设计思路是基于Android的View或者 ViewGroup 进行扩展,并结合手势识别技术来实现这些高级交互。 首先,我们要理解Android中的View和ViewGroup。View是Android UI的基本元素,它负责绘制和事件处理...

    自定义控件 短视频录制控件 列表选择 圆形图片 条形控件

    本文将深入探讨如何基于Android平台实现自定义控件,包括短视频录制控件、列表选择、圆形图片和条形控件的设计与实现。 首先,让我们关注短视频录制控件。在当今社交媒体盛行的时代,短视频分享功能成为许多应用...

    在surfaceview上放置控件

    在提供的`MySurfaceTest`文件中,可能包含了实现这一功能的示例代码,包括SurfaceView的自定义类、布局文件以及相关的触摸事件处理和按钮事件监听。你可以通过查看这些文件,进一步理解如何在SurfaceView上添加和...

    android 自定义view之进度条(混合模式)

    2. **进度条原理**:Android原生提供了ProgressBar控件,但这里的自定义进度条需要更复杂的逻辑。它不仅需要追踪和显示进度,还需要处理与文字的混合模式交互。进度条的更新通常通过`setProgress()`方法实现,而动画...

    android自定义控件贝塞尔曲线

    本篇将深入探讨如何在Android中实现自定义控件以绘制贝塞尔曲线,特别是结合SurfaceView的使用。 首先,了解贝塞尔曲线的基本概念。贝塞尔曲线由控制点和基多项式构成,分为线性、二次和三次等不同阶数。在Android...

    用SurfaceView自定义时钟

    `Surface`是实际进行绘图的地方,而`View`则负责处理布局和与用户交互。通常,我们会在`SurfaceView`的子类中创建一个后台线程,这个线程负责在`Surface`上绘制内容。 1. **创建自定义SurfaceView子类**: 创建一...

    Android源码——SurfaceView添加组件view不被组件覆盖.zip

    3. 使用`ViewGroup`:将SurfaceView和其他View放在同一个自定义的`ViewGroup`中,通过重写`onLayout()`方法来控制子视图的布局。在该方法中,我们可以精确地指定每个子视图的位置,确保它们不会被SurfaceView覆盖。 ...

    Android 自定义地图控件,可放大缩小拖动,加点加线

    自定义地图控件通常涉及到对View或SurfaceView的扩展,通过重写其onTouchEvent等方法,实现手势识别,从而实现地图的移动和缩放。 在该项目中,`MyMapView`可能是自定义地图控件的类名,它继承自Android的View或...

    android SurfaceView 使用示例 why SurfaceView上 不可以用控件的轻微解释

    3. 自定义控件:如果你需要在SurfaceView上实现特定的交互,可以考虑创建自定义View,这个View继承自SurfaceView,并在其内部处理触摸事件和绘图。 4. 使用Layout嵌套:可以将SurfaceView和控件放入一个单独的...

    android中surfaceview控件的使用范例

    SurfaceView通常配合一个自定义的Thread(如GameThread)来实现后台绘图。在`surfaceCreated()`方法中启动线程,在`surfaceDestroyed()`方法中关闭线程。在`surfaceChanged()`方法中,可以根据Surface的新尺寸调整...

    动画柱状图

    在Android开发中,自定义控件(Custom View)是一个强大的工具,允许开发者根据需求定制界面元素,这里我们将深入探讨如何使用自定义控件SurfaceView来创建动画柱状图。 首先,我们要了解**自定义控件**的概念。在...

    surfaceView控件资料

    它的工作原理与普通的View不同,SurfaceView拥有一个独立的Surface,这个Surface位于应用程序窗口的最上方,直接与硬件图形渲染管道交互,从而减少了UI线程的负担,提升了性能。 1. SurfaceView的基础概念: - ...

    Android 刮刮卡效果 自定义控件实现

    本篇将详细介绍如何在Android中自定义控件实现刮刮卡效果。 首先,刮刮卡效果的核心在于一个可被用户“刮掉”的覆盖层。这个覆盖层通常是颜色较深的一层,当用户进行手势操作时,会逐渐露出底层的颜色或图像。为了...

    android图像绘制(四)自定义一个SurfaceView控件

    在Android开发中,自定义控件能够满足开发者对界面及交互的特殊需求。本文将深入讲解如何自定义一个`SurfaceView`控件,以便实现特定的动态图像展示或类似UC浏览器底部工具栏的效果。 `SurfaceView`是Android系统...

    SurfaceView实例源代码

    通过customView1404_03SurfaceView这个示例,你可以看到如何在实际项目中创建和使用自定义的SurfaceView控件。这个简单的demo可能包括创建一个基本的SurfaceView,设置背景颜色,以及在Surface上绘制简单的图形,...

    安卓手绘图片处理画板相关-Android签名控件手写自定义的控件.rar

    本资源"安卓手绘图片处理画板相关-Android签名控件手写自定义的控件.rar"提供了一个针对这一需求的自定义控件实现。下面我们将深入探讨这个主题,讲解如何在Android中实现手绘图片处理和签名控件。 首先,自定义...

    Android自定义控件实现手势密码

    ...本以为这个东西很简单,实际上手的时候发现,还有很多逻辑需要处理,稍不注意就容易乱套。写个UI效果图大约只花了... 1、整个自定义控件是继承View还是SurfaceView呢?我的经验告诉我:需要一直不断绘制的最好继承Sur

    Android游戏开发学习(5)--实现Button悬浮于与SurfaceView之上

    在Android游戏开发中,将一个`Button`控件悬浮于`SurfaceView`之上是一项常见的需求。这通常是为了解决在游戏界面中添加交互元素,如暂停、设置或返回按钮,以便用户可以随时进行操作。本篇文章将深入探讨如何实现这...

Global site tag (gtag.js) - Google Analytics