ListView加Fragment实现Flyme4.0设置界面

来源:互联网 发布:c语言入门经典 编辑:程序博客网 时间:2024/04/30 22:43

ListView加Fragment实现Flyme4.0设置界面

使用实现了单选功能的ListView,不要问为什么不使用RecyclerView,RecyclerView真的做得不如ListView和GridView完善全面,但是RecyclerView真的是很灵活(目前发现RecyclerView有几个bug,以后再吐槽),RecyclerView也有自己的优势,这里解释一下我们为啥使用了ListView,ListView加上Fragment,点击ListView的item来切换Fragment,Fragment是可以保存状态的,使用了hide和show事务,可以根据下发的数据来创建对面的Fragment,就是创建对应的Fragment类型。下面先看看图片吧:

Flyme4.0设置界面:

Flyme4.0设置界面

我们实现的效果:

我们实现的效果

实现效果GIF:

实现效果GIF

ListView可以支持对选和单选:

tabList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);//单选tabList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);//多选

看代码之前先看一下工程结构:
java代码:
java代码
xml文件:
xml文件
要实现单选那么ListView的item的布局ViewGroup需要实现Checkable接口,下面是item_tab_list.xml

<?xml version="1.0" encoding="utf-8"?><com.example.bottommenudemo.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="80dp"    android:gravity="center_vertical"    android:orientation="horizontal">    <TextView        android:id="@+id/tabName"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="4dp"        android:clickable="false"        android:layout_centerVertical="true"        android:maxLines="1"        android:text="标题栏"        android:layout_alignParentLeft="true"        android:textColor="@android:color/white"        android:textSize="15sp" />    <CheckedTextView        android:layout_width="8dip"        android:layout_height="80dp"        android:background="@drawable/checkbox_selector"        android:gravity="center"        android:layout_alignParentRight="true"        android:paddingLeft="8dp" /></com.example.bottommenudemo.CheckableRelativeLayout>

需要把CheckedTextView这个选中flag以外的控件设置为android:clickable=”false”

下面是自定义的RelativeLayout,主要是实现了Checkable接口:

package com.example.bottommenudemo;import android.content.Context;import android.util.AttributeSet;import android.widget.Checkable;import android.widget.RelativeLayout;/** * Created by Danxx on 2016/4/29. */public class CheckableRelativeLayout extends RelativeLayout implements Checkable{    private static final int CHECKABLE_CHILD_INDEX = 1;    private Checkable child;    public CheckableRelativeLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        child = (Checkable) getChildAt(CHECKABLE_CHILD_INDEX);    }    @Override    public boolean isChecked() {        return child.isChecked();    }    @Override    public void setChecked(boolean checked) {        child.setChecked(checked);    }    @Override    public void toggle() {        child.toggle();    }}

ListView的choiceMode可以在代码中设置,也可以在xml文件中设置:

 tabList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);//单选(代码实现) android:choiceMode="singleChoice"  //单选(xml中实现)

其余的ListView使用跟一般的ListView使用是一样的,这个时候我单击ListView的item就可以实现单选功能了。

Fragment的创建我封装了一下下,FragmentFactory.java就是用来创建对应的Fragment,需要传入FragmentBean和与ListView对应的position:

package com.example.bottommenudemo;import android.os.Bundle;import android.support.v4.app.Fragment;import java.util.HashMap;/** * fragment build factory * Created by Danxx on 2016/4/28. */public class FragmentFactory {    /**fragment缓存**/    private static HashMap<String,Fragment> fragments = new HashMap<String, Fragment>();    public static Fragment buildFragment(FragmentBean data ,int pos){        Fragment fragment = null;        String id = data.getID();        String name = data.getName();        int position = data.getPosition();        String url = data.getUrl();        fragment = fragments.get(String.valueOf(pos));        if(fragment != null){            return fragment;        }        if(id.equalsIgnoreCase(Common.BACKGROUND)){            fragment = new FragmentSetBackground();        }else if(id.equalsIgnoreCase(Common.RECOMMEND)){            fragment = new FragmentSetRecommend();        }else if(id.equalsIgnoreCase(Common.SCREENSAVER)){            fragment = new FragmentSetScreensaver();        }else if(id.equalsIgnoreCase(Common.ABOUT)){            fragment = new FragmentSetAbout();        }        Bundle bundle = new Bundle();        bundle.putString("id" ,id);        bundle.putString("name" ,name);        bundle.putInt("position", position);        bundle.putString("url" , url);        if(fragment != null){            //传递简单的参数            fragments.put(String.valueOf(pos), fragment);            fragment.setArguments(bundle);        }        return fragment;    }}

直接看MainActivity的代码:

package com.example.bottommenudemo;import android.content.Context;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentTransaction;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    private ListView tabList;    private List<FragmentBean> fragmentData = new ArrayList<FragmentBean>();    private MyAdapater mAdapter;    private int lastPosition = -1;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_2_main);        Log.d("danxx", "onCreate--->");        tabList = (ListView) findViewById(R.id.tabList);        /************************填充假数据,可以根据服务器下发的数据来初始化数据(一定得给出模板类型layout_code)*************************/        FragmentBean backGround = new FragmentBean(Common.BACKGROUND,0,"背景0","http://www.dusa.com/da/index.jsp");        fragmentData.add(backGround);        FragmentBean recommend = new FragmentBean(Common.RECOMMEND,1,"推荐>1","http://www.dusa.com/food/list.jsp");        fragmentData.add(recommend);        FragmentBean screensaver = new FragmentBean(Common.SCREENSAVER,2,"背景>2" ,"http://www.meitu.com/pic/con.jsp");        fragmentData.add(screensaver);        FragmentBean about = new FragmentBean(Common.ABOUT,3,"关于>3","http://www.alibaba.com/good/index.php");        fragmentData.add(about);        FragmentBean backGround2 = new FragmentBean(Common.BACKGROUND,4,"背景>4","http://www.dusa.com/da/index.jsp");        fragmentData.add(backGround2);        FragmentBean about2 = new FragmentBean(Common.ABOUT,5,"关于>5","http://www.alibaba.com/good/index.php");        fragmentData.add(about2);        FragmentBean recommend2 = new FragmentBean(Common.RECOMMEND,6,"推荐>6","http://www.dusa.com/food/list.jsp");        fragmentData.add(recommend2);        FragmentBean screensaver2 = new FragmentBean(Common.SCREENSAVER,7,"背景>7" ,"http://www.meitu.com/pic/con.jsp");        fragmentData.add(screensaver2);        FragmentBean about3 = new FragmentBean(Common.ABOUT,8,"关于>8","http://www.alibaba.com/good/index.php");        fragmentData.add(about3);        mAdapter = new MyAdapater(this , fragmentData);        tabList.setAdapter(mAdapter);        tabList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);        mAdapter.notifyDataSetChanged();        /**根据用户点击来切换fragment**/        tabList.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                Log.d("danxx" ,"position-->"+position);                if(lastPosition == position){                    return;                }                if(lastPosition != -1){                    Fragment fromFragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(lastPosition));                    if(fromFragment==null){                        fromFragment = buildFragment(lastPosition);                    }                    Fragment toFragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(position));                    if(toFragment == null){                        toFragment = buildFragment(position);                    }                    switchContent(fromFragment ,lastPosition ,toFragment ,position);                }else{                    /*第一次显示fragment*/                    getSupportFragmentManager().beginTransaction().                        add(R.id.content ,FragmentFactory.buildFragment(mAdapter.getItemData(position) ,position) ,String.valueOf(position)).commit();                }                lastPosition = position;            }        });    }    public Fragment buildFragment(int position){        /**根据模板类型layout_code的不同来创建对应的fragment**/        return FragmentFactory.buildFragment(mAdapter.getItemData(position) ,position);    }    /**     * 切换显示的fragment     * @param fromFragment     * @param fromPos     * @param toFragment     * @param toPos     */    public void switchContent(Fragment fromFragment ,int fromPos, Fragment toFragment ,int toPos) {        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();        if (!toFragment.isAdded()) {    // 先判断是否被add过            transaction.hide(fromFragment).add(R.id.content, toFragment ,String.valueOf(toPos)).commit(); // 隐藏当前的fragment,add下一个到Activity中        } else {            transaction.hide(fromFragment).show(toFragment).commit(); // 隐藏当前的fragment,显示下一个        }    }    class MyAdapater extends BaseAdapter{        private List<FragmentBean> mData;        private Context mContext;        public MyAdapater(Context context , List<FragmentBean> data){            this.mContext = context;            this.mData = data;        }        @Override        public int getCount() {            return mData.size();        }        @Override        public Object getItem(int position) {            return mData.get(position);        }        public FragmentBean getItemData(int position){            return mData.get(position);        }        @Override        public long getItemId(int position) {            return position;        }        /**         * 数据不会很多,所以没有使用ViewHolder复用         * @param position         * @param convertView         * @param parent         * @return         */        @Override        public View getView(final int position, View convertView, ViewGroup parent) {            Log.d("danxx" ,"getView_position-->"+position);            final View view =  LayoutInflater.from(mContext).inflate(R.layout.item_tab_list , null);            TextView tabName = (TextView) view.findViewById(R.id.tabName);            tabName.setText(mData.get(position).getName());            return view;        }    }}

MainActivity.java需要留意的就是,我们在切换Fragment的时候并没有把所有的Fragment都找到,然后hide掉,我觉得这样真的很没有必要,耗时耗力,还显得很蠢,我使用了switchContent方法来做这个操作,从一个Fragment切换到另一个Fragment,就直接是hide现在看到的Fragment,show我们需要的Fragment,这样我们切换Fragment就总是对两个Fragment做处理,是不是简洁了很多?

    /**     * 切换显示的fragment     * @param fromFragment     * @param fromPos     * @param toFragment     * @param toPos     */    public void switchContent(Fragment fromFragment ,int fromPos, Fragment toFragment ,int toPos) {        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();        if (!toFragment.isAdded()) {    // 先判断是否被add过            transaction.hide(fromFragment).add(R.id.content, toFragment ,String.valueOf(toPos)).commit(); // 隐藏当前的fragment,add下一个到Activity中        } else {            transaction.hide(fromFragment).show(toFragment).commit(); // 隐藏当前的fragment,显示下一个        }    }

完整的代码请看GitHub:FragmentSwitchDemo

0 0