我正在使用片段为API15构建一个Android应用程序。
布局是:
Java文件是:
在activity_page_detail.xml中:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/page_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".pageDetailActivity"
tools:ignore="MergeRootFrame"/>
在activity_page_list.xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="contentDescription"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="@+id/logoimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/logo"
android:layout_marginTop="20dp"
android:layout_marginBottom="30dp"/>
<fragment
android:id="@+id/page_list"
android:name="com.application.trigger.pageListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context=".pageListActivity"
tools:layout="@android:layout/list_content" />
</LinearLayout>
在activity_page_twopane.xml中:
<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:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
tools:context=".pageListActivity" >
<!--
This layout is a two-pane layout for the pages
master/detail flow. See res/values-large/refs.xml and
res/values-sw600dp/refs.xml for an example of layout aliases
that replace the single-pane version of the layout with
this two-pane version.
For more on layout aliases, see:
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
-->
<fragment
android:id="@+id/page_list"
android:name="com.application.trigger.pageListFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@android:layout/list_content" />
<FrameLayout
android:id="@+id/page_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
在fragment_page_detail.xml中:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".pageDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="contentDescription"
android:background="#000">
<TextView
android:id="@+id/page_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:textColor="#fafafa"
android:textIsSelectable="true"
android:textAppearance="@android:attr/textAppearanceListItemSmall"
/>
<LinearLayout
android:id="@+id/linear_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#7f7f7f"
/>
</LinearLayout>
Java源代码是:
package com.application.trigger;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
/**
* An activity representing a list of pages. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {@link pageDetailActivity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
* <p>
* The activity makes heavy use of fragments. The list of items is a
* {@link pageListFragment} and the item details
* (if present) is a {@link pageDetailFragment}.
* <p>
* This activity also implements the required
* {@link pageListFragment.Callbacks} interface
* to listen for item selections.
*/
public class pageListActivity extends FragmentActivity
implements pageListFragment.Callbacks {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_list);
if (findViewById(R.id.page_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((pageListFragment) getSupportFragmentManager()
.findFragmentById(R.id.page_list))
.setActivateOnItemClick(true);
}
// TODO: If exposing deep links into your app, handle intents here.
}
/**
* Callback method from {@link pageListFragment.Callbacks}
* indicating that the item with the given ID was selected.
*/
@Override
public void onItemSelected(String id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(pageDetailFragment.ARG_ITEM_ID, id);
pageDetailFragment fragment = new pageDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.page_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, pageDetailActivity.class);
detailIntent.putExtra(pageDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
}
和
package com.application.trigger;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.application.trigger.dummy.DummyContent;
/**
* A list fragment representing a list of pages. This fragment
* also supports tablet devices by allowing list items to be given an
* 'activated' state upon selection. This helps indicate which item is
* currently being viewed in a {@link pageDetailFragment}.
* <p>
* Activities containing this fragment MUST implement the {@link Callbacks}
* interface.
*/
public class pageListFragment extends ListFragment {
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {@link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public pageListFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO: replace with a real list adapter.
setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
DummyContent.ITEMS));
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(activateOnItemClick
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
private void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}
并且:
package com.application.trigger;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.view.MenuItem;
/**
* An activity representing a single page detail screen. This
* activity is only used on handset devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a {@link pageListActivity}.
* <p>
* This activity is mostly just a 'shell' activity containing nothing
* more than a {@link pageDetailFragment}.
*/
public class pageDetailActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page_detail);
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don't need to manually add it.
// For more information, see the Fragments API guide at:
//
// http://developer.android.com/guide/components/fragments.html
//
if (savedInstanceState == null) {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(pageDetailFragment.ARG_ITEM_ID,
getIntent().getStringExtra(pageDetailFragment.ARG_ITEM_ID));
pageDetailFragment fragment = new pageDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.page_detail_container, fragment)
.commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpTo(this, new Intent(this, pageListActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
并且:
package com.application.trigger.dummy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper class for providing sample content for user interfaces created by
* Android template wizards.
* <p>
* TODO: Replace all uses of this class before publishing your app.
*/
public class DummyContent {
/**
* An array of sample (dummy) items.
*/
public static List<DummyItem> ITEMS = new ArrayList<DummyItem>();
/**
* A map of sample (dummy) items, by ID.
*/
public static Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
static {
// Add 3 sample items.
addItem(new DummyItem("1", "ListItem-1"));
addItem(new DummyItem("2", "ListItem-2"));
addItem(new DummyItem("3", "ListItem-3"));
addItem(new DummyItem("4", "ListItem-4"));
addItem(new DummyItem("5", "ListItem-5"));
}
private static void addItem(DummyItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
/**
* A dummy item representing a piece of content.
*/
public static class DummyItem {
public String id;
public String content;
public DummyItem(String id, String content) {
this.id = id;
this.content = content;
}
@Override
public String toString() {
return content;
}
}
}
最后,与我的问题相关的代码文件是:
package com.application.trigger;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Intents.Insert;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.application.trigger.dummy.DummyContent;
/**
* A fragment representing a single page detail screen.
* This fragment is either contained in a {@link pageListActivity}
* in two-pane mode (on tablets) or a {@link pageDetailActivity}
* on handsets.
*/
public class pageDetailFragment extends Fragment {
/**
* The fragment argument representing the item ID that this fragment
* represents.
*/
public static final String ARG_ITEM_ID = "item_id";
/**
* The dummy content this fragment is presenting.
*/
private DummyContent.DummyItem mItem;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public pageDetailFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments().containsKey(ARG_ITEM_ID)) {
// Load the dummy content specified by the fragment
// arguments. In a real-world scenario, use a Loader
// to load content from a content provider.
mItem = DummyContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
getActivity().setTitle(mItem.content);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page_detail, container, false);
// show each product specification
//passing data to each page
if (mItem != null) {
switch (Integer.parseInt(mItem.id)) {
case 1:
((TextView) rootView.findViewById(R.id.page_detail))
.setText("show text1");
final LinearLayout row1 = new LinearLayout(getActivity());
row1.setOrientation(LinearLayout.HORIZONTAL);
row1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
row1.setVisibility(View.VISIBLE);
final TextView text1 = new TextView(getActivity());
text1.setText("some sample text");
text1.setVisibility(View.VISIBLE);
final ImageView image1 = new ImageView(getActivity());
image1.setVisibility(View.VISIBLE);
image1.setImageResource(R.drawable.logo);
row1.addView(text1);
row1.addView(image1);
//LinearLayout vertical = (LinearLayout) rootView.findViewById(R.id.linear_vertical);
//vertical.addView(row1);
((ViewGroup)rootView).addView(row1);
break;
case 2:
((TextView) rootView.findViewById(R.id.page_detail))
.setText("show text2");
break;
case 3:
((TextView) rootView.findViewById(R.id.page_detail))
.setText("show text3");
break;
case 4:
Intent contact = new Intent(Intent.ACTION_INSERT);
contact.setType(ContactsContract.Contacts.CONTENT_TYPE);
ArrayList<ContentValues> data = new ArrayList<ContentValues>();
ContentValues company = new ContentValues();
company.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
company.put(Organization.COMPANY, "company name");
data.add(company);
ContentValues mobile = new ContentValues();
mobile.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
mobile.put(Phone.NUMBER, "9898989898");
data.add(mobile);
ContentValues phone = new ContentValues();
phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
phone.put(Phone.TYPE, Phone.TYPE_WORK);
phone.put(Phone.NUMBER, "9898989898");
data.add(phone);
ContentValues email = new ContentValues();
email.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
email.put(Email.TYPE, Email.TYPE_WORK);
email.put(Email.ADDRESS, "info@company.com");
data.add(email);
ContentValues website = new ContentValues();
website.put(Data.MIMETYPE, Website.CONTENT_ITEM_TYPE);
website.put(Website.URL, "http://company.com");
data.add(website);
contact.putParcelableArrayListExtra(Insert.DATA, data);
int request_Code = 100;
startActivityForResult(contact, request_Code);
break;
case 5:
((TextView) rootView.findViewById(R.id.page_detail))
.setText("show text5");
break;
}
}
return rootView;
}
}
问题是如何在onCreateView方法的最后一个java代码中以编程方式为每个片段细节添加视图?案例1中所述功能的我的代码退出程序而不起作用。
以下是相关的堆栈跟踪:
08-04 06:19:35.623: DEBUG/dalvikvm(1153): GC_CONCURRENT freed 84K, 3% free 9379K/9607K, paused 4ms+4ms
08-04 06:19:39.283: WARN/WindowManager(89): Failure taking screenshot for (180x300) to layer 21015
08-04 06:19:43.063: INFO/ActivityManager(89): START {cmp=com.application.trigger/.pageDetailActivity (has extras)} from pid 1153
08-04 06:19:43.074: WARN/WindowManager(89): Failure taking screenshot for (180x300) to layer 21010
08-04 06:19:43.233: DEBUG/AndroidRuntime(1153): Shutting down VM
08-04 06:19:43.233: WARN/dalvikvm(1153): threadid=1: thread exiting with uncaught exception (group=0x2ba041f8)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): FATAL EXCEPTION: main
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.application.trigger/com.application.trigger.pageDetailActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread.access$600(ActivityThread.java:123)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.os.Handler.dispatchMessage(Handler.java:99)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.os.Looper.loop(Looper.java:137)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread.main(ActivityThread.java:4424)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at java.lang.reflect.Method.invokeNative(Native Method)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at java.lang.reflect.Method.invoke(Method.java:511)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at dalvik.system.NativeStart.main(Native Method)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.view.ViewGroup.addViewInner(ViewGroup.java:3337)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.view.ViewGroup.addView(ViewGroup.java:3208)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.view.ViewGroup.addView(ViewGroup.java:3165)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.view.ViewGroup.addView(ViewGroup.java:3145)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at com.application.trigger.pageDetailFragment.onCreateView(pageDetailFragment.java:98)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:556)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1133)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.Activity.performStart(Activity.java:4475)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1929)
08-04 06:19:43.265: ERROR/AndroidRuntime(1153): ... 11 more
08-04 06:19:43.293: WARN/ActivityManager(89): Force finishing activity com.application.trigger/.pageDetailActivity
08-04 06:19:43.323: WARN/ActivityManager(89): Force finishing activity com.application.trigger/.pageListActivity
08-04 06:19:43.633: INFO/Process(89): Sending signal. PID: 1153 SIG: 3
答案 0 :(得分:3)
堆栈跟踪清楚地表明问题在于您正在尝试将已附加到ViewGroup(其父级)的View添加到另一个VIewGroup。
视图不能有两个不同的父项,因此错误。
您可以在将视图添加到新父视图之前从其父视图中删除视图,或者只是多次膨胀相同的XML。如果您将一个XML更多地膨胀,那么您将创建新的View对象,并且可以将它们附加到不同的父对象。