无法显示2实例我自定义的SurfaceView [英] Cannot Display 2 Instances of my custom SurfaceView
问题描述
我创建自己的自定义SurfaceView工作正常自身但是当我试图把两个到单独的选项卡中的 TabWidget 的只有一个无论哪个选项卡的要求不断示出被选择,它始终是SurfaceView其首先时绘制的应用程序启动。
要说明,我创建样本code可以编译,显示为问题的问题。
下面的SurfaceView,叫SurfaceViewCircle简单地创建一个位图,绘制一个蓝色圆圈为默认值,然后显示它。有一个公共的方法,changeColour(),这将改变位图中的圆圈的颜色。
其次,我创建一个XML布局其中只包含SurfaceViewCircle的一个实例。
在活动类,我创建了一个TabWidget和主机等。然后我吹上面的XML两次,但在一种情况下我的SurfaceViewCircle的颜色变为红色。一旦应用程序运行时,无论是什么标签我选择,红圈是始终显示,除了显示应用程序退出和蓝色的圆圈,当一个简短的实例。
任何人都可以指出,如果我错过了一个步骤中,使用SurfaceView什么时候?
这是活动code:
公共类TestActivity延伸活动{
/ **第一次创建活动时调用。 * /
私人TabHost mTabHost;
私人语境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 = mTabHost.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 = mTabHost.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.setRunning(真正的);
t.start();
surfaceIsCreated = TRUE;
}
@覆盖
公共无效surfaceDestroyed(SurfaceHolder持有者){
Log.i(广场,surfaceDestroyed()调用。);
surfaceIsCreated = FALSE;
布尔重试= TRUE;
同步(T){
t.setRunning(假);
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:机器人=http://schemas.android.com/apk/res/android
机器人:方向=垂直机器人:layout_width =FILL_PARENT
机器人:layout_height =FILL_PARENT>
< TabHost的xmlns:机器人=http://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:机器人=http://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()
每次破坏表面。
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屋!