1. 程式人生 > >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 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<ButtomTabBean, ButtomItemdelegate> 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<ButtomTabBean, ButtomItemdelegate> items) {
        ITEMS.putAll(items);
        return this;
    }

    public final LinkedHashMap<ButtomTabBean, ButtomItemdelegate> build() {
        return ITEMS;
    }
}

ItemBuilder是將Tab與介面關聯起來。

然後就是主介面的基類,程式碼:

public abstract class BaseButtomDelegete extends MinDelegate implements View.OnClickListener {
    //儲存Tab的內容
    private final ArrayList<ButtomTabBean> TAB_BEANS = new ArrayList<>();
    //儲存每個Tab所對應的Fragment
    private final ArrayList<ButtomItemdelegate> TAB_DELEGATES = new ArrayList<>();
    private final LinkedHashMap<ButtomTabBean, ButtomItemdelegate> 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<ButtomTabBean, ButtomItemdelegate> 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<ButtomTabBean, ButtomItemdelegate> maps = setItems(builder);
        ITEMS.putAll(maps);
        for (Map.Entry<ButtomTabBean, ButtomItemdelegate> 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<ButtomTabBean> TAB_BEANS:儲存Tab所對應的內容。
ArrayList<ButtomItemdelegate> TAB_DELEGATES:儲存Tab所對應的Fragmnet。
private final LinkedHashMap<ButtomTabBean, ButtomItemdelegate> ITEMS:使每個ButtomTabBean物件與對應的Fragment對應起來。
還有幾個抽象方法:

 public abstract LinkedHashMap<ButtomTabBean, ButtomItemdelegate> 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<ButtomTabBean, ButtomItemdelegate> setItems(ItemBuilder builder) {
        final  LinkedHashMap<ButtomTabBean, ButtomItemdelegate> 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");
    }
}

前面封裝好了,這裡程式碼就比較簡單了,直接實現三個抽象方法。

到這裡,主介面就基本實現了。可以使用這種思想,不用每次對檢視直接建立,而是通過動態繫結的方式傳入資料,這樣就比較靈活。