2016-03-25 38 views
0

如果我将RecyclerView与TextView一起放入LinearLayout中,会出现下面的错误,为什么?它工作正常,只有一个RecyclerView。如何在使用碎片时在LinearLayout中使用RecyclerView?

java.lang.IllegalStateException:指定的子项已经有父项。您必须先调用子对象的父对象的removeView()。

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical"> 

<TextView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:textAppearance="?android:attr/textAppearanceLarge" 
    android:text="Title ....." 
    android:id="@+id/textView" /> 

<android.support.v7.widget.RecyclerView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/fragment_beat_box_recycler_view" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

</android.support.v7.widget.RecyclerView> 

</LinearLayout> 

片段

public class SoundBoardFragment extends Fragment { 

private static final String TAG = "SoundBoardFragment"; 
private BeatBox mBeatBox; 
private static final String ARG_FOLDER_NAME = "soundboard_folder"; 
private static String mFolderName; 

public static SoundBoardFragment newInstance(String folderName) 
{ 
    Log.i(TAG, "createFragment " + folderName); 
    mFolderName = "sounds/" + folderName; 
    Bundle args = new Bundle(); 
    args.putSerializable(ARG_FOLDER_NAME, folderName); 
    SoundBoardFragment fragment = new SoundBoardFragment(); 
    fragment.setArguments(args); 
    return fragment; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setHasOptionsMenu(true); 
    setRetainInstance(true); 
    Log.i(TAG, "onCreate " + mFolderName); 
    mBeatBox = new BeatBox(getActivity(),mFolderName); 

} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{ 
    View view = inflater.inflate(R.layout.fragment_beat_box, container,false); 


    RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.fragment_beat_box_recycler_view); 
    recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3)); 
    recyclerView.setAdapter(new SoundAdapter(mBeatBox.getSounds())); 
    return recyclerView; 
} 

@Override 
public void onDestroy() 
{ 
    super.onDestroy(); 
    mBeatBox.release(); 

} 

@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
{ 
    super.onCreateOptionsMenu(menu, inflater); 
    inflater.inflate(R.menu.fragment_sound_board, menu); 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) 
{ 
    switch (item.getItemId()) 
    { 
     case R.id.menu_item_quit: 
      getActivity().onBackPressed(); 
      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
    } 
} 

private class SoundHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
{ 
    private Button mButton; 
    private Sound mSound; 

    public SoundHolder (LayoutInflater inflater, ViewGroup container) 
    { 
     super(inflater.inflate(R.layout.list_item_sound, container, false)); 
     mButton = (Button)itemView.findViewById(R.id.list_item_sound_button); 
     mButton.setOnClickListener(this); 
    } 

    public void bindSound(Sound sound) 
    { 
     mSound = sound; 
     mButton.setText(mSound.getName()); 
    } 

    @Override 
    public void onClick(View v) { 
     mBeatBox.play(mSound); 
    } 
} 

private class SoundAdapter extends RecyclerView.Adapter<SoundHolder>{ 
    private List<Sound> mSounds; 

    public SoundAdapter(List<Sound> sounds) 
    { 
     mSounds=sounds; 
    } 

    @Override 
    public SoundHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     LayoutInflater inflater = LayoutInflater.from(getActivity()); 
     return new SoundHolder(inflater,parent); 
    } 

    @Override 
    public void onBindViewHolder(SoundHolder holder, int position) { 
     Sound sound = mSounds.get(position); 
     holder.bindSound(sound); 
    } 

    @Override 
    public int getItemCount() { 
     return mSounds.size(); 
    } 
} 

} 

logcat的结果

03-25 21:56:05.258 25429-25429/com.example.blah.soundboard E/AndroidRuntime: FATAL EXCEPTION: main 
Process: com.example.blah.soundboard, PID: 25429 
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.blah.soundboard/com.example.blah.soundboard.SoundBoardActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
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:4309) 
    at android.view.ViewGroup.addView(ViewGroup.java:4145) 
    at android.view.ViewGroup.addView(ViewGroup.java:4086) 
    at android.view.ViewGroup.addView(ViewGroup.java:4059) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1083) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) 
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613) 
    at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330) 
    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547) 
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1237) 
    at android.app.Activity.performStart(Activity.java:6268) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)  
    at android.app.ActivityThread.-wrap11(ActivityThread.java)  
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)  
    at android.os.Handler.dispatchMessage(Handler.java:102)  
    at android.os.Looper.loop(Looper.java:148)  
    at android.app.ActivityThread.main(ActivityThread.java:5417)  
    at java.lang.reflect.Method.invoke(Native Method)  
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)  

每个ItemView控件是内部的FrameLayout

<FrameLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_margin="8dp" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content"> 
<Button 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/list_item_sound_button" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:layout_gravity="center" 
tools:text="Sound name"> 
</Button> 
</FrameLayout> 
+0

您可以显示logcat输出吗? – chRyNaN

+0

“itemView”来自SoundHolder(LayoutInflater inflater,ViewGroup容器)? –

+0

itemView是根视图 –

回答

1

的问题按钮在你的片段onCreateView您将返回RecyclerView。相反,您应该返回名为“view”的变量,该变量是布局的根视图。

发生了什么是RecyclerView正在附加在两个地方。

+0

谢谢,显而易见。 :) – ChibaKun

1

您在片段的onCreateView中返回的对象View应该是片段的视图。所以你的代码应该看起来像这样:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{ 
    View view = inflater.inflate(R.layout.fragment_beat_box, container,false); 


    RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.fragment_beat_box_recycler_view); 
    recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3)); 
    recyclerView.setAdapter(new SoundAdapter(mBeatBox.getSounds())); 
    return view; 
} 

在做出改变后,它应该工作。

+0

感谢您的更正;) – ChibaKun