Android电商项目学习笔记(二)--主界面完成

本项目来源于慕课网Android实战课——Android通用框架设计与完整电商开发

前天跟随视频完成了对主界面的封装及使用,这种模式使用的还不够熟悉,需加强理解并练习。写下这篇来加深理解。
先上效果图:
Android电商项目学习笔记(二)--主界面完成_第1张图片

哈哈,别想多,就是我们平常见的效果。底部一些Tab,上部是与之对应的Fragment。但是与以往不同的是,该界面本身还是一个Fragment,但都是一个原理(底部导航+Fragment)。
在项目中是进行抽取(主界面的基类,详情页的基类)。主界面分为两个部分,上部详情页的容器,下部Tab导航栏,同时对Tab导航栏的点击事件进行处理。详情页的基类比较简单,封装了一些通用的功能:如双击返回键退出应用等。

首先上详情页的代码:

public abstract class ButtomItemdelegate extends MinDelegate implements View.OnKeyListener {

    private long mExitTime = 0;
    private static final int EXIT_TIME = 2000;

    @Override
    public void onResume() {
        super.onResume();
        View rootView = getView();
        if (rootView != null) {
            rootView.setFocusableInTouchMode(true);
            rootView.requestFocus();
            rootView.setOnKeyListener(this);
        }
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if (System.currentTimeMillis() - mExitTime > EXIT_TIME) {
                Toast.makeText(getContext(), "双击退出应用", Toast.LENGTH_SHORT).show();
                mExitTime = System.currentTimeMillis();
            } else {
                _mActivity.finish();
                if (mExitTime != 0) {
                    mExitTime = 0;
                }
            }
            return true;
        }
        return false;
    }
}

这里代码来说相对简单,就提取了一个功能,就是双击返回键退出应用。
监听返回键的点击事件,判断两次点击的间隔时间,如果大于2s,就提示,小于2s直接退出。值得注意的是,在Fragment中,每次重新进入都要对View的焦点重新获取,并重新注册点击事件。代码如下:

    rootView.setFocusableInTouchMode(true);
    rootView.requestFocus();
    rootView.setOnKeyListener(this);

接着是每个Tab的信息,建一个类:

public class ButtomTabBean {

    private final CharSequence ICON;
    private final CharSequence TITLE;

    public ButtomTabBean(CharSequence icon, CharSequence title) {
        ICON = icon;
        TITLE = title;
    }

    public CharSequence getIcon() {
        return ICON;
    }

    public CharSequence getTitle() {
        return TITLE;
    }
}

ICON, TITLE,表示每个Tab有一个图标,和个描述文字。

public class ItemBuilder {
    private final LinkedHashMap ITEMS = new LinkedHashMap<>();

    static ItemBuilder builder() {
        return new ItemBuilder();
    }

    public final ItemBuilder addItem(ButtomTabBean bean, ButtomItemdelegate itemdelegate) {
        ITEMS.put(bean, itemdelegate);
        return this;
    }

    public final ItemBuilder addItems(LinkedHashMap items) {
        ITEMS.putAll(items);
        return this;
    }

    public final LinkedHashMap build() {
        return ITEMS;
    }
}

ItemBuilder是将Tab与界面关联起来。

然后就是主界面的基类,代码:

public abstract class BaseButtomDelegete extends MinDelegate implements View.OnClickListener {
    //保存Tab的内容
    private final ArrayList TAB_BEANS = new ArrayList<>();
    //保存每个Tab所对应的Fragment
    private final ArrayList TAB_DELEGATES = new ArrayList<>();
    private final LinkedHashMap ITEMS = new LinkedHashMap<>();

    private int mCurrentItem = 0; //当前界面
    private int mIndexItem = 0; //进入的第一个界面
    private int mTabColor = Color.RED;

    @BindView(R2.id.mBottomBar)
    LinearLayoutCompat mBottomBar;

    public abstract LinkedHashMap setItems(ItemBuilder builder);
    /**
     * @return 进入应用显示的界面
     */
    public abstract int setIndexItem();

    /**
     * @return tab点击后的颜色
     */
    @ColorInt
    public abstract int setColor();

    @Override
    public Object setLayout() {
        return R.layout.buttom_delegate_layout;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mIndexItem = setIndexItem();
        if (setColor() != 0) {
            mTabColor = setColor();
        }
        final ItemBuilder builder = new ItemBuilder();
        final LinkedHashMap maps = setItems(builder);
        ITEMS.putAll(maps);
        for (Map.Entry item : ITEMS.entrySet()) {
            final ButtomTabBean key = item.getKey();
            final ButtomItemdelegate value = item.getValue();
            TAB_BEANS.add(key);
            TAB_DELEGATES.add(value);
        }
    }

    @Override
    public void onBindView(@Nullable Bundle savedInstanceState, View rootView) {
        final int size = ITEMS.size();
        for (int i = 0; i < size; i++) {
            LayoutInflater.from(getContext()).inflate(R.layout.buttom_item_icon_title_layout, mBottomBar);
            final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i);
            //设置每个tab的点击事件
            item.setTag(i);
            item.setOnClickListener(this);
            final IconTextView icon = (IconTextView) item.getChildAt(0);
            final IconTextView tv = (IconTextView) item.getChildAt(1);
            final ButtomTabBean bean = TAB_BEANS.get(i);
            //初始化数据
            icon.setText(bean.getIcon());
            tv.setText(bean.getTitle());
            if (i == mIndexItem) {
                icon.setTextColor(mTabColor);
                tv.setTextColor(mTabColor);
            }

        }
        //初始化每个TAB对应的界面
        final ISupportFragment[] fragments = TAB_DELEGATES.toArray(new ISupportFragment[size]);
        getSupportDelegate().loadMultipleRootFragment(R.id.buttom_frame, mIndexItem, fragments);
    }

    private void resetColor() {
        final int count = mBottomBar.getChildCount();
        for (int i = 0; i < count; i++) {
            final RelativeLayout item = (RelativeLayout) mBottomBar.getChildAt(i);
            final IconTextView itemIcon = (IconTextView) item.getChildAt(0);
            itemIcon.setTextColor(Color.GRAY);
            final IconTextView itemTitle = (IconTextView) item.getChildAt(1);
            itemTitle.setTextColor(Color.GRAY);
        }

    }


    @Override
    public void onClick(View v) {
        final int tag = (int) v.getTag();
        resetColor();
        final RelativeLayout item = (RelativeLayout) v;
        final IconTextView itemIcon = (IconTextView) item.getChildAt(0);
        itemIcon.setTextColor(mTabColor);
        final IconTextView itemTitle = (IconTextView) item.getChildAt(1);
        itemTitle.setTextColor(mTabColor);
        //展示和隐藏Fragment 参数一为要展示的  参数二为要隐藏的
        getSupportDelegate().showHideFragment(TAB_DELEGATES.get(tag), TAB_DELEGATES.get(mCurrentItem));
        //注意先后顺序
        mCurrentItem = tag;

    }
}

首先声明的几个参数:
ArrayList TAB_BEANS:保存Tab所对应的内容。
ArrayList TAB_DELEGATES:保存Tab所对应的Fragmnet。
private final LinkedHashMap ITEMS:使每个ButtomTabBean对象与对应的Fragment对应起来。
还有几个抽象方法:

 public abstract LinkedHashMap setItems(ItemBuilder builder); //创建Tab类与Fragment类,并传入到界面
 public abstract int setIndexItem(); //设置第一次进入的要显示第几个界面
 public abstract int setColor(); //设置Tab点击后的颜色

然后就是主代码,在oncreat中将 Tab与绑定的界面获取出来,保存到TAB_BEANS,TAB_DELEGATES中,这样就可以控制。

接着在onBindView中对视图进行绑定,循环依次取出每个TabBean,然后使用LayoutInflater加载每个Tab视图,并添加到容器中,这个容器就是界面底部的一个LinearLayout,同时从TAB_BEANS中获取数据,并赋值。这里记得对每个Tab的点击事件进行注册。点击事件主要处理的就是Tab显示及对应界面变化。

//初始化每个TAB对应的界面
        final ISupportFragment[] fragments = TAB_DELEGATES.toArray(new ISupportFragment[size]);
        getSupportDelegate().loadMultipleRootFragment(R.id.buttom_frame, mIndexItem, fragments);

这两句代码实现的对界面(Fragment)的加载,是框架Fragmentation里的内容,不太懂,待我研究下。

到这里,这基类的抽取就算完成了。然后就是使用:

public class Bottomdalegate extends BaseButtomDelegete {

    @Override
    public LinkedHashMap setItems(ItemBuilder builder) {
        final  LinkedHashMap ITEMS=new LinkedHashMap<>();
        ITEMS.put(new ButtomTabBean("{fa-home}","主页"),new IndexDelegate());
        ITEMS.put(new ButtomTabBean("{fa-sort}","分类"),new SortDelegate());
        ITEMS.put(new ButtomTabBean("{fa-compass}","发现"),new CompassDelegate());
        ITEMS.put(new ButtomTabBean("{fa-shopping-cart}","购物车"),new ShopCarDelegate());
        ITEMS.put(new ButtomTabBean("{fa-user}","我的"),new UserDelegate());
        return builder.addItems(ITEMS).build();
    }

    @Override
    public int setIndexItem() {
        return 0;
    }

    @Override
    public int setColor() {
        return Color.parseColor("#0099cc");
    }
}

前面封装好了,这里代码就比较简单了,直接实现三个抽象方法。

到这里,主界面就基本实现了。可以使用这种思想,不用每次对视图直接创建,而是通过动态绑定的方式传入数据,这样就比较灵活。

你可能感兴趣的:(电商项目学习笔记)