嗨,有很多相关的话题都是关于这个问题,我看了一下。我已经按照这些相关的答案,我使用了这些建议,但我仍然在logcat上收到以下错误:
06-16 02:54:22.333: W/System.err(20722): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
我有一个从LinearLayout类扩展的PitchView。 ArrayList<PlayerView> playerList;
包含我的玩家列表,setupTeamView()
方法负责绘制类。
用户可以更换玩家。所以我将chanes添加到数组列表(playerList),然后立即调用setupTeamView()
来重绘类。第一次运行应用程序时没有问题但是当我根据新数据调用setupTeamView()
方法重绘屏幕时,应用程序崩溃并且logcat显示标记的行。我有一个clearTeamView()
方法负责清除此类的容器。虽然它已经运行但似乎没有删除它的孩子(llContainer
方法中setupTeamView()
)。
我花了大约10个小时来解决这个问题但是没有成功。如果有人告诉我我的问题是什么,我将非常感激。感谢。
public class PitchView extends LinearLayout {
private ArrayList<PlayerView> playerList;
public void clearTeamView() {
final LinearLayout parentLayout = (LinearLayout) this.findViewById(R.id.team_pitch_view);
parentLayout.removeAllViews();
}
public void setupTeamView() {
if(playerList == null)
return;
// remove all views
clearTeamView();
// to count from 1-11 (Number of Players)
int pointer = 1;
// Get formation
ArrayList<Integer> formationArr = Formation.getFormationAsArray(formation);
// Container to hold other views inside
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
LinearLayout llContainer = new LinearLayout(getContext());
llContainer.setOrientation(LinearLayout.VERTICAL);
this.addView(llContainer, params);
// -1.... This is to cover the goalie case, who is always present, and always on his own
for(int i = -1; i < formationArr.size(); i++) {
if(i == -1) {
PlayerView goaller = playerList.get(0);
goaller.switchStatistics(rightStatsOn);
goaller.setOnPlayerClickedListener(listener);
goaller.setGravity(Gravity.CENTER);
LinearLayout goalieLayout = new LinearLayout(getContext());
goalieLayout.setOrientation(LinearLayout.HORIZONTAL);
goalieLayout.addView(goaller, params); <<<<<<<<<<<<<<<<<<<<<< ERROR
llContainer.addView(goalieLayout);
} else {
LinearLayout teamMemberLayout = new LinearLayout(getContext());
teamMemberLayout.setOrientation(LinearLayout.HORIZONTAL);
for (int j = 0; j < formationArr.get(i); j++) {
PlayerView player = playerList.get(pointer++);
player.switchStatistics(rightStatsOn);
player.setOnPlayerClickedListener(listener);
player.setGravity(Gravity.CENTER);
teamMemberLayout.addView(player, params);
}
llContainer.addView(teamMemberLayout);
}
}
}
...
}
====== UPDATE ==
感谢CommonsWare的建议,我得到了很好的想法但不幸的是,我有同样的问题。我改变了
public void clearTeamView() {
final LinearLayout parentLayout = (LinearLayout) this.findViewById(R.id.team_pitch_view);
parentLayout.removeAllViews();
}
到
public void clearTeamView() {
this.removeAllViews();
}
但我有同样的问题。我还尝试在setupViews中将llContainer添加到parentLayout但不幸的是,结果相同:(
所以,我决定重构我的viewGroup。但我仍然得到相同的结果:((((似乎它并不像我一样
任何方式,而不是动态创建所有内容,我决定为我的视图组创建一个布局,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/bg_play_ground"
android:id="@+id/ivPlayGround"
android:contentDescription="@string/general_content_description"
android:alpha="0.2"
android:scaleType="fitXY"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="7dp"
android:id="@+id/llContainer">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/llGoalieLayout">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/llDefLayout">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/llMedLayout">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center"
android:id="@+id/llFwdLayout">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
并以此形式更改了类:
public class PitchView extends RelativeLayout {
private static final String TAG = "PitchView";
private Context mContext;
public Formation.FORMATION formation;
private ArrayList<PlayerView> playerList;
private LinearLayout llContainer;
private LinearLayout llGoalieLayout;
private LinearLayout llDefLayout;
private LinearLayout llMedLayout;
private LinearLayout llFwdLayout;
private void init() {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout view = (RelativeLayout) mInflater.inflate(R.layout.widget_pinch_view, null);
addView(view);
llContainer = (LinearLayout) view.findViewById(R.id.llContainer);
llGoalieLayout = (LinearLayout) view.findViewById(R.id.llGoalieLayout);
llDefLayout = (LinearLayout) view.findViewById(R.id.llDefLayout);
llMedLayout = (LinearLayout) view.findViewById(R.id.llMedLayout);
llFwdLayout = (LinearLayout) view.findViewById(R.id.llFwdLayout);
this.formation = Formation.FORMATION.four_four_two;
setupTeamView();
}
public void clearTeamView() {
llGoalieLayout.removeAllViews();
llDefLayout.removeAllViews();
llMedLayout.removeAllViews();
llFwdLayout.removeAllViews();
Log.e(TAG, "goalie child count: " + llGoalieLayout.getChildCount());
Log.e(TAG, "DEF child count: " + llDefLayout.getChildCount());
Log.e(TAG, "MED child count: " + llMedLayout.getChildCount());
Log.e(TAG, "FWD child count: " + llFwdLayout.getChildCount());
}
public void setupTeamView() {
if(playerList == null)
return;
// remove all views)
clearTeamView();
// Get formation
ArrayList<Integer> formationArr = Formation.getFormationAsArray(formation);
// to count from 0-10 (Number of Players)
int pointer = 0;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
// 1. This is to cover the goalie case, who is always present, and always on his own
PlayerView goaller = playerList.get(pointer);
goaller.switchStatistics(rightStatsOn);
goaller.setOnPlayerClickedListener(listener);
goaller.setGravity(Gravity.CENTER);
llGoalieLayout.addView(goaller, params);
// 2. This is to cover the defender cases
for(int i=0; i<formationArr.get(0); i++) {
PlayerView defender = playerList.get(++pointer);
defender.switchStatistics(rightStatsOn);
defender.setOnPlayerClickedListener(listener);
defender.setGravity(Gravity.CENTER);
llDefLayout.addView(defender, params); <<<<<<<<<<<<<< ERROR
}
// 3. This is to cover the midfielder cases
for(int i=0; i<formationArr.get(1); i++) {
PlayerView midfielder = playerList.get(++pointer);
midfielder.switchStatistics(rightStatsOn);
midfielder.setOnPlayerClickedListener(listener);
midfielder.setGravity(Gravity.CENTER);
llMedLayout.addView(midfielder, params);
}
// 4. This is to cover the attacker cases
for(int i=0; i<formationArr.get(2); i++) {
PlayerView attacker = playerList.get(++pointer);
attacker.switchStatistics(rightStatsOn);
attacker.setOnPlayerClickedListener(listener);
attacker.setGravity(Gravity.CENTER);
llFwdLayout.addView(attacker, params);
}
Log.e(TAG, "goalie child count: " + llGoalieLayout.getChildCount());
Log.e(TAG, "DEF child count: " + llDefLayout.getChildCount());
Log.e(TAG, "MED child count: " + llMedLayout.getChildCount());
Log.e(TAG, "FWD child count: " + llFwdLayout.getChildCount());
}
.
.
.
}
与上次相同,应用程序在第一次尝试时工作正常,但在我想要重新组织玩家时会崩溃。
这是登录首次运行的输出:
06-16 17:47:33.326: E/PitchView(24305): goalie child count: 0
06-16 17:47:33.326: E/PitchView(24305): DEF child count: 0
06-16 17:47:33.326: E/PitchView(24305): MED child count: 0
06-16 17:47:33.326: E/PitchView(24305): FWD child count: 0
06-16 17:47:33.346: E/PitchView(24305): goalie child count: 1
06-16 17:47:33.346: E/PitchView(24305): DEF child count: 4
06-16 17:47:33.346: E/PitchView(24305): MED child count: 4
06-16 17:47:33.346: E/PitchView(24305): FWD child count: 2
替换后(形成相同但播放器的新对象添加到playerList并且setupTeamView想要重绘缩放区域)
06-16 17:50:35.331: E/PitchView(24305): goalie child count: 0
06-16 17:50:35.331: E/PitchView(24305): DEF child count: 0
06-16 17:50:35.331: E/PitchView(24305): MED child count: 0
06-16 17:50:35.331: E/PitchView(24305): FWD child count: 0
06-16 17:52:13.321: E/AndroidRuntime(25088): FATAL EXCEPTION: main
06-16 17:52:13.321: E/AndroidRuntime(25088): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
06-16 17:52:13.321: E/AndroidRuntime(25088): at com.allstarxi.view.PitchView.setupTeamView(PitchView.java:169)
正如您所看到的,所有观看次数都已删除,但我仍然会得到&#34; 您必须首先在孩子的父母身上调用removeView()。&#34 ;
答案 0 :(得分:0)
您要移除parentLayout
的所有观看次数。您没有将llContainer
添加到parentLayout
。您已将llContainer
添加到this
。由于parentLayout
是this
的孩子(因为您是通过findViewById()
找到的),llContainer
无法成为parentLayout
的孩子,所以删除parentLayout
的子女不会影响llContainer
。
llContainer
需要parentLayout
的孩子,或者您需要删除this
的所有观看,或者您需要从llContainer
删除this
除了你当前的代码。
答案 1 :(得分:0)
如果您的所有孩子都有 llContainer 作为父级,那么为什么要从 R.id.team_pitch_view 中删除所有孩子?
下一个版本:
for(PlayerView player : playerList){
((LinearLayout)player.getParent()).removeView(player);
}
答案 2 :(得分:0)
您的布局只支持一个子视图,您必须从中删除所有视图才能添加另一个视图。