我正在学习 fragment ,我使用了给定 developers website 的示例代码。
我添加了这个 http://nhaarman.github.io/ListViewAnimations/#getting-started
用于启用列表上的滑动和删除操作。
我有两个问题
1. 当我的手机处于横向模式时,我似乎根本看不到详细信息 Pane 。
2. 滑动后无法移除对象,滑动完成后出现
Land\fragment_layout
<!--
Top-level content view for the layout fragment sample. This version is
for display when in landscape: we can fit both titles and dialog.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal" >
<com.nhaarman.listviewanimations.itemmanipulation.DynamicListView
android:id="@+id/dynamiclistview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<fragment
android:id="@+id/titles"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
class="edu.dartmouth.cs.FragmentLayout$TitlesFragment" />
<FrameLayout
android:id="@+id/details"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/detailsElementBackground"
/>
</LinearLayout>
fragment 布局
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.nhaarman.listviewanimations.appearance.simple.AlphaInAnimationAdapter;
import com.nhaarman.listviewanimations.itemmanipulation.DynamicListView;
import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.OnDismissCallback;
import edu.dartmouth.cs.apis.Shakespeare;
// Demonstration of using fragments to implement different activity layouts.
// This sample provides a different layout (and activity flow) when run in
// landscape.
public class FragmentLayout extends Activity {
// static DynamicListView listView;
static ArrayAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(this, "FragmentLayout: OnCreate()", Toast.LENGTH_SHORT)
.show();
// Sets the view. Depending on orientation it will select either
// res/layout/fragment_layout.xml (portrait mode) or
// res/layout-land/fragment_layout.xml (landscape mode). This is done
// automatically by the system.
setContentView(R.layout.fragment_layout);
}
// This is a secondary activity, to show what the user has selected when the
// screen is not large enough to show it all in one activity.
public static class DetailsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(this, "DetailsActivity", Toast.LENGTH_SHORT).show();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// If the screen is now in landscape mode, we can show the
// dialog in-line with the list so we don't need this activity.
finish();
return;
}
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
// create fragment
DetailsFragment details = new DetailsFragment();
// get and set the position input by user (i.e., "index")
// which is the construction arguments for this fragment
details.setArguments(getIntent().getExtras());
//
getFragmentManager().beginTransaction()
.add(android.R.id.content, details).commit();
}
}
}
// This is the "top-level" fragment, showing a list of items that the user
// can pick. Upon picking an item, it takes care of displaying the data to
// the user as appropriate based on the current UI layout.
// Displays a list of items that are managed by an adapter similar to
// ListActivity. It provides several methods for managing a list view, such
// as the onListItemClick() callback to handle click events.
public static class TitlesFragment extends ListFragment {
boolean mDualPane;
int mCurCheckPosition = 0;
// onActivityCreated() is called when the activity's onCreate() method
// has returned.
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
DynamicListView listView = (DynamicListView) getActivity()
.findViewById(R.id.dynamiclistview);
// You can use getActivity(), which returns the activity associated
// with a fragment.
// The activity is a context (since Activity extends Context) .
Toast.makeText(getActivity(), "TitlesFragment:onActivityCreated",
Toast.LENGTH_LONG).show();
// Populate list with our static array of titles in list in the
// Shakespeare class
myAdapter = new ArrayAdapter(getActivity(),
android.R.layout.simple_list_item_activated_1,
Shakespeare.TITLES);
AlphaInAnimationAdapter animationAdapter = new AlphaInAnimationAdapter(
myAdapter);
animationAdapter.setAbsListView(listView);
listView.setAdapter(animationAdapter);
// Check to see if we have a frame in which to embed the details
// fragment directly in the containing UI.
// R.id.details relates to the res/layout-land/fragment_layout.xml
// This is first created when the phone is switched to landscape
// mode
View detailsFrame = getActivity().findViewById(R.id.details);
Toast.makeText(getActivity(), "detailsFrame " + detailsFrame,
Toast.LENGTH_LONG).show();
// Check that a view exists and is visible
// A view is visible (0) on the screen; the default value.
// It can also be invisible and hidden, as if the view had not been
// added.
//
mDualPane = detailsFrame != null
&& detailsFrame.getVisibility() == View.VISIBLE;
Toast.makeText(getActivity(), "mDualPane " + mDualPane,
Toast.LENGTH_LONG).show();
if (savedInstanceState != null) {
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
if (mDualPane) {
// In dual-pane mode, the list view highlights the selected
// item.
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Make sure our UI is in the correct state.
showDetails(mCurCheckPosition);
} else {
// We also highlight in uni-pane just for fun
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
getListView().setItemChecked(mCurCheckPosition, true);
}
listView.enableSwipeToDismiss(new OnDismissCallback() {
@Override
public void onDismiss(final ViewGroup listView,
final int[] reverseSortedPositions) {
Toast.makeText(getActivity(), "swipe detected " ,
Toast.LENGTH_LONG).show();
for (int position : reverseSortedPositions) {
// NOT WORKING!!
myAdapter.remove(position);
}
}
});
listView.setOnItemClickListener(new MyOnItemClickListener(listView));
}
private class MyOnItemClickListener implements
AdapterView.OnItemClickListener {
private final DynamicListView mListView;
MyOnItemClickListener(final DynamicListView listView) {
mListView = listView;
}
@Override
public void onItemClick(final AdapterView<?> parent,
final View view, final int position, final long id) {
//
Toast.makeText(getActivity(),
"onListItemClick position is" + position,
Toast.LENGTH_LONG).show();
showDetails(position);
//
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Toast.makeText(getActivity(), "onSaveInstanceState",
Toast.LENGTH_LONG).show();
outState.putInt("curChoice", mCurCheckPosition);
}
// If the user clicks on an item in the list (e.g., Henry V then the
// onListItemClick() method is called. It calls a helper function in
// this case.
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(getActivity(),
"onListItemClick position is" + position, Toast.LENGTH_LONG)
.show();
showDetails(position);
}
// Helper function to show the details of a selected item, either by
// displaying a fragment in-place in the current UI, or starting a whole
// new activity in which it is displayed.
void showDetails(int index) {
mCurCheckPosition = index;
// The basic design is mutli-pane (landscape on the phone) allows us
// to display both fragments (titles and details) with in the same
// activity; that is FragmentLayout -- one activity with two
// fragments.
// Else, it's single-pane (portrait on the phone) and we fire
// another activity to render the details fragment - two activities
// each with its own fragment .
//
if (mDualPane) {
// We can display everything in-place with fragments, so update
// the list to highlight the selected item and show the data.
// We keep highlighted the current selection
getListView().setItemChecked(index, true);
// Check what fragment is currently shown, replace if needed.
DetailsFragment details = (DetailsFragment) getFragmentManager()
.findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
// Make new fragment to show this selection.
details = DetailsFragment.newInstance(index);
System.out.println(" Dual plane");
Toast.makeText(
getActivity(),
"**showDetails dual-pane: create and relplace fragment",
Toast.LENGTH_LONG).show();
// Execute a transaction, replacing any existing fragment
// with this one inside the frame.
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (index == 0) {
ft.replace(R.id.details, details); // NOT WORKING!!
} else {
ft.replace(R.id.details, details);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else {
// Otherwise we need to launch a new activity to display
// the dialog fragment with selected text.
// That is: if this is a single-pane (e.g., portrait mode on a
// phone) then fire DetailsActivity to display the details
// fragment
// Create an intent for starting the DetailsActivity
Intent intent = new Intent();
// explicitly set the activity context and class
// associated with the intent (context, class)
intent.setClass(getActivity(), DetailsActivity.class);
// pass the current position
intent.putExtra("index", index);
startActivity(intent);
}
}
}
// This is the secondary fragment, displaying the details of a particular
// item.
public static class DetailsFragment extends Fragment {
// Create a new instance of DetailsFragment, initialized to show the
// text at 'index'.
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
// The system calls this when it's time for the fragment to draw its
// user interface for the first time. To draw a UI for your fragment,
// you must return a View from this method that is the root of your
// fragment's layout. You can return null if the fragment does not
// provide a UI.
// We create the UI with a scrollview and text and return a reference to
// the scoller which is then drawn to the screen
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Toast.makeText(getActivity(), "DetailsFragment:onCreateView",
Toast.LENGTH_LONG).show();
//
// if (container == null) {
// // We have different layouts, and in one of them this
// // fragment's containing frame doesn't exist. The fragment
// // may still be created from its saved state, but there is
// // no reason to try to create its view hierarchy because it
// // won't be displayed. Note this is not needed -- we could
// // just run the code below, where we would create and return
// // the view hierarchy; it would just never be used.
// return null;
// }
// If non-null, this is the parent view that the fragment's UI
// should be attached to. The fragment should not add the view
// itself, but this can be used to generate the LayoutParams of
// the view.
//
// programmatically create a scrollview and texview for the text in
// the container/fragment layout. Set up the properties and add the
// view.
ScrollView scroller = new ScrollView(getActivity());
TextView text = new TextView(getActivity());
int padding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
.getResources().getDisplayMetrics());
text.setPadding(padding, padding, padding, padding);
scroller.addView(text);
text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
return scroller;
}
}
}
最佳答案
你搞砸了 listfragment 和 dynamiclist。 listfragment 本身有一个列表,在您的代码的某些部分您操作 dynamiclist,而在其他部分您操作 listfragment 的列表。所以为了使用动态列表,你必须使用 fragment 而不是 listFragment 并且你必须为它创建单独的布局并将你的动态列表放在那里。
因为 myAdapter.remove(position);
删除了你标题的 View ,你必须删除后面的数据集,但你的数据集是字符串数组,所以你不能从中删除,你该怎么办?您必须创建一个 List
并将其传递给您的适配器,然后在扫描发生后,您必须删除指定位置的数据。所以你的代码必须改变并且是这样的:
package edu.dartmouth.cs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.nhaarman.listviewanimations.appearance.simple.AlphaInAnimationAdapter;
import com.nhaarman.listviewanimations.itemmanipulation.DynamicListView;
import com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.OnDismissCallback;
import edu.dartmouth.cs.apis.Shakespeare;
public class FragmentLayout extends Activity {
static ArrayAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(this, "FragmentLayout: OnCreate()", Toast.LENGTH_SHORT)
.show();
setContentView(R.layout.fragment_layout);
}
public static class DetailsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(this, "DetailsActivity", Toast.LENGTH_SHORT).show();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
if (savedInstanceState == null) {
DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction()
.add(android.R.id.content, details).commit();
}
}
}
public static class TitlesFragment extends Fragment {
boolean mDualPane;
int mCurCheckPosition = 0;
List<String> title;
DynamicListView listView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_title_dynamiclist,container);
listView = (DynamicListView) root
.findViewById(R.id.dynamiclistview);
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Toast.makeText(getActivity(), "TitlesFragment:onActivityCreated",
Toast.LENGTH_LONG).show();
if (savedInstanceState != null) {
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
title = savedInstanceState.getStringArrayList("Title");
}else{
title = new ArrayList<String>(Arrays.asList(Shakespeare.TITLES));
}
myAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_activated_1,
title);
final AlphaInAnimationAdapter animationAdapter = new AlphaInAnimationAdapter(
myAdapter);
animationAdapter.setAbsListView(listView);
listView.setAdapter(animationAdapter);
View detailsFrame = getActivity().findViewById(R.id.details);
Toast.makeText(getActivity(), "detailsFrame " + detailsFrame,
Toast.LENGTH_LONG).show();
mDualPane = detailsFrame != null
&& detailsFrame.getVisibility() == View.VISIBLE;
Toast.makeText(getActivity(), "mDualPane " + mDualPane,
Toast.LENGTH_LONG).show();
if (mDualPane) {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Make sure our UI is in the correct state.
showDetails(mCurCheckPosition);
} else {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setItemChecked(mCurCheckPosition, true);
}
listView.enableSwipeToDismiss(new OnDismissCallback() {
@Override
public void onDismiss(final ViewGroup listView,
final int[] reverseSortedPositions) {
Toast.makeText(getActivity(), "swipe detected " ,
Toast.LENGTH_LONG).show();
for (int position : reverseSortedPositions) {
// NOT WORKING!!
myAdapter.remove(position);
title.remove(position);
}
}
});
listView.setOnItemClickListener(new MyOnItemClickListener(listView));
}
private class MyOnItemClickListener implements
AdapterView.OnItemClickListener {
private final DynamicListView mListView;
MyOnItemClickListener(final DynamicListView listView) {
mListView = listView;
}
@Override
public void onItemClick(final AdapterView<?> parent,
final View view, final int position, final long id) {
//
Toast.makeText(getActivity(),
"onListItemClick position is" + position,
Toast.LENGTH_LONG).show();
showDetails(position);
//
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Toast.makeText(getActivity(), "onSaveInstanceState",
Toast.LENGTH_LONG).show();
outState.putStringArrayList("Title", new ArrayList<String>(title));
outState.putInt("curChoice", mCurCheckPosition);
}
void showDetails(int index) {
mCurCheckPosition = index;
if (mDualPane) {
listView.setItemChecked(index, true);
DetailsFragment details = (DetailsFragment) getFragmentManager()
.findFragmentById(R.id.details);
if (details == null || details.getShownIndex() != index) {
details = DetailsFragment.newInstance(index);
System.out.println(" Dual plane");
Toast.makeText(
getActivity(),
"**showDetails dual-pane: create and relplace fragment",
Toast.LENGTH_LONG).show();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else {
Intent intent = new Intent();
intent.setClass(getActivity(), DetailsActivity.class);
intent.putExtra("index", index);
startActivity(intent);
}
}
}
public static class DetailsFragment extends Fragment {
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Toast.makeText(getActivity(), "DetailsFragment:onCreateView",
Toast.LENGTH_LONG).show();
ScrollView scroller = new ScrollView(getActivity());
TextView text = new TextView(getActivity());
int padding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
.getResources().getDisplayMetrics());
text.setPadding(padding, padding, padding, padding);
scroller.addView(text);
text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
return scroller;
}
}
}
并且您的布局必须是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal" >
<fragment
android:id="@+id/titles"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
class="edu.dartmouth.cs.FragmentLayout$TitlesFragment" />
<FrameLayout
android:id="@+id/details"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/detailsElementBackground"
/>
</LinearLayout>
和标题 fragment 的布局:(fragment_title_dynamiclist.xml)
<?xml version="1.0" encoding="utf-8"?>
<com.nhaarman.listviewanimations.itemmanipulation.DynamicListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dynamiclistview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
关于android - 没有显示简单的 Android Fragment 的框架,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25964743/