欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-07-10 12:10:52
本项目来源于慕课网Android实战课——Android通用框架设计与完整电商开发 前天跟随视频完成了对主界面的封装及使用,这种模式使用的还不够熟悉,需加...

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

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

哈哈,别想多,就是我们平常见的效果。底部一些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 ;

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

    public CharSequence getIcon() {
        return ICON;
    }

    public CharSequence get() {
        return ;
    }
}

ICON, ,表示每个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__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.get());
            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 item = (IconTextView) item.getChildAt(1);
            item.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 item = (IconTextView) item.getChildAt(1);
        item.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");
    }
}

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

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