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
ArrayList
private final LinkedHashMap
还有几个抽象方法:
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"); } }
前面封装好了,这里代码就比较简单了,直接实现三个抽象方法。
到这里,主界面就基本实现了。可以使用这种思想,不用每次对视图直接创建,而是通过动态绑定的方式传入数据,这样就比较灵活。
上一篇: javaSE练习1——变量和运算符
下一篇: android内存管理