2013-02-15 77 views
1

我正在尋找一種優雅的方式來顯示片段上的層次結構(樹)。多個片段的樹狀視圖

我的想法是在不同的片段上顯示每個級別。通過點擊一片葉子,我可以進入層次結構中的下一個層次(如果在這裏也有漂亮的滑動動畫會很好)。最後,我會得到一個點,我有葉子,這應該導致一個細節視圖。

我已經知道樹視圖實現(如http://code.google.com/p/tree-view-list-android/),但我想要在不同的片段上有每個級別。如果在Mac文件瀏覽器中顯示大屏幕(平板電腦)上的幾個級別,也會很酷。

主要的原因是,我想要從服務器根據請求加載每個級別的數據(樹是相當大的),其次我想要有一個清晰的佈局。另一方面,我不希望每個級別的片段都分開執行,因爲深度可以從分支到分支。

我的數據當前是在表單中,每個樹節點都由具有id,名稱,TreeElementType(節點或葉子)和TreeElements列表的TreeElement對象表示爲子節點。如果這個結構不得不被修改,那將是可行的。

任何人都可以想出一個很好的方法來實現這一點?

貝斯特,埃裏克

回答

1

我終於找到了一個工作的解決方案:

我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,組織片段:

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(); 
    } 
} 
} 

To使其完成,我的自定義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的構造函數有一個帶參數的構造函數,這不是很好。
  • 當改變方向時,尋呼機跳轉到第一頁。
  • 後退按鈕不會轉到上一頁。