Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ListView加Fragment實現Flyme4.0設置界面

ListView加Fragment實現Flyme4.0設置界面

編輯:關於Android編程

使用實現了單選功能的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




    

    


需要把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 fragments = new HashMap();

    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 fragmentData = new ArrayList();
    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 mData;
        private Context mContext;

        public MyAdapater(Context context , List 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

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved