I was learning about fragments and I used this sample code given the developers website. I added this http://nhaarman.github.io/ListViewAnimations/#getting-started For enabling swipe and remove operations on the list.
I have 2 problems 1. When my phone is in landscape mode I cannot seem to see the detail pane at all. 2. I can’t remove the object after swiping, it appears as soon as the swipe is complete
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>
FragmentLayout
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;
}
}
}
- When my phone is in landscape mode I cannot seem to see the detail pane at all.
you mess up listfragment and dynamiclist. listfragment has a list by itself and in some part of your code you manipulate dynamiclist and in other part you manipulate listfragment's list. so in order to use the dynamiclist you must use fragment instead of listFragment and you must create separate layout for it and put your dynamic list in that.
- I can’t remove the object after swiping, it appears as soon as the swipe is complete
because myAdapter.remove(position);
removes the view of your title and you must remove the data set behind that but your data set is String array so you can not remove from it, what should you do? you must create a List
and pass it to your adapter and then after the sweep occurred you must remove the data at the specified position. so your code must change and be something like:
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;
}
}
}
and your layout must be:
<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>
and the layout of title 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" />