Android Studio - 第四十八期 模块ViewPager+Fragment

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Studio - 第四十八期 模块ViewPager+Fragment相关的知识,希望对你有一定的参考价值。

    最近一直在review撸撸的代码,发现了一种模块的写法,非常不错,独立出来,希望能帮到你~

    如果你遇到这样的页面,怎么办,不会把所有代码都写到一个页面中吧~,这样看你代码的人会骂死你的吧~我想~而且如果不同的版本要用不同的位置,大小也不一样,难道你要重新布局嘛~这都是开发中需要纠结的,下面就开始正题了,这是利用了以前讲过的多版本打版以及配置多Fragment加载巧妙的解决了复杂的页面逻辑,我数了数,首页代码不到一百行,厉害吧~哈哈哈哈~

    技术分享

    技术分享

    技术分享

    在写这样的页面之前给大家介绍一下怎么写一个页面模块代码。

    demo1:单Activity页面多模块单版本

    Demo1FragmentFactory:

package com.example.p031_mokuaihua_viewpager_fragment.demo1.factorys;

import android.support.v4.util.SparseArrayCompat;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo1.fragments.Demo1Fragment1;
import com.example.p031_mokuaihua_viewpager_fragment.demo1.fragments.Demo1Fragment2;


/**
 * Created by shining on 2017/2/27 0027.
 */

public class Demo1FragmentFactory {
    private static SparseArrayCompat<Class<? extends BaseFragment>> sIndexFragments = new SparseArrayCompat<>();

    static {

        sIndexFragments.put(R.id.demo1_page_0_item_0, Demo1Fragment1.class);//模块1
        sIndexFragments.put(R.id.demo1_page_0_item_1, Demo1Fragment2.class);//模块2

    }

    public static Class<? extends BaseFragment> get(int id) {
        if (sIndexFragments.indexOfKey(id) < 0) {
            throw new UnsupportedOperationException("cannot find fragment by " + id);
        }
        return sIndexFragments.get(id);
    }

    public static SparseArrayCompat<Class<? extends BaseFragment>> get() {
        return sIndexFragments;
    }
}

    ComFragmentHelper:

package com.example.p031_mokuaihua_viewpager_fragment.utils;

import android.os.Bundle;
import android.support.v4.app.Fragment;

/**
 * Created by shining on 2016/12/21 0021.
 */

public class ComFragmentHelper {
    /**
     * 新建fragment实例
     * @param fragmentKlass
     * @param bundle
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Fragment> T newFragment(Class<T> fragmentKlass, Bundle bundle) {
        T res = null;
        try {
            res = fragmentKlass.newInstance();
            if (bundle != null) {
                res.setArguments(bundle);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 根据fragment的完整包名+名称实例化fragment
     * @param className
     * @param bundle
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Fragment> T newFragment(String className, Bundle bundle) {
        T res = null;
        try {
            res = (T) Class.forName(className).newInstance();
            if (bundle != null) {
                res.setArguments(bundle);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return res;
    }
}

    Demo1Fragment1:

package com.example.p031_mokuaihua_viewpager_fragment.demo1.fragments;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexNetFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo1.Demo1Activity;

/**
 * Created by shining on 2017/8/14.
 */

public class Demo1Fragment1 extends BaseIndexNetFragment {


    @Override
    public void call(Object value) {

    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo1_fragment1;
    }

    @Override
    protected void setup(View rootView, @Nullable Bundle savedInstanceState) {
        super.setup(rootView, savedInstanceState);
        rootView.findViewById(R.id.tv1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SendToFragment("demo1的fragment1页面");
            }
        });
    }

    /**
     * 页面传值操作部分
     *
     * @param id1
     */
    private void SendToFragment(String id1) {
        //举例
//        IndexFoodFragmentUpdateIds iff = new IndexFoodFragmentUpdateIds();
//        iff.setFood_definition_id(id1);
//        iff.setFood_name(id2);
        if (getActivity() != null && getActivity() instanceof Demo1Activity) {
            ((Demo1Activity) getActivity()).callFragment(id1, Demo1Fragment2.class.getName());
        }
    }
}

    Demo1Fragment2:

package com.example.p031_mokuaihua_viewpager_fragment.demo1.fragments;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexNetFragment;
import com.example.p031_mokuaihua_viewpager_fragment.utils.ToastUtil;

/**
 * Created by shining on 2017/8/14.
 */

public class Demo1Fragment2 extends BaseIndexNetFragment {

    @Override
    public void call(Object value) {
        String ids = (String) value;
        ToastUtil.showToastShort(ids);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo1_fragment2;
    }

    @Override
    protected void setup(View rootView, @Nullable Bundle savedInstanceState) {
        super.setup(rootView, savedInstanceState);

    }
}

    这里注意Fragment之间如果需要通信,可以用下面的方法:

 /**
     * 页面传值操作部分
     *
     * @param id1
     */
    private void SendToFragment(String id1) {
        //举例
//        IndexFoodFragmentUpdateIds iff = new IndexFoodFragmentUpdateIds();
//        iff.setFood_definition_id(id1);
//        iff.setFood_name(id2);
        if (getActivity() != null && getActivity() instanceof Demo1Activity) {
            ((Demo1Activity) getActivity()).callFragment(id1, Demo1Fragment2.class.getName());
        }
    }
    
    //接收传值处理逻辑bufen
    @Override
    public void call(Object value) {
        String ids = (String) value;
        ToastUtil.showToastShort(ids);
    }

    Demo1Activity:

package com.example.p031_mokuaihua_viewpager_fragment.demo1;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.util.SparseArrayCompat;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseActivity;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo1.factorys.Demo1FragmentFactory;
import com.example.p031_mokuaihua_viewpager_fragment.utils.ComFragmentHelper;

public class Demo1Activity extends BaseActivity implements OnClickListener {



    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo1;
    }

    @Override
    protected void setup(@Nullable Bundle savedInstanceState) {
        super.setup(savedInstanceState);
        findview();
        onclickListener();
        doNetWork();
    }

    private void doNetWork() {

    }

    private void onclickListener() {

    }

    private void findview() {
        setupFragments();
    }


    /**
     * 初始化首页fragments
     */
    private void setupFragments() {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        SparseArrayCompat<Class<? extends BaseFragment>> array = Demo1FragmentFactory.get();//一个版本模式bufen
        int size = array.size();
        BaseFragment item;
        for (int i = 0; i < size; i++) {
            item = ComFragmentHelper.newFragment(array.valueAt(i), null);
            ft.replace(array.keyAt(i), item, item.getClass().getName());
        }
        ft.commitAllowingStateLoss();
    }

    @Override
    public void onClick(View v) {

    }

    /**
     * fragment间通讯bufen
     *
     * @param value 要传递的值
     * @param tag   要通知的fragment的tag
     */
    public void callFragment(Object value, String... tag) {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment;
        for (String item : tag) {
            if (TextUtils.isEmpty(item)) {
                continue;
            }

            fragment = fm.findFragmentByTag(item);
            if (fragment != null && fragment instanceof BaseIndexFragment) {
                ((BaseIndexFragment) fragment).call(value);
            }
        }
    }
}

    效果如下图:

    技术分享

    demo2:单Activity页面多模块多版本

    Demo2Config1:

package com.example.p031_mokuaihua_viewpager_fragment.demo2.configs;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.v4.util.SparseArrayCompat;
import android.text.TextUtils;

import com.example.p031_mokuaihua_viewpager_fragment.applications.DemoApplication;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.utils.MyLogUtil;


/**
 * <p>function: </p>
 * <p>description:  </p>
 * <p>history:  1. 2017/3/23</p>
 * <p>Author: geek</p>
 * <p>modification:</p>
 */
public class Demo2Config1 {

    private static final String INDEX_META_DATA = "DEMO2_CONFIG";

    /** viewpager页大小*/
//    public static int PAGE_COUNT;
    /** viewpager每页的itemview id*/
//    public static String PAGE_ID;

    /** 默认显示第几页*/
//    public static int DEFAULT_PAGE_INDEX;

    /**
     * fragment配置
     */
    private static SparseArrayCompat<Class<? extends BaseFragment>> sIndexFragments = new SparseArrayCompat<>();

    public static void config() {
        Context ctx = DemoApplication.get();
        ApplicationInfo info = null;

        try {
            info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        if (info == null) {
            throw new UnsupportedOperationException();
        }

        String klassName = info.metaData.getString(INDEX_META_DATA);
        if (TextUtils.isEmpty(klassName)) {
            throw new UnsupportedOperationException("please config " + INDEX_META_DATA + " value");
        }

        if (klassName.startsWith(".")) {
            klassName = DemoApplication.get().getPackageName() + klassName;
        }

        MyLogUtil.d("geek", klassName);

        try {
            Class<?> klass = Class.forName(klassName);
            klass.getDeclaredMethod("setup").invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Class<? extends BaseFragment> getFragment(int id) {
        if (sIndexFragments.indexOfKey(id) < 0) {
            throw new UnsupportedOperationException("cannot find fragment by " + id);
        }
        return sIndexFragments.get(id);
    }

    public static SparseArrayCompat<Class<? extends BaseFragment>> getFragments() {
        return sIndexFragments;
    }
}

    Demo2Factory1:

package com.example.p031_mokuaihua_viewpager_fragment.demo2.factorys;

import android.support.v4.util.SparseArrayCompat;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo2.configs.Demo2Config1;
import com.example.p031_mokuaihua_viewpager_fragment.demo2.fragments.Demo2Fragment1;
import com.example.p031_mokuaihua_viewpager_fragment.demo2.fragments.Demo2Fragment2;

public class Demo2Factory1 {

    public static void setup() {
//        IndexConfig.PAGE_COUNT = 3;
//        IndexConfig.PAGE_ID = "old_pager_index_";
//        IndexConfig.DEFAULT_PAGE_INDEX = 1;
        registerFragments(Demo2Config1.getFragments());
    }

    private static void registerFragments(SparseArrayCompat<Class<? extends BaseFragment>> sIndexFragments) {
        sIndexFragments.put(R.id.demo2_page_0_item_1, Demo2Fragment1.class);//菜谱
        sIndexFragments.put(R.id.demo2_page_0_item_2, Demo2Fragment2.class);//视频

    }
}

    build.gradle:(多版本打版)

def currentMode = flavor.versionName.split("_")[3]
def currentEnvironment = flavor.versionName.split("_")[1]
def stValue = true
// t == currentEnvironment 以前的判断条件
if (currentEnvironment.endsWith("T")) {//判断是否为测试版 是否以T结尾
    stValue = false
} else {
    stValue = true
}
if (currentMode == demo1) {
    flavor.manifestPlaceholders = [DEMO2_CONFIG_VALUE: ".demo2.factorys.Demo2Factory1", STATISTICS_VALUE: stValue]
} else if (currentMode == demo2) {
    flavor.manifestPlaceholders = [DEMO2_CONFIG_VALUE: ".demo2.factorys.Demo2Factory2", STATISTICS_VALUE: stValue]
}

    Demo2Activity:

package com.example.p031_mokuaihua_viewpager_fragment.demo2;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.util.SparseArrayCompat;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.applications.ConstantNetUtil;
import com.example.p031_mokuaihua_viewpager_fragment.applications.NetConfig;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseActivity;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo2.configs.Demo2Config1;
import com.example.p031_mokuaihua_viewpager_fragment.demo2.configs.Demo2Config2;
import com.example.p031_mokuaihua_viewpager_fragment.utils.ComFragmentHelper;

public class Demo2Activity extends BaseActivity implements OnClickListener{


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {
            Demo2Config1.config();
        } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {
            Demo2Config2.config();
        }
        super.onCreate(savedInstanceState);
        setupFragments();
        findview();
        onclickListener();
        doNetWork();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo2;
    }

    @Override
    protected void setup(@Nullable Bundle savedInstanceState) {
        super.setup(savedInstanceState);
//        setupFragments();
//        findview();
//        onclickListener();
//        doNetWork();
    }

    /**
     * 初始化首页fragments
     */
    private void setupFragments() {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        //TODO 多版本模式bufen
        SparseArrayCompat<Class<? extends BaseFragment>> array = which_version_fragment_config();//
        int size = array.size();
        BaseFragment item;
        for (int i = 0; i < size; i++) {
            item = ComFragmentHelper.newFragment(array.valueAt(i), null);
            ft.replace(array.keyAt(i), item, item.getClass().getName());
        }
        ft.commitAllowingStateLoss();
    }

    private SparseArrayCompat<Class<? extends BaseFragment>> which_version_fragment_config() {
       if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {
            return Demo2Config1.getFragments();
        } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {
            return Demo2Config2.getFragments();
        }
        return Demo2Config1.getFragments();
    }

    private void doNetWork() {

    }

    private void onclickListener() {

    }

    private void findview() {

    }

    @Override
    public void onClick(View v) {

    }


    /**
     * fragment间通讯bufen
     *
     * @param value 要传递的值
     * @param tag   要通知的fragment的tag
     */
    public void callFragment(Object value, String... tag) {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment;
        for (String item : tag) {
            if (TextUtils.isEmpty(item)) {
                continue;
            }

            fragment = fm.findFragmentByTag(item);
            if (fragment != null && fragment instanceof BaseIndexFragment) {
                ((BaseIndexFragment) fragment).call(value);
            }
        }
    }
}

    效果如下图:

    技术分享

    下面就是最复杂的一种需求:demo3 单Activity页面多模块单版本两个Viewpager

    Demo3Config:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.configs;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.v4.util.SparseArrayCompat;
import android.text.TextUtils;

import com.example.p031_mokuaihua_viewpager_fragment.applications.DemoApplication;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.utils.MyLogUtil;

public class Demo3Config {

    private static final String INDEX_META_DATA = "DEMO3_CONFIG";

    /** viewpager页大小*/
    public static int PAGE_COUNT;
    /** viewpager每页的itemview id*/
    public static String PAGE_LAYOUT_ID;

    /** 默认显示第几页*/
    public static int DEFAULT_PAGE_INDEX;

    /**
     * fragment配置
     */
    private static SparseArrayCompat<Class<? extends BaseFragment>> sIndexFragments = new SparseArrayCompat<>();

    public static void config() {
        Context ctx = DemoApplication.get();
        ApplicationInfo info = null;

        try {
            info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        if (info == null) {
            throw new UnsupportedOperationException();
        }

        String klassName = info.metaData.getString(INDEX_META_DATA);
        if (TextUtils.isEmpty(klassName)) {
            throw new UnsupportedOperationException("please config " + INDEX_META_DATA + " value");
        }

        if (klassName.startsWith(".")) {
            klassName = DemoApplication.get().getPackageName() + klassName;
        }

        MyLogUtil.d("geek", klassName);

        try {
            Class<?> klass = Class.forName(klassName);
            klass.getDeclaredMethod("setup").invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Class<? extends BaseFragment> getFragment(int id) {
        if (sIndexFragments.indexOfKey(id) < 0) {
            throw new UnsupportedOperationException("cannot find fragment by " + id);
        }
        return sIndexFragments.get(id);
    }

    public static SparseArrayCompat<Class<? extends BaseFragment>> getFragments() {
        return sIndexFragments;
    }
}

    Demo3Factory:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.factorys;

import android.support.v4.util.SparseArrayCompat;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.configs.Demo3Config;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment10;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment11;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment20;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment21;


/**
 * 首页模块fragment的工厂, 首页模块有需要更换的,可以在此修改,格式为id->Fragment.class<br />
 * Created by shining on 2016/8/1.
 */

public class Demo3Factory {

    public static void setup() {
        Demo3Config.PAGE_COUNT = 2;
        Demo3Config.PAGE_LAYOUT_ID = "activity_demo3_layout_pager_item_";
        Demo3Config.DEFAULT_PAGE_INDEX = 0;
        registerFragments(Demo3Config.getFragments());
    }

    private static void registerFragments(SparseArrayCompat<Class<? extends BaseFragment>> sIndexFragments) {

        sIndexFragments.put(R.id.fragment_demo3_pager_index_0_0, Demo3Fragment10.class);//第一屏 layout1
        sIndexFragments.put(R.id.fragment_demo3_pager_index_0_1, Demo3Fragment11.class);//第一屏 layout2

        sIndexFragments.put(R.id.fragment_demo3_pager_index_1_0, Demo3Fragment20.class);//第二屏 layout1
        sIndexFragments.put(R.id.fragment_demo3_pager_index_1_1, Demo3Fragment21.class);//第二屏 layout2

    }
}

    Demo3Fragment10:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexNetFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.Demo3Activity;

/**
 * Created by shining on 2017/8/14.
 */

public class Demo3Fragment10 extends BaseIndexNetFragment {


    private Context mContext;

    @Override
    public void onCreate(@Nullable Bundle bundle) {
        super.onCreate(bundle);
        mContext = getActivity();
    }

    @Override
    public void call(Object value) {

    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo3_fragment10;
    }

    @Override
    protected void setup(View rootView, @Nullable Bundle savedInstanceState) {
        super.setup(rootView, savedInstanceState);
        rootView.findViewById(R.id.tv1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SendToFragment("demo3的fragment1页面");
                ((Demo3Activity) mContext).changeView(1);
            }
        });
    }

    /**
     * 页面传值操作部分
     *
     * @param id1
     */
    private void SendToFragment(String id1) {
        //举例
//        IndexFoodFragmentUpdateIds iff = new IndexFoodFragmentUpdateIds();
//        iff.setFood_definition_id(id1);
//        iff.setFood_name(id2);
        if (getActivity() != null && getActivity() instanceof Demo3Activity) {
            ((Demo3Activity) getActivity()).callFragment(id1, Demo3Fragment20.class.getName());
        }
    }
}

    Demo3Fragment20:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseIndexNetFragment;
import com.example.p031_mokuaihua_viewpager_fragment.utils.ToastUtil;

/**
 * Created by shining on 2017/8/14.
 */

public class Demo3Fragment20 extends BaseIndexNetFragment {

    @Override
    public void call(Object value) {
        String ids = (String) value;
        ToastUtil.showToastShort(ids);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_demo3_fragment20;
    }

    @Override
    protected void setup(View rootView, @Nullable Bundle savedInstanceState) {
        super.setup(rootView, savedInstanceState);

    }
}

    这里的导航点也可以自定义:给大家提供一个util 有圆的 方的 长方形 水滴

    IndexPagerIndicator:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

import com.example.p031_mokuaihua_viewpager_fragment.R;


/**
 * 首页viewpager指示符<br/>
 * Created by geek on 2016/7/29.
 */

public class IndexPagerIndicator extends LinearLayout {

    private int mItemWidth;
    private int mItemSelectedHeight;
    private int mItemInterval;

    private int mItemColor;
    private int mStartX;
    private int mCurrentX;

    private Paint mSelectedPaint;
    private IStyleDrawer mStyleDrawer;

    public IndexPagerIndicator(Context context) {
        this(context, null, 0);
    }

    public IndexPagerIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IndexPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setBackgroundColor(Color.TRANSPARENT);
        setOrientation(LinearLayout.HORIZONTAL);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndexPagerIndicator, defStyleAttr, 0);
        mItemWidth = ta.getDimensionPixelSize(R.styleable.IndexPagerIndicator_indicator_width, 10);
        int itemHeight = ta.getDimensionPixelSize(R.styleable.IndexPagerIndicator_indicator_height, 2);
        mItemSelectedHeight = ta.getDimensionPixelSize(R.styleable.IndexPagerIndicator_indicator_select_height, 0);
        if (mItemSelectedHeight == 0) { mItemSelectedHeight = itemHeight;}
        mItemInterval = ta.getDimensionPixelSize(R.styleable.IndexPagerIndicator_indicator_interval, 0);
        mItemColor = ta.getColor(R.styleable.IndexPagerIndicator_indicator_item_color, Color.BLACK);
        int selectedColor = ta.getColor(R.styleable.IndexPagerIndicator_indicator_select_color, Color.WHITE);

        String styleDrawer = ta.getString(R.styleable.IndexPagerIndicator_indicator_style_drawer);
        try {
            if (TextUtils.isEmpty(styleDrawer)) {
                throw new Exception();
            }

            mStyleDrawer = (IStyleDrawer) Class.forName(styleDrawer).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            mStyleDrawer = new DefaultStyleDrawer();
        }

        ta.recycle();

        mStyleDrawer.prepare(mItemWidth, itemHeight, mItemSelectedHeight);

        mSelectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSelectedPaint.setColor(selectedColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mItemSelectedHeight > getMeasuredHeight()) {
            setMeasuredDimension(getMeasuredWidth(), mItemSelectedHeight);
        }

        mStartX = (getMeasuredWidth() - (getChildCount() * mItemWidth
                + (getChildCount() - 1) * mItemInterval)) / 2;
        if (mCurrentX == 0) {
            mCurrentX = mStartX;
        }
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        canvas.save();
        canvas.translate(mCurrentX, (getMeasuredHeight() - mItemSelectedHeight) / 2);
        mStyleDrawer.draw(canvas, mSelectedPaint);
        canvas.restore();
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable p = super.onSaveInstanceState();
        Bundle bundle = new Bundle();
        bundle.putInt("current", mCurrentX);
        bundle.putParcelable("state", p);
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            mCurrentX = bundle.getInt("current");
            state = bundle.getParcelable("state");
        }
        super.onRestoreInstanceState(state);
    }

    public void setupWithViewPager(ViewPager pager) {
        if (pager.getAdapter() == null) {
            throw new UnsupportedOperationException("your viewpager must set adapter first");
        }

        create(pager.getAdapter().getCount());
        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                mCurrentX = (int) (mStartX + (mItemWidth + mItemInterval) * (position + positionOffset));
                invalidate();
            }

            @Override
            public void onPageSelected(int position) {
                mCurrentX = mStartX + (mItemWidth + mItemInterval) * position;
                invalidate();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void create(int count) {
        removeAllViews();
        View itemView;
        for (int i = 0; i < count - 1; i++) {
            itemView = buildView(mItemInterval);
            setOnClick(itemView, i);
            addView(itemView);
        }
        itemView = buildView(0);
        setOnClick(itemView, count - 1);
        addView(itemView);
    }

    private void setOnClick(View itemView, final int pos) {
        itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener != null) { mListener.onItemClick(pos);}
            }
        });
    }

    private View buildView(int margin) {
        return mStyleDrawer.buildView(getContext(), mItemColor, margin);
    }

    private OnItemClickListener mListener;

    public void setOnItemClickListener(OnItemClickListener li) {
        mListener = li;
    }

    public interface OnItemClickListener {
        void onItemClick(int pos);
    }

    public interface IStyleDrawer {
        void prepare(int itemWidth, int itemHeight, int selectedHeight);
        void draw(Canvas canvas, Paint paint);
        View buildView(Context ctx, int bgColor, int margin);
    }

    public static class DefaultStyleDrawer implements IStyleDrawer {

        private Rect mRect;
        private int mItemWidth;
        private int mItemHeight;

        @Override
        public void prepare(int itemWidth, int itemHeight, int selectedHeight) {
            mItemWidth = itemWidth;
            mItemHeight = itemHeight;
            mRect = new Rect(0, 0, itemWidth, selectedHeight);
        }

        @Override
        public void draw(Canvas canvas, Paint paint) {
            canvas.drawRect(mRect, paint);
        }

        @Override
        public View buildView(Context ctx, int bgColor, int margin) {
            View view = new View(ctx);
            view.setBackgroundColor(bgColor);
            LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(mItemWidth, mItemHeight);
            if (margin != 0) { p.rightMargin = margin;}
            view.setLayoutParams(p);
            return view;
        }
    }
}

    NoScrollViewPager:

/**
 * Copyright  2015,  Smart  Haier
 * All  rights  reserved.
 * Description:  没有滑屏效果的ViewPager
 * Author:  geyanyan
 * Date:  2016/11/18
 * FileName:  TabFragmentAdapter.java
 * History:
 * 1.  Date:2016/11/21 21:45
 * Author:geyanyan
 * Modification:
 */
package com.example.p031_mokuaihua_viewpager_fragment.demo3.utils;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;


public class NoScrollViewPager extends ViewPager {
    public NoScrollViewPager(Context context) {
        super(context);
    }

    public NoScrollViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }
}

    ViewPagerChangeAdapter:

package com.example.p031_mokuaihua_viewpager_fragment.demo3.utils;

import android.support.v4.view.ViewPager;

/**
 * <p>function: </p>
 * <p>description:  </p>
 * <p>history:  1. 2016/12/13</p>
 * <p>Author: geek</p>
 * <p>modification:</p>
 */
public class ViewPagerChangeAdapter implements ViewPager.OnPageChangeListener {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

   Demo3Activity:

package com.example.p031_mokuaihua_viewpager_fragment.demo3;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;

import com.example.p031_mokuaihua_viewpager_fragment.R;
import com.example.p031_mokuaihua_viewpager_fragment.base.BaseFragment;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.configs.Demo3Config;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment10;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.fragments.Demo3Fragment20;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.utils.IndexPagerIndicator;
import com.example.p031_mokuaihua_viewpager_fragment.demo3.utils.ViewPagerChangeAdapter;
import com.example.p031_mokuaihua_viewpager_fragment.utils.ComFragmentHelper;
import com.example.p031_mokuaihua_viewpager_fragment.utils.MyLogUtil;

import java.util.List;

import static com.example.p031_mokuaihua_viewpager_fragment.demo3.configs.Demo3Config.PAGE_COUNT;

public class Demo3Activity extends FragmentActivity implements OnClickListener {

    private ViewPager mViewPager;
    private IndexPagerIndicator mIndicator;

    //当前选中的项
    private int currenttab = -1;
//    private static final int PAGE_COUNT = 2;
//    private static final String PAGE_LAYOUT_ID = "demo3_layout_pager_item_";


    private Demo3Fragment10 oneFragment;
    private Demo3Fragment20 twoFragment;

    /**
     * 页面集合
     */
    List<Fragment> fragmentList;

    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Demo3Config.config();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo3);
        mContext = Demo3Activity.this;
        findview();
        addListener();
        doNetWork();
    }

    private void doNetWork() {
        setupViewPager();
        setupFragments();
//        fragmentList = new ArrayList<Fragment>();
//        oneFragment = new ShezhimimaOneFragment();
//        twoFragment = new ShezhimimaTwoFragment();
//
//        fragmentList.add(oneFragment);
//        fragmentList.add(twoFragment);

//        mViewPager.setAdapter(new MyFrageStatePagerAdapter(getSupportFragmentManager()));
    }

    private void setupViewPager() {
        mViewPager.setOffscreenPageLimit(Demo3Config.PAGE_COUNT);
        mViewPager.setAdapter(new IndexPagerAdapter());

        mIndicator.setupWithViewPager(mViewPager);
        mIndicator.setOnItemClickListener(new IndexPagerIndicator.OnItemClickListener() {
            @Override
            public void onItemClick(int pos) {
                mViewPager.setCurrentItem(pos);
            }
        });

        mViewPager.addOnPageChangeListener(new ViewPagerChangeAdapter() {
            @Override
            public void onPageSelected(int position) {
                if (position == 0) {
//                    MobEventHelper.onEvent(Demo3Activity.this, "UI2_index_personal_center");//统计
                }
            }
        });

        mViewPager.setCurrentItem(Demo3Config.DEFAULT_PAGE_INDEX);//设置当前显示标签页为第一页
    }

    /**
     * 初始化首页fragments
     */
    private void setupFragments() {
        // 使用HierarchyChangeListener的目的是防止在viewpager的itemview还没有准备好就去inflateFragment
        // 带来的问题
        mViewPager.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
            @Override
            public void onChildViewAdded(View parent, View child) {
                if (((ViewGroup) parent).getChildCount() < PAGE_COUNT) {
                    return;
                }
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                SparseArrayCompat<Class<? extends BaseFragment>> array = Demo3Config.getFragments();
                int size = array.size();
                BaseFragment item;
                for (int i = 0; i < size; i++) {
                    item = ComFragmentHelper.newFragment(array.valueAt(i), null);
                    ft.replace(array.keyAt(i), item, item.getClass().getName());
                }
                ft.commitAllowingStateLoss();
            }

            @Override
            public void onChildViewRemoved(View parent, View child) {

            }
        });


    }


    private void addListener() {

    }

    private void findview() {
        mViewPager = (ViewPager) findViewById(R.id.viewpager_my);
        mIndicator = (IndexPagerIndicator) findViewById(R.id.indicator);
    }

    @Override
    public void onClick(View v) {

    }

    /**
     * 首页viewpager adapter
     */
    public class IndexPagerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            MyLogUtil.d(Demo3Config.PAGE_LAYOUT_ID + position);
            int layoutId = getResources().getIdentifier(Demo3Config.PAGE_LAYOUT_ID + position, "layout", getPackageName());
            if (layoutId == 0) {
                throw new UnsupportedOperationException("layout not found!");
            }
            View itemLayout = LayoutInflater.from(Demo3Activity.this).inflate(layoutId, container, false);
            container.addView(itemLayout);
            return itemLayout;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }

    /**
     * 定义自己的ViewPager适配器。
     * 也可以使用FragmentPagerAdapter。关于这两者之间的区别,可以自己去搜一下。
     */
    public class MyFrageStatePagerAdapter extends FragmentStatePagerAdapter {

        public MyFrageStatePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

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

        /**
         * 每次更新完成ViewPager的内容后,调用该接口,此处复写主要是为了让导航按钮上层的覆盖层能够动态的移动
         */
        @Override
        public void finishUpdate(ViewGroup container) {
            super.finishUpdate(container);//这句话要放在最前面,否则会报错
            //获取当前的视图是位于ViewGroup的第几个位置,用来更新对应的覆盖层所在的位置
            int currentItem = mViewPager.getCurrentItem();
            if (currentItem == currenttab) {
                return;
            }
            currenttab = mViewPager.getCurrentItem();
        }
    }

    //手动设置ViewPager要显示的视图
    public void changeView(int desTab) {
        mViewPager.setCurrentItem(desTab, true);
    }

//    public IndexViewPager getViewPager() {
//        return mViewPager;
//    }

    /**
     * fragment间通讯bufen
     *
     * @param value 要传递的值
     * @param tag   要通知的fragment的tag
     */
    public void callFragment(Object value, String... tag) {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment;
        for (String item : tag) {
            if (TextUtils.isEmpty(item)) {
                continue;
            }

            fragment = fm.findFragmentByTag(item);
            if (fragment != null && fragment instanceof BaseFragment) {
                ((BaseFragment) fragment).call(value);
            }
        }
    }
}

    效果如下图:

    技术分享

    总结:遇到新的需求,并且很复杂的时候,多想想,多总结一下原生的写法,你会发现有更简单的方法这样下次会节省你近80%的时间,如果你一直都是老的写法,需求却在变,你就会落后,效率就低了,这才是架构师高薪的原因,善于总结,并不是多牛逼~相信上面的方案能给你启发,提前祝大家周末快乐~看杀破狼吧~周末~约嘛~

    地址:https://github.com/geeklx/MyApplication/tree/master/p031_mokuaihua_viewpager_fragment

    另附图:传火嘛~

    技术分享


本文出自 “梁肖技术中心” 博客,请务必保留此出处http://liangxiao.blog.51cto.com/3626612/1957026

以上是关于Android Studio - 第四十八期 模块ViewPager+Fragment的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio 第七十八期 - Android下拉悬停collapsinglayout

Android Studio 第五十八期 - Android屏幕亮度与休眠

Android Studio 第六十八期 - Android8.0 进程保活

Android Studio第三十八期 - HIOS跳转协议解决URI跳转原生页面并传递参数

python学习第四十八天json模块与pickle模块差异

一起Talk Android吧(第四百四十八回:UI控件之Switch)