我终于找到了一个可行的解决方案:
我的 TreeElement 类如下所示:
public class TreeElement
{
private int id;
private TreeElementType type;
private String name;
/**
* List that holds a set of all the children tree elements.
*/
private List<TreeElement> children = new ArrayList<TreeElement>();
/**
* List that holds a set of the courses associated to the TreeElement.
*
* @see Course
*/
private List<Course> courses = new ArrayList<Course>();
public TreeElement()
{
this.type = TreeElementType.NODE;
this.children = new ArrayList<TreeElement>();
}
public TreeElement(int id)
{
this();
this.id = id;
}
public TreeElement(int id, String name)
{
this( id );
this.name = name;
}
public TreeElement(int id, TreeElementType type, String name)
{
this( id, name );
this.type = type;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public TreeElementType getType()
{
return type;
}
public void setType(TreeElementType type)
{
this.type = type;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public List<TreeElement> getChildren() {
return children;
}
public void setChildren(List<TreeElement> children) {
this.children = children;
}
public void addChild(TreeElement child) {
this.children.add(child);
}
public void addChildren(List<TreeElement> children) {
this.children.addAll(children);
}
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
public void addCourse(Course course) {
this.courses.add(course);
}
public void addCourses(List<Course> courses) {
this.courses.addAll(courses);
}
}
因此,这些 TreeElements 会生成一个分层树。每个 TreeElement 还可以包含一些我想在树中显示的课程。
包含页面的所有寻呼机的片段是这个:
public class BrowserSectionFragment extends Fragment {
private BrowserFragmentPagerAdapter mAdapter;
private ViewPager mPager;
private List<Fragment> fragments = new Vector<Fragment>();
public BrowserSectionFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_browser, container, false);
/*
* Add the root TreeElement-fragment, holding the categories of lowest
* level.
*/
fragments.add(new BrowserPageFragment(this,TreeContainer.getTreeElement(TreeContainer.ROOT_ID)));
mAdapter = new BrowserFragmentPagerAdapter(this.getFragmentManager(), fragments);
mPager = (ViewPager) view.findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageSelected(int arg0) {
while (arg0 < fragments.size()-1) {
fragments.remove(fragments.size()-1);
}
/*
* notify the adapter of the changes being made
* causes the adapter to check all elements, if they are still in the
* list of fragments
*/
mAdapter.notifyDataSetChanged();
}
});
return view;
}
/**
* Adds a new fragment to the fragment manager. The data is taken from
* the children list of the TreeElement.
*
* @param clickedElement
*/
public void addFragmentFromElement(TreeElement clickedElement) {
fragments.add(new BrowserPageFragment((this),clickedElement));
mPager.setCurrentItem(fragments.size()-1, true);
}
}
现在我需要一个 PagerAdapter,在本例中是 FragmentStatePagerAdapter,来组织 Fragment:
public class BrowserFragmentPagerAdapter extends FragmentStatePagerAdapter {
/**
* List that holds all the fragments which are currently accessible
* through the Pager.
*/
private List<Fragment> mFragments;
/**
* Constructor that initializes the list of fragments.
*
* @param fm FragmentsManager
* @param fragments
*/
public BrowserFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public int getItemPosition(Object item) {
/*
* See if fragment is still in the list.
* If yes, the position in the list is returned, if not, POSITION_NONE,
* which causes the Pager to delete the related view.
*/
Fragment fragment = (Fragment) item;
int position = mFragments.indexOf(fragment);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
}
最后我实现了一个显示 ListView 的 PageFragment:
public class BrowserPageFragment extends ListFragment {
public static final String ARG_ELEMENT_ID = "element_id";
TreeElement element;
BrowserSectionFragment frag;
Context context;
public BrowserPageFragment() {
super();
}
public BrowserPageFragment( BrowserSectionFragment frag, TreeElement element ) {
this();
this.frag = frag;
this.element = element;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
/* Creating an array adapter to store the list of countries **/
BrowserListAdapter adapter = new BrowserListAdapter(inflater.getContext(),element);
/* Setting the list adapter for the ListFragment */
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Object clickedElement = l.getAdapter().getItem(position);
if (clickedElement instanceof TreeElement) {
frag.addFragmentFromElement((TreeElement) clickedElement);
} else if (clickedElement instanceof Course) {
/*
* Start a new fragment which shows a detail view of the course.
*/
Course course = (Course) clickedElement;
int courseId = course.getId();
CourseContainer.setCourse(courseId, course);
Fragment fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putInt( DetailsFragment.ARG_COURSE_NUMBER, courseId);
fragment.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
}
}
}
为了使其完整,我的自定义 ListAdapter 如下所示:
public class BrowserListAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
TreeElement element;
List<Object> elements = new ArrayList<Object>();
public BrowserListAdapter(Context context, TreeElement element) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.element = element;
elements.addAll(element.getChildren());
elements.addAll(element.getCourses());
}
@Override
public int getCount() {
return elements.size();
}
@Override
public Object getItem(int position) {
return elements.get(position);
}
@Override
public long getItemId(int position) {
Object item = elements.get(position);
if (item instanceof TreeElement) {
return ((TreeElement) item).getId();
} else if (item instanceof Course) {
return ((Course) item).getId();
}
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = (View) mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
bindView(itemView, position);
return itemView;
}
private void bindView(View itemView, int position) {
Object item = getItem(position);
String text = null;
if (item instanceof TreeElement) {
text = ((TreeElement) item).getName();
} else if (item instanceof Course) {
text = ((Course) item).getTitle();
}
itemView.setId((int) getItemId(position));
TextView title = (TextView) itemView;
title.setText(text);
}
}
也许这个解决方案可以帮助某人。这里唯一剩下的问题是:
- BrowserPageFragment 的构造函数有一个带参数的构造函数,这不是很好。
- 更改方向时,寻呼机跳到第一页。
- 后退按钮不会转到上一页。