2016-02-17 37 views
1

Diagram of Hierarchical View consisting of Android Activity with Fragments我如何使用BaseAdapter

下圖說明了我的活動的複雜子片段添加到Android的一個片段。有多個(在這種情況下是3個)需要動態加載的片段層。使用LinearListView加載重複片段,這是我在此處找到的視圖庫:https://github.com/frankiesardo/LinearListView。這允許列表像ListView一樣加載,但是避免了在ScrollView中有ListView的問題。

下面是一些示例代碼:

line_item_list.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:id="@+id/line_item_list"> 

    <TextView 
    android:layout_width="171dp" 
    android:layout_height="wrap_content" 
    android:text="LineItem List" 
    android:id="@+id/line_item_list_text" /> 

    <com.linearlistview.LinearListView 
    android:id="@+id/line_item_wrapper" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:divider="#f00" 
    android:orientation="vertical" 
    android:showDividers="middle" 
    app:dividerThickness="16dp" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/tools"/> 
</LinearLayout> 

line_item.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:id="@+id/line_item"> 

    <TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="my line item." 
    android:id="@+id/line_item_text" 
    android:layout_gravity="center_horizontal" /> 

    <!-- notes child items go here --> 

</LinearLayout> 

LineItemFragment.java加載片段與適配器(LINEITEM在此代碼與上圖中的「零件」一起顯示。)

public class LineItemFragment extends Fragment { 
    LineItemAdapter adapter; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 


    LinearListView lineItems = (LinearListView)container.findViewById(R.id.line_item_wrapper); 
    adapter = new LineItemAdapter(this.getContext(), getChildFragmentManager()); 
    lineItems.setAdapter(adapter); 

    return null; 

    } 
} 

LineItemAdapter.java

public class LineItemAdapter extends BaseAdapter{ 

    ArrayList<String> lineItems = new ArrayList<String>(); 
    Context context; 
    FragmentManager fm; 


    public LineItemAdapter(Context context, FragmentManager fragmentManager) { 
    this.context = context; 
    lineItems.add("Item A"); 
    lineItems.add("Item B"); 
    lineItems.add("Item C"); 
    this.fm = fragmentManager; 
    } 

    @Override 
    public int getCount() { 
    return lineItems.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
    return lineItems.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
    return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) 
       .inflate(R.layout.line_item, parent, false); 
    } 
     ((TextView)convertView.findViewById(R.id.line_item_text)).setText(getItem(position).toString()); 


    // *** The getView method could load the child fragments 
    return convertView; 
    } 
} 

在此之前的文件(***),我目前想的getView方法應加載下一個級別的子片段,但一切我都試過沒有奏效。看起來佈局還沒有膨脹,所以我不能將子視圖添加到它。

我的問題是,「我如何從getView中添加子片段?」或者,也許我正在討論這個錯誤。

這裏是什麼,我已經試過了一個例子:

getView方法(***)在lineItemAdapter.java:

. 
. 
. 

    LinearLayout notes = (LinearLayout) ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) 
      .inflate(R.layout.line_item, parent, false); 

    LinearLayout b = (LinearLayout)((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) 
      .inflate(R.layout.note_list, notes).getRootView(); 

    NoteListFragment noteListFragment = new NoteListFragment(); 
    fm.beginTransaction().add(b.getId(), noteListFragment).commit(); 
. 
. 
. 

而且我得到了這樣的一個例外。

E/AndroidRuntime: FATAL EXCEPTION: main 

Process: com.example.myapplication, PID: 12207 

java.lang.RuntimeException: Unable to start activity 
ComponentInfo{com.example.myapplication/com.example.myapplication.DetailActivity}: java.lang.IllegalStateException: Fragment does not have a view 
                      at 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
                      at 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
. 
. 
. 

在此先感謝。

編輯

我需要一個片段添加到XML,即:

line_item.xml ...新的節點:

<fragment android:name="com.example.noteListFragment" 
      android:id="@+id/note_list_fragment" 
      android:layout_weight="1" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" /> 
+0

不同類你不能'getView()'屬於一個片段中添加片段。你從你的活動中創建一個片段。 – mt0s

+0

檢查此答案也http://stackoverflow.com/a/13221546/423980 – mt0s

+0

欣賞快速反應。很有幫助,但您將如何解決從活動中請求片段的多個層的複雜性?我能否將convertview傳遞給Activity中的方法而不會導致內存泄漏,以便可以添加子項? – dwaz

回答

0

在我搬走結束從碎片中爲此目的,並刪除通貨膨脹代碼。相反,我使用xml中的includes加載了相同的佈局結構,所以我不必構建比我已有的更大的xml文件。

對於我要放入片段的功能,我放置在演示者類中,然後使用ButterKnife的視圖注入將演示者綁定到視圖中的適當級別。

我仍在使用事件總線在層之間進行通信,如@ mt0s建議。

下面是一些代碼來幫助你,如果你想要去的這個方向:

使用包括我可以把整個結構在一起,保持每層佈局自己的XML文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/activity_workorder" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:fitsSystemWindows="true" 
> 
    <LinearLayout 
     android:id="@+id/workorder_detail_container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical"> 
     <include layout="@layout/workorder_header"/> <!-- include other layouts --> 
     <include layout="@layout/workorder_service_items"/> 
    </LinearLayout> 
</LinearLayout> 

接着我創建了一個Presenter.class文件來設置適配器,使用ButterKnife綁定到視圖的那部分:

public class WorkOrderPresenter implements PropertyChangeListener 
{ 

    private View detailView; 
    private WorkOrder workOrder; // the object to display 
    private List<WorkorderAsset> assetList; 

    // Set your bindings to the view, passing the id from the layout. 
    @Bind(R.id.workorderasset_list) View serviceItemDetail; 
    @Bind(R.id.workorderasset_list_content) LinearListView assets; 
    @Bind(R.id.number_of_service_items) TextView numberOfServiceItems; 
    @Bind(R.id.total_value) TextView totalView; 

    WorkOrderAssetAdapter workOrderAssetAdapter; // an adapter for a child list 

    // Constructor 
    public WorkOrderPresenter(View view, WorkOrder wo, final Activity activity) 
    { 
     workOrder = wo; 
     detailView = view; 
     ButterKnife.bind(this, detailView); //this is where the binding actually happens 

     workOrderAssetContent = Provider.GetItems // Load you items for the adapter. 

     // My system gives items back asynchronously: 
     workOrderAssetContent.getWorkOrderAssets(workOrder.getWorkOrderID(), new iProvideCallback<List<WorkorderAsset>>() { 
      @Override 
      public void onSuccess(iResponse<List<WorkorderAsset>> response) { 
       assetList = response.getResponse(); 
       numberOfServiceItems.setText(String.valueOf(assetList.size())); 
       workOrderAssetAdapter = new WorkOrderAssetAdapter(activity, assetList); // construct the adapter with items. 
       assets.setAdapter(workOrderAssetAdapter); 
      } 

      @Override 
      public void onFailure(iResponse<List<WorkorderAsset>> response) { 
       Toast.makeText(activity.getApplicationContext(), R.string.ServiceItemsError, Toast.LENGTH_LONG); 

      } 
     }); 
    } 
} 

,這裏是一個適配器二張開的項目:

public class WorkOrderAssetAdapter extends BaseAdapter 
{ 
    private Activity activity; 
    private List<WorkorderAsset> workorderAssetList; 
    private static LayoutInflater inflater = null; 

    // Constructor 
    public WorkOrderAssetAdapter(Activity a, List<WorkorderAsset> items) 
    { 
     workorderAssetList = items; 
     activity = a; 
     inflater = LayoutInflater.from(activity); 
    } 

    @Override 
    public int getCount() { return workorderAssetList.size(); } 

    @Override 
    public Object getItem(int position) { return workorderAssetList.get(position); } 

    @Override 
    public long getItemId(int position) { return position; } 

    // view holder for the item 
    public static class ViewHolder extends WorkOrderAssetViewHolder 
    { 
     @Bind(R.id.line_item_text) TextView line_item_text; 
     @Bind(R.id.line_item_list) LinearListView list; 

     // Adapter, Data Provider and Presenter for the next level. 
     public WorkOrderAssetLineItemAdapter adapter; 
     public WorkOrderAssetLineItemProvider provider; 
     public WorkOrderAssetLineItemPresenter presenter; 

     private Activity activity; 
     private WorkorderAsset workOrderAsset; 

     public VehicleViewHolder(WorkorderAsset asset, final View view, Activity activity_in) 
     { 
      ButterKnife.bind(this, view); 
      workOrderAsset = asset; 
      activity = activity_in; 
      workOrderAssetLineItemContent = new WorkOrderAssetLineItemContent(((RoadFS)activity.getApplication()).getServer(), ((RoadFS)activity.getApplication()).getApplicationContext()); 
      workOrderAssetLineItemContent.getWorkOrderAssetLineItems(
        workOrderAsset.getWorkOrderID(), 
        workOrderAsset.getWorkOrderAssetID(), 
        new iProvideCallback<List<WorkorderAssetLineItem>>() { 

         @Override 
         public void onSuccess(iResponse response) { 
          list.setAdapter(new WorkOrderAssetLineItemAdapter(activity, 
            (List<WorkorderAssetLineItem>) response.getResponse(), 
            view)); 
         } 

         @Override 
         public void onFailure(iResponse response) { 

         } 
        }); 

     } 

    @Override 
    public View getView(final int position, View view, ViewGroup parent) 
    { 

     WorkorderAsset workOrderAsset; 
     workOrderAsset = workorderAssetList.get(position); 
     ViewHolder holder; 
     if (view != null) { 
      holder = (ViewHolder) view.getTag(); 
     } else { 
      view = inflater.inflate(R.layout.workorder_detail_workorderasset_vehicle, parent, false); 
      holder = new VehicleViewHolder(workOrderAsset, view, activity); 
      view.setTag(holder); 
     } 

     holder.item_text.setText(workOrderAsset.getVIN()); 

     holder.workOrderAssetLineItemContent = new WorkOrderAssetLineItemContent(((RoadFS) activity.getApplication()).getServer(), activity); 
     holder.workOrderAssetLineItemAdapter = new WorkOrderAssetLineItemAdapter(activity, WorkOrderAssetLineItemContent.workorderAssetLineItemList, view); 

     return view; 
    } 
} 

這個例子是有點不完整的,而且我還沒有一個示例項目,但希望它會幫助別人。它沒有像預期的那樣回答問題,但是嘗試了兩種方法,我認爲這是一個更好的解決方案,因爲它比處理碎片的複雜性更簡單。碎片仍將用於更改屏幕大小/方向,但片段不會用於複雜的佈局。感謝您的任何意見。

0
  1. 使用適配器

    public class TabCategory extends Fragment { 
        private ListView listView; 
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
        } 
        @Override 
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
         // Inflate the layout for this fragment 
         View tabCat=inflater.inflate(R.layout.tab_all, container, false); 
         listView = (ListView) tabCat.findViewById(R.id.listView); 
         //ADAPTER 
         CategoryList adapter = new CategoryList(getContext()); 
         listView.setAdapter(adapter); 
         return tabCat; 
        } 
    }