如何使用没有ListFragment的列表创建片段

时间:2014-11-06 15:55:12

标签: android android-fragments android-listview android-animation android-listfragment

关于这个主题的文献非常少,谷歌的文档没有说明使用ListFragment扩展名对片段列表进行自定义(listviewanimation)的可能性。因此,我会问这个问题,然后尽可能地回答这个问题,因为我也想要50个声望点,所以我终于可以通过评论感谢本网站上的优秀解释员了。

出于本评论的目的,我将使用listviewanimation lib中的组件:

https://github.com/nhaarman/ListViewAnimations

答案:

我们需要设置4个组件才能拥有一个带有listview组件的正确片段

  • 活动通过活动的片段管理器创建片段。
  • Fragment类将是非常基本的片段内容,它将具有listview,它将使用arrayadapter链接该listview。
  • 适用于我们目的的Adapter类只处理字符串。
  • 在ADAPTER CLASS中,最后的第四个组件将是一个viewholder类,它将允许更快地创建列表中的行,因为每个行的各个组件将被包装在一个允许更快的对象实例化的类中。 / LI>

好的,首先是活动的代码,这个代码可以通过按钮点击或其他一些事件来调用。当事件发生时,将创建片段管理器,并且片段管理器将创建一个事务,这是一种奇特的说法,管理器将在活动和新形成的片段之间进行通信,以便正确设置所有内容。

以下是应该在事件发生的活动中放置的代码:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
GenericFragment fragment = new GenericFragment();
fragmentTransaction.add(R.id.pager, fragment); 
//Replace R.id.pager with the view that you want your fragment to go in.
fragmentTransaction.commit();

就是这样!不是很糟糕,是吗?现在让我们转到GenericFragment类,您可以创建一个不同的名称。我不会为此发布所有代码,但我会逐步完成具有listview的片段类所需的一切:

  • 让你的Fragment类扩展Fragment
  • 为此类设置一个空构造函数(google需要它... -__-)

创建一个newInstance方法,当从活动创建片段的“新实例”时,该方法将处理从活动到片段的数据传递:

我会帮助你解决这个问题:

public static GenericFragment newInstance(String StuffYouWantGetsPassedFromActivityToFragment) {
    GenericFragment GenericFragment = new GenericFragment();

    Bundle args = new Bundle();
    GenericFragment.setArguments(args);

    return GenericFragment;
}

再次没那么糟,对吧?我们还没有完成,我们仍然需要覆盖onCreateView和onCreate,然后我们将完成这个简单的步骤!

关于onCreateView:

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.generic_fragment_layout, container, false);

    addGoalButton = (Button) view.findViewById(R.id.btn_newRow); //Created for testing purposes
    lv = (ListView) view.findViewById(R.id.GenericListView);

    addGoalButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) { //Created for testing purposes
            genericAdapter.add("Goal");
            genericAdapter.notifyDataSetChanged();
        }

    });

    lv.setAdapter(genericAdapter);
    return view;
}

上面的代码可能看起来像一个怪物,你是对的!高级概述是您获得了希望片段看起来像的布局文件。从那个布局文件中,你得到listview并创建一个变量来保存它。然后你调用listView的'setAdapter'方法来添加下一步,即适配器类。出于测试目的,我添加了该按钮,以便您可以在心理上扩展本教程l8er。 (如果您只想列表,请删除所有按钮代码)

好的,片段类的最后一步:重写OnCreate!

OnCreate方法是您想要实例化所有私有变量的地方,例如genericAdapter变量或您希望在Fragment类的多个部分上使用的任何内容。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ArrayList<String> exampleItemList = new ArrayList<String>();
    exampleItemList.add("item1");
    exampleItemList.add("item2");
    exampleItemList.add("item3");
    exampleItemList.add("item4");
    exampleItemList.add("item5");
    exampleItemList.add("item6");
    exampleItemList.add("item7");
    exampleItemList.add("item8");
    exampleItemList.add("item9");
    exampleItemList.add("item10");
    exampleItemList.add("item11");
    exampleItemList.add("item12");
    genericAdapter = new genericAdapter(getActivity(), 0, exampleItemList);

    setHasOptionsMenu(true); // Allows the fragment to change the menu buttons
}

我将示例项添加到arrayList中,以使本教程更加透明地了解数据的来源以及数据的来源。

就是这样!你的片段已经完成了!我保证,它快要结束了。

让我们一起敲出最后两个步骤,创建一个扩展ArrayAdapter的GenericAdapter类,并有一个私有的内部ViewHolder类来包装所有布局组件:

 public class GenericAdapter extends ArrayAdapter<String>

LayoutInflater layoutInflater;

//Used to get the correct LayoutInflater to inflate each row item
public GenericAdapter(Context context, int resource, List<String> objects) {
    super(context, 0, objects);
    layoutInflater = layoutInflater.from(context);
}


/**
 * @param position The position in the list to get the data for that row item.
 * @param convertView The view for the row item that will be shown in the list.
 * @param parent Having this object allows you to use the LayoutInflater for the parent.
 * @return
 */
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    final GenericViewHolder GenericViewHolder;
    final String item = getItem(position);

    if(convertView == null){
        LinearLayout rootView = (LinearLayout) layoutInflater.inflate(R.layout.item_row, parent, false);
        genericViewHolder = genericViewHolder.create(rootView);
        rootView.setTag(genericViewHolder);
    }
    else{
        genericViewHolder = (genericViewHolder) convertView.getTag();
    }

    genericViewHolder.textView.setText(item);

    return genericViewHolder.rootView;
}

/**
 * ViewHolder's allow for a single object to maintain a Goal row item, so that the row item
 * doesn't have to create each individual component (textview layout etc.) each time the
 * row object is created/recreated. Allows for fast scrolling with little latency.
 */
private static class GenericViewHolder {
    public final LinearLayout rootView;
    public final GripView gripView;
    public final TextView textView;


    private GoalViewHolder(LinearLayout rootView, GripView gripView, TextView textView) {
        this.rootView = rootView;
        this.gripView = gripView;
        this.textView = textView;
    }

    public static GoalViewHolder create(LinearLayout rootView){
        TextView textView = (TextView)rootView.findViewById(R.id.list_row_draganddrop_textview);
        GripView gripView = (GripView)rootView.findViewById(R.id.list_row_draganddrop_touchview);
        return new GenericViewHolder(rootView, gripView, textView);
    }
}

}

这又是一个怪物,让我们看一下高级概述,我们创建了一个适配器类,以及一个适用于要使用的适配器类的viewholder类。在适配器的构造函数中,我们得到了一个layoutinflater来帮助扩展每一行的项目。然后,我们创建了getView方法,该方法在您的应用程序中被调用了数千次,因为它处理了每个行在用户可以看到时出现。 getView方法查看要转换为行的视图是否为null。如果是,它将创建一个新的数据条目(一个视图),但是如果它不是null,那么该视图持有者已经被创建,所以我们已经得到了视图中的任何东西,这样我们就不必创建一个新的行项目。

唷!我不希望你理解任何这些,但恭喜你。

好的就是这样。您应该进行设置,并且当您调用活动的事件时,片段将显示在包含片段的任何视图中。我会在我的答案中发布我的xml文件,以便我可以获得那些美味的赞成(或者不是,我可能完全不正确,但这对我有用!)

享受生活,不要放弃!

1 个答案:

答案 0 :(得分:0)

活动xml,其中大部分与读者无关,但片段的容器视图是寻呼机:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<!--Navigation Drawer Still Under Construction-->
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         The drawer is given a fixed width in dp and extends the full height of
         the container. A solid background is used for contrast
         with the content view. -->

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#ffff"/>
</android.support.v4.widget.DrawerLayout>
<!--Navigation Drawer Still Under Construction-->


<!--Customizations on README at: https://github.com/astuetz/PagerSlidingTabStrip-->
<com.astuetz.PagerSlidingTabStrip
    android:id="@+id/tabs"
    android:layout_width="wrap_content"
    android:layout_height="48dip"
    app:pstsShouldExpand="true"
    app:pstsIndicatorHeight="5dip"
    app:pstsDividerPadding="0dip"
    app:pstsDividerColor="#ff6d00"
    app:pstsUnderlineColor="#ff5722"
    app:pstsIndicatorColor="#ff5722"/>

<!--To scale the viewpager vertically, android:layout_above="@+id/[viewname]" -->
<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/tabs"
    tools:context=".MainActivity" />

</RelativeLayout>

片段的xml布局:

<?xml version="1.0" encoding="utf-8"?>



<Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="New Item"
    android:id="@+id/btn_newItem"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<com.nhaarman.listviewanimations.itemmanipulation.DynamicListView
    android:id="@+id/GenericListView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_above="@+id/btn_newGoal" />

特定的行项目:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:ignore="UseCompoundDrawables">

<com.nhaarman.listviewanimations.itemmanipulation.dragdrop.GripView
    android:id="@+id/list_row_draganddrop_touchview"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:color="@android:color/darker_gray"
    android:paddingBottom="4dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:paddingTop="4dp" />

<TextView
    android:id="@+id/list_row_draganddrop_textview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="sans-serif-light"
    android:gravity="center_vertical"
    android:minHeight="48dp"
    android:textColor="?android:attr/textColorSecondary"
    android:textSize="20sp"
    tools:ignore="UnusedAttribute" />
</LinearLayout>

第二个代码片段的布局部分被切断了,SO与我的ctrl K'ing不一致,但是它的长短不一样,无所谓,因为listview就在那里,所以无论您将其置于线性布局还是相对布局中都无关紧要。

祝你好运兄弟的快乐编码