Stworzyłem własny niestandardowy SurfaceView, który działa dobrze na własną rękę, ale kiedy próbuję umieścić dwa na osobnych kartach w TabWidget tylko jeden jest wyświetlany niezależnie od tego, która karta jest wybrana, oraz zawsze jest to SurfaceView, który jest najpierw narysowany po uruchomieniu aplikacji.Nie mogę wyświetlić 2 wystąpienia mojego niestandardowego SurfaceView
Aby zilustrować problem, stworzyłem przykładowy kod, który można skompilować w celu wyświetlenia problemu.
SurfaceView poniżej, o nazwie SurfaceViewCircle, po prostu tworzy bitmapę, rysuje niebieskie kółko jako domyślne, a następnie wyświetla je. Istnieje publiczna metoda changeColour(), która zmieni kolor koła w bitmapie.
Po drugie, tworzę układ XML, który po prostu zawiera pojedyncze wystąpienie obiektu SurfaceViewCircle.
W klasie Activity tworzę obiekt TabWidget i host itd. Następnie nadymam powyższy XML dwukrotnie, ale w jednym przypadku zmieniam kolor SurfaceViewCircle na czerwony. Po uruchomieniu aplikacji, bez względu na wybraną kartę, czerwone kółko jest ZAWSZE pokazane, Z WYJĄTKIEM, dla krótkiego wystąpienia, gdy aplikacja wychodzi i wyświetla się niebieskie kółko.
Czy ktoś może wskazać, czy pominięto krok podczas korzystania z SurfaceView?
Jest to kod aktywny:
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;
}
}
To jest mój zwyczaj 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
}
}
}
}
}
}
Plik maintabs.xml:
<?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>
A 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>
Zauważyłem też, że ktoś miał podobny problem here.
Przepraszamy za słabą formatowania ale edytor kodu jest prawie niemożliwe do wykorzystania na dużych cytaty kod!
Dodatkowe informacje
Próbowałem za pomocą setVisibility()'
w onvisibilityChanged()
ale ostatecznie powoduje wyjątek:
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.
wydaje się powołanie changedView.setvisibility()
niszczy powierzchnię za każdym razem.
na setupTab jesteś tylko tworząc jedną, jak ja to widzę, spróbuj sprawdzić w ten sposób: http://stackoverflow.com/a/5034063/ 1084764 – Raykud
Dzięki Raykud. Sprawdzi to i zgłoś się nieco później. – Kerry