无法显示2实例我自定义的SurfaceView [英] Cannot Display 2 Instances of my custom SurfaceView

查看:218
本文介绍了无法显示2实例我自定义的SurfaceView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建自己的自定义SurfaceView工作正常自身但是当我试图把两个到单独的选项卡中的 TabWidget 的只有一个无论哪个选项卡的要求不断示出被选择,它始终是SurfaceView其首先时绘制的应用程序启动。

要说明,我创建样本code可以编译,显示为问题的问题。

下面的SurfaceView,叫SurfaceViewCircle简单地创建一个位图,绘制一个蓝色圆圈为默认值,然后显示它。有一个公共的方法,changeColour(),这将改变位图中的圆圈的颜色。

其次,我创建一个XML布局其中只包含SurfaceViewCircle的一个实例。

在活动类,我创建了一个TabWidget和主机等。然后我吹上面的XML两次,但在一种情况下我的SurfaceViewCircle的颜色变为红色。一旦应用程序运行时,无论是什么标签我选择,红圈是始终显示,除了显示应用程序退出和蓝色的圆圈,当一个简短的实例。

任何人都可以指出,如果我错过了一个步骤中,使用SurfaceView什么时候?

这是活动code:

 公共类TestActivity延伸活动{
/ **第一次创建活动时调用。 * /

私人TabHost mTab​​Host;
私人语境mTabHostContext;
私人查看surfaceView1,surfaceView2;
@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);

    / *
     *设置选项卡
     * /
    的setContentView(R.layout.maintabs);
        setupTabHost(); //从code,而不是XML prepares的TabHost;
    。mTabHost.getTabWidget()setDividerDrawable(R.drawable.tab_divider); //设置一个细细的分界线
    mTabHostContext = mTab​​Host.getContext();
    surfaceView1 = LayoutInflater.from(mTabHostContext).inflate(R.layout.surfaceviewindependent,NULL);
    SurfaceViewCircle S =(SurfaceViewCircle)surfaceView1.findViewById(R.id.circle1);
    / *
     *更改颜色为红色
     * /
    s.changeColour(getResources()的getColor(R.color.red_square));

    / *
     *创建一个包含SurfaceViewCircle第二的布局,但保留圈为默认的蓝色。
     * /
    surfaceView2 = LayoutInflater.from(mTabHostContext).inflate(R.layout.surfaceviewindependent,NULL);
    setupTab(surfaceView1SurfaceView1);
    setupTab(surfaceView2SurfaceView2);


}

私人无效setupTabHost(){
    mTabHost =(TabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup();
}

私人无效setupTab(最终视图中查看,最终字符串变量){
    查看TabView的= createTabView(mTabHost.getContext(),标签); //这将创建一个视图选项卡中的使用只

    / *此创建选项卡的内容和应用在previous一步创建的TAB一气呵成* /
    则tabspec setContent = mTab​​Host.newTabSpec(标签).setIndicator(TabView的).setContent(新TabContentFactory(){
        公共查看createTabContent(字符串标签){返回查看;}
    });
    mTabHost.addTab(setContent);

}

私有静态视图createTabView(最终上下文的背景下,最终的文本字符串){
    查看查看= LayoutInflater.from(上下文).inflate(R.layout.tabs_bg,NULL);
    TextView的电视=(TextView中)view.findViewById(R.id.tabsText);
    tv.setText(文本);

    返回查看;
}
}
 

这是我自定义的SurfaceView:

 公共类SurfaceViewCircle扩展了SurfaceView实现SurfaceHolder.Callback {

私人油漆涂料,circlePaint;
私人位图位= NULL;
私人诠释瓦;
私人诠释H;
私人诠释色= 0;
私人资源R = NULL;
私人_Thread T = NULL;
私人布尔surfaceIsCreated;

公共SurfaceViewCircle(上下文的背景下){
    超(上下文);
    初始化();
}

公共SurfaceViewCircle(上下文的背景下,ATTRS的AttributeSet){
    超(背景下,ATTRS);
    初始化();
}

公共SurfaceViewCircle(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
    超(背景下,ATTRS,defStyle);
    初始化();
}

私人无效INITIALISE(){
    R = getResources();
    。getHolder()的addCallback(本);
    油漆=新的油漆(Paint.ANTI_ALIAS_FLAG);
    paint.setFilterBitmap(真正的);
    颜色= R.color.blue_square;
    circlePaint =新的油漆(Paint.ANTI_ALIAS_FLAG);
    circlePaint.setColor(r.getColor(颜色));
    circlePaint.setStyle(Style.FILL);
    circlePaint.setStrokeWidth(0.02f);
    T =新_Thread(getHolder());


}

公共无效changeColour(INT颜色){
    circlePaint.setColor(颜色);
    如果(surfaceIsCreated){
        createBitmap();
    }
    同步(T){
        t.notify();
    }
}

私人位图createBitmap(){
    位图B = NULL;
    B = Bitmap.createBitmap(W,H,Bitmap.Config.ARGB_8888);
    帆布C =新的Canvas(B);
    c.scale((浮点)W,(浮动)W); //缩放背景无论像素大小
    c.drawCircle(0.5F,0.5F,0.5F,circlePaint);
    //c.drawColor(r.getColor(colour));
    返回b;
}

公共无效onMeasure(INT widthMeasureSpec,诠释heightMeasureSpec){
    INT宽度=措施(widthMeasureSpec);
    INT高=措施(heightMeasureSpec);

    INT D = Math.min(宽度,高度);
    setMeasuredDimension(D,D);
}

私人诠释措施(INT measureSpec){
    INT结果为0;
    //德$ C C的测量规范$
    INT specMode = MeasureSpec.getMode(measureSpec);
    INT specSize = MeasureSpec.getSize(measureSpec);

    返回specSize;
}

@覆盖
保护无效onSizeChanged(INT W,INT小时,INT oldW,诠释oldH){
    super.onSizeChanged(W,H,oldW,oldH);
    //同步(本){
        this.w = Math.min(W,H);
        this.h = W;
    //}
    位图B = createBitmap();

        位= B;

    Log.i(广场,onSizeChanged()调用。);


}
@覆盖
公共无效surfaceChanged(SurfaceHolder持有人,INT格式,诠释的宽度,
        INT高度){
    // TODO自动生成方法存根

}

@覆盖
公共无效surfaceCreated(SurfaceHolder持有者){
    Log.i(面板,surfaceCreated()调用。);
    t.se​​tRunning(真正的);
    t.start();
    surfaceIsCreated = TRUE;

}

@覆盖
公共无效surfaceDestroyed(SurfaceHolder持有者){
    Log.i(广场,surfaceDestroyed()调用。);

    surfaceIsCreated = FALSE;
    布尔重试= TRUE;
    同步(T){
        t.se​​tRunning(假);
        t.notify();
    }
    而(重试){
        尝试 {
            t.join();
            重试= FALSE;
        }赶上(InterruptedException异常E){
            //我们会一次又一次地尝试...
        }
    }

}

私有类_Thread继承Thread {
    私人SurfaceHolder _surfaceHolder;
    私人布尔_run = FALSE;

    公共_Thread(SurfaceHolder surfaceHolder){
        _surfaceHolder = surfaceHolder;
    }

    公共无效setRunning(布尔运行){
        _run =运行;
    }

    @覆盖
    公共无效的run(){
        帆布C = NULL;
        而(_run){
            尝试 {
                C = _surfaceHolder.lockCanvas(空);
                同步(_surfaceHolder){
                    同步(位图){
                        c.drawBitmap(位图,0,0,油漆);
                    }
                }
            } 最后 {
                //这样做的最后,这样,如果抛出一个异常
                //上面的过程中,我们不留在表面
                //不一致的状态
                如果(C!= NULL){
                    _surfaceHolder.unlockCanvasAndPost(C);
                }
            }
            同步(本){
                尝试 {
                    等待();
                }赶上(InterruptedException异常E){
                    // TODO自动生成的catch块

                }
            }
        }
    }
}
}
 

该maintabs.xml文件:

 < XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
机器人:方向=垂直机器人:layout_width =FILL_PARENT
机器人:layout_height =FILL_PARENT>
< TabHost的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@机器人:ID / tabhost机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT>
    <的LinearLayout机器人:方向=垂直
        机器人:layout_width =FILL_PARENT机器人:layout_height =FILL_PARENT>
        < TabWidget机器人:ID =@机器人:ID /标签
            机器人:layout_width =FILL_PARENT机器人:layout_height =WRAP_CONTENT
            机器人:layout_marginLeft =0dip机器人:layout_marginRight =0dip/>
            <的FrameLayout机器人:ID =@机器人:ID / tabcontent
            机器人:layout_width =FILL_PARENT机器人:layout_height =FILL_PARENT/>
    < / LinearLayout中>
    < / TabHost>
< / LinearLayout中>
 

而surfaceviewindependent.xml:

 < XML版本=1.0编码=UTF-8&GT?;
<的LinearLayout
  的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
  机器人:方向=垂直
  机器人:layout_width =match_parent
  机器人:layout_height =match_parent>
< uk.co.androidcontrols.gauges.SurfaceViewCircle
机器人:ID =@ + ID / circle1添加
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:layout_weight =0.5
    机器人:layout_margin =1dip>
< /uk.co.androidcontrols.gauges.SurfaceViewCircle>
< / LinearLayout中>
 

我还注意到,其他人遇到过类似的问题这里。

抱歉穷人的格式,但code编辑器是几乎不可能用于大型code报价!

其他信息

我尝试使用 setVisibility() onvisibilityChanged(),但它最终导致异常:

 保护无效onVisibilityChanged(查看changedView,INT可见性){
    super.onVisibilityChanged(changedView,可见性);
    changedView.setVisibility(知名度);
    Log.i(SurfaceViewCircle,onVisibilityChanged()调用。);
}

java.lang.IllegalThreadStateException:线程已经启动。
 

这似乎叫 changedView.setvisibility()每次破坏表面。

解决方案

看起来像什么,我想要做SurfaceView不建议:的

I've created my own custom SurfaceView which works fine on its own but when I try putting two onto separate tabs in a TabWidget only one is ever shown regardless of which tab is selected, and it is always the SurfaceView which is first drawn when the app starts.

To illustrate the problem I have created sample code which can be compiled to display to problem.

The SurfaceView below, called SurfaceViewCircle simply creates a bitmap, draws a blue circle as default and then displays it. There is a public method, changeColour(), which will change the circle colour in the bitmap.

Secondly, I create an XML layout which simply contains a single instance of SurfaceViewCircle.

In the Activity class, I create a TabWidget and host etc. I then inflate the above XML twice but in one instance I change the colour of the SurfaceViewCircle to red. Once the application runs, no matter what tab I select, the red circle is ALWAYS shown EXCEPT for a brief instance when the app exits and the blue circle is displayed.

Can anyone point out if I have missed out a step when using SurfaceView?

This is the Activity code:

public class TestActivity extends Activity  {
/** Called when the activity is first created. */

private TabHost mTabHost;
private Context mTabHostContext;
private View surfaceView1, surfaceView2;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /*
     * Setup tabs
     */
    setContentView(R.layout.maintabs);
        setupTabHost(); //Prepares the TabHost from code rather than XML;
    mTabHost.getTabWidget().setDividerDrawable(R.drawable.tab_divider); //Sets a thin dividing line
    mTabHostContext = mTabHost.getContext();
    surfaceView1 = LayoutInflater.from(mTabHostContext).inflate(R.layout.surfaceviewindependent, null);
    SurfaceViewCircle s = (SurfaceViewCircle)surfaceView1.findViewById(R.id.circle1);
    /*
     * Change the colour to red
     */
    s.changeColour(getResources().getColor(R.color.red_square));

    /*
     * Create a second layout containing SurfaceViewCircle but leave circle as default blue.
     */
    surfaceView2 = LayoutInflater.from(mTabHostContext).inflate(R.layout.surfaceviewindependent, null);
    setupTab(surfaceView1,"SurfaceView1");
    setupTab(surfaceView2,"SurfaceView2");


}

private void setupTabHost() {
    mTabHost = (TabHost) findViewById(android.R.id.tabhost);
    mTabHost.setup();
}

private void setupTab(final View view, final String tag) {
    View tabview = createTabView(mTabHost.getContext(), tag); // This creates a view to be used in the TAB only

    /* this creates the tab content AND applies the TAB created in the previous step in one go */
    TabSpec setContent = mTabHost.newTabSpec(tag).setIndicator(tabview).setContent(new TabContentFactory() {
        public View createTabContent(String tag) {return view;}
    });
    mTabHost.addTab(setContent);

}

private static View createTabView(final Context context, final String text) {
    View view = LayoutInflater.from(context).inflate(R.layout.tabs_bg, null);
    TextView tv = (TextView) view.findViewById(R.id.tabsText);
    tv.setText(text);

    return view;
}   
}

This is my custom SurfaceView:

public class SurfaceViewCircle extends SurfaceView implements SurfaceHolder.Callback{

private Paint paint, circlePaint;
private Bitmap bitmap = null;
private int w;
private int h;
private int colour = 0;
private Resources r = null;
private _Thread t = null;
private boolean surfaceIsCreated;

public SurfaceViewCircle(Context context) {
    super(context);
    initialise();
}

public SurfaceViewCircle(Context context, AttributeSet attrs) {
    super(context, attrs);
    initialise();
}

public SurfaceViewCircle(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initialise();
}

private void initialise(){
    r = getResources();
    getHolder().addCallback(this);
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setFilterBitmap(true);
    colour = R.color.blue_square;
    circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    circlePaint.setColor(r.getColor(colour));
    circlePaint.setStyle(Style.FILL);
    circlePaint.setStrokeWidth(0.02f);
    t = new _Thread(getHolder());


}

public void changeColour(int colour){
    circlePaint.setColor(colour);
    if (surfaceIsCreated){
        createBitmap();
    }
    synchronized (t){
        t.notify();
    }
}

private Bitmap createBitmap(){
    Bitmap b = null;
    b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.scale((float)w, (float)w);        //Scales the background for whatever pixel size
    c.drawCircle(0.5f, 0.5f, 0.5f, circlePaint);
    //c.drawColor(r.getColor(colour));
    return b;
}

public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    int width = measure(widthMeasureSpec);
    int height = measure(heightMeasureSpec);

    int d = Math.min(width, height);
    setMeasuredDimension(d,d);
}

private int measure(int measureSpec) {
    int result = 0;
    // Decode the measurement specifications
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    return specSize;
}

@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH){
    super.onSizeChanged(w, h, oldW, oldH);
    //synchronized (this){
        this.w = Math.min(w, h);
        this.h = w;
    //}
    Bitmap b = createBitmap();

        bitmap = b;

    Log.i("Square", "onSizeChanged() called.");


}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.i("Panel", "surfaceCreated() called.");
    t.setRunning(true);
    t.start();
    surfaceIsCreated = true;

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.i("Square", "surfaceDestroyed() called.");

    surfaceIsCreated = false;
    boolean retry = true;
    synchronized (t){
        t.setRunning(false);
        t.notify();
    }
    while (retry) {
        try {
            t.join();
            retry = false;
        } catch (InterruptedException e) {
            // we will try it again and again...
        }
    }

}

private class _Thread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private boolean _run = false;

    public _Thread(SurfaceHolder surfaceHolder) {
        _surfaceHolder = surfaceHolder;
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    @Override
    public void run() {
        Canvas c = null;
        while (_run){
            try {
                c = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {
                    synchronized(bitmap){
                        c.drawBitmap(bitmap, 0, 0, paint);
                    }
                }
            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
            synchronized(this){
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block

                }
            }
        }
    }
}
}

The maintabs.xml file:

<?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">
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout android:orientation="vertical"
        android:layout_width="fill_parent" android:layout_height="fill_parent">
        <TabWidget android:id="@android:id/tabs"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:layout_marginLeft="0dip" android:layout_marginRight="0dip" />
            <FrameLayout android:id="@android:id/tabcontent"
            android:layout_width="fill_parent" android:layout_height="fill_parent" />
    </LinearLayout>
    </TabHost>
</LinearLayout>

And the surfaceviewindependent.xml:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
<uk.co.androidcontrols.gauges.SurfaceViewCircle
android:id="@+id/circle1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="0.5"
    android:layout_margin="1dip">
</uk.co.androidcontrols.gauges.SurfaceViewCircle>
</LinearLayout>

I also noted that someone else has had a similar problem here.

Apologies for the poor formatting but the code editor is nigh on impossible to use for large code quotes!

Additional Info

I tried using the setVisibility()' in onvisibilityChanged() but it eventually results in an exception:

protected void onVisibilityChanged(View changedView, int visibility){
    super.onVisibilityChanged(changedView, visibility);
    changedView.setVisibility(visibility);
    Log.i("SurfaceViewCircle", "onVisibilityChanged() called.");
}

java.lang.IllegalThreadStateException: Thread already started.

It appears calling changedView.setvisibility() destroys the surface each time.

解决方案

Looks like what I want to do with SurfaceView is not recommended: link

这篇关于无法显示2实例我自定义的SurfaceView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆