我有一个简单布局文件的活动,它将创建一个以编程方式创建并添加到其中的片段。该片段没有任何布局文件,因为我以编程方式创建布局,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/bubble_fragment">
</LinearLayout>
My Fragment的onCreateView()是这样的,它将创建布局和类Bubble,它使用Handler(android.os.Handler)对Canvas进行一些绘制:
public class Bubble extends View implements View.OnClickListener {
private static final boolean BUBBLING = true; //thread is running to draw
private Paint paint;
private ShapeDrawable bubble;
// coordiantes, radius etc
private int x;
private int y;
private int r;
private int w = 200;
private int h = 200;
//handler to invalidate (force redraw on main GUI thread from this thread)
private Handler handler = new Handler();
public Bubble(Context context) {
super(context);
x = w/2;
y = h/2;
r = w/2;
bubble = new ShapeDrawable(new OvalShape());
bubble.getPaint().setColor(Color.BLUE);
bubble.setBounds(0, 0, r, r);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(0);
}
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh){
//set bubble parameters (center, size, etc)
startAnimation();
}
public void startAnimation(){
new Thread(new Runnable() {
public void run() {
while (BUBBLING) {
moveBubble();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
//update by invalidating on main UI thread
handler.post(new Runnable() {
public void run() {
invalidate();
}
});
}
}
}).start();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draws bubble on canvas
}
private void moveBubble(){
x = x + 1;
y = y + 1;
}
@Override
public void onClick(View v) {
Toast.makeText(this.getContext(), "Tapped on screen", Toast.LENGTH_LONG).show();
}
}
我正在使用setRetainInstance(true)来保留我的fragmnet状态。一切似乎工作正常,我的绘图工作,刷新自己就好了。但是,在方向更改时,我收到此错误:
E/AndroidRuntime: Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
at android.view.ViewGroup.addView(ViewGroup.java:3786)
at android.view.ViewGroup.addView(ViewGroup.java:3727)
at android.view.ViewGroup.addView(ViewGroup.java:3700)
at my.study.android.bubble.BubbleFragment.onCreateView(BubbleFragment.java:52)
从我到目前为止所读到的,使用这样的充气机
View v = inflater.inflate(R.layout.camera_fragment, parent, false);
应该解决这个问题,但在我的情况下,我不使用inflater,我动态地为我的片段创建布局。
更新 这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.study.android.bubble" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
>
<!-- removed this from above to show ActionBar
android:theme="@style/AppTheme.NoActionBar"> -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
更新2: 我弄清楚它崩溃的原因。我在onCreate()中创建了Bubble。如果我将它移动到onCreateView(),然后在方向上,它不会崩溃。 但是,我的动画不会保留在方向上,这意味着当我更改方向时,气泡会在其初始位置绘制:
public class BubbleFragment extends Fragment {
Bubble bubble;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//retain fragment
setRetainInstance(true);
//bubble = new Bubble(getActivity()); //THIS WILL CRASH APP, MOVE TO onCreateView instetad
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
100);
LinearLayout ll = new LinearLayout(getActivity());
ll.setOrientation(LinearLayout.VERTICAL);
// instantiate my class that does drawing on Canvas
bubble = new Bubble(getActivity());
bubble.setLayoutParams(lp);
bubble.setBackgroundColor(Color.BLUE);
ll.addView(bubble); //if you create bubble in onCreate() this will crash. Create bubble in onCreateView
return ll;
}
}
非常感谢,