Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android Support Library 之 Toolbar

Android Support Library 之 Toolbar

編輯:關於android開發

Android Support Library 之 Toolbar


在 Android 3.0 開始 ,所有的主題默認把 ActionBar 作為默認的 App Bar,但是它很死板,不容易自行設計想要的風格, 在 v7 兼容庫中,出現了 Toolbar, 它改善了這個問題,伴隨著 Toolbar 取代 傳統的 ActionBar ,ActionBar 上的功能要怎麼在 ToolBar 上實現,需要我們去探討下 。

如何添加Toolbar

1、我們使用的是 v7 兼容庫,所以 Activity 要繼承自 AppCompatActivity
MainActivity extends AppCompatActivity

2、修改主題 ,去掉默認的 ActionBar,v7 兼容庫給我們提供了一個默認的沒有 ActionBar 的主題

  在這裡,我把 application 的設置為沒有 ActionBar 的主題 ,這樣所有的 Activity 都會應用這個主題 ,但是實際中並不是所有的 Activity 都需要自己設計 ActionBar,因此我們最好把這個主題應用到單獨 Activity 上。
例如
        

    
 
    



3、在布局中添加 Toolbar


我們可以看到,ToolBar 的高度用的是系統的 ActionBar的高度,在 Material Design 中,需要為一個視圖設計 一個投擲陰影 android:elevation 通常為4dp,為了與 Material Design 設計規則一致 ,我們還需要為 ToolBar 設計著色,取的就是 colorPrimary 的顏色 。

4、在代碼中把 Toolbar 設置為 App Bar ,並設置它的 Navigation Icon, Logo,Title,SubTitle
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.mipmap.ic_action_back);
        toolbar.setLogo(R.mipmap.ic_launcher);
        toolbar.setTitle("Toolbar");
        toolbar.setSubtitle("Toolbar SubTitle");
        setSupportActionBar(toolbar);

捕獲.PNG
看下效果 \
可是標題的顏色和 overflow 的顏色並不統一,全改為白色或許可以
    


再看下效果 \
捕獲.PNG
還可以吧~

如何使用Toolbar

一旦我們設置了 ToolBar 作為了App Bar,那麼就可以使用 v7 兼容包中的 ActionBar 類的方法 例如
    private void setupActionbar() {
        android.support.v7.app.ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.hide();
    }
我們在操作ActionBar的時候,也就相當於在操作Toolbar,因此在 Acionbar 上設置 title,Logo 都會覆蓋 toolbar 上的顯示

在 Toolbar 上增加 action menu 中的 options menu (>=3.0)

在上面的圖中,可以看到 action menu 出現在 toolbar 上,這與之前 action menu 添加到 action bar 上一樣操作
定義menu 菜單


 
    
 
    
 
顯示menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }
響應menu事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.favorite:
                Toast.makeText(this, "Favorite", Toast.LENGTH_SHORT).show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

在 Toolbar 中增加 action menu 中的 contextual menu 之 contextual action mod ( >= 3.0)

先來看下效果
\
GIF.gif
傳統的是用 ListView,但是為了跟上時代的腳步,我想是時候用 RecyclerView 了,但是它沒有提供如 ListView 一樣的方法
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener();


突然發現 ,RecyclerView沒有這個方法,只能自己來做了,那麼我們就需要想想如何設計這個問題。 首先,長按事件,可以在 ViewHolder 中提供接口 然後在 Activity 實現,通過實現長按來開啟contextual action mode 這個時候,我們需要在 adapter 中改變 item 的顏色 ,我們可以用 notifyItemChanged(position) 來讓 RecyclerView 重新調用 onBindViewHolder() 方法來給 item 設置背景色,然後,我們可以選擇其它的 item 並同時讓它們變色,再響應 contextual action mode 的 delete 響應事件來刪除 item。這樣看來一切很完美 ,那我們來一步一步實現。 1、先實現 RecyclerView
item 布局


 
    
 
        
    
 
實現 Recycler.Adapter
public class MyAdapter extends RecyclerView.Adapter {
    private recyclerViewListener mListener;
    private List mDatas;
 
    public MyAdapter(List list, MyAdapter.recyclerViewListener listener) {
        mDatas = list;
        mListener = listener;
    }
 
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }
 
    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
        holder.title.setText(mDatas.get(position));
    }
 
    @Override
    public int getItemCount() {
        return mDatas.size();
    }
 
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
        TextView title;
        CardView cardView;
 
        public ViewHolder(View itemView) {
            super(itemView);
            title = (TextView) itemView.findViewById(R.id.maintitle);
            cardView = (CardView) itemView.findViewById(R.id.item_cardview);
            itemView.setOnClickListener(this);
            itemView.setOnLongClickListener(this);
        }
 
        @Override
        public void onClick(View v) {
            if (mListener != null) {
                mListener.onClick(getLayoutPosition());
            }
        }
 
        @Override
        public boolean onLongClick(View v) {
            if (mListener != null) {
                return mListener.onLongClick(getLayoutPosition());
            }
            return false;
        }
    }
 
    public interface recyclerViewListener {
        void onClick(int position);
        boolean onLongClick(int position);
    }
}

在MainActivity.java中添加Adapter,並添加空的 onClick() 和 onLongClick() 實現
    private void setupRecyclerView() {
        mDatas = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            mDatas.add(String.valueOf(i));
        }
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recyclerView);
        mAdapter = new MyAdapter(mDatas, this);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        mRecyclerView.setAdapter(mAdapter);
    }

這樣,RecyclerView就已經顯示出來了 \
捕獲.PNG

2、實現長按和短按
        mCallback = new ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                getMenuInflater().inflate(R.menu.action_mode_menu, menu);
                return true;
            }
 
            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false;
            }
 
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.delete:
                        mActionMode.finish();
                        return true;
                }
                return false;
            }
 
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                mActionMode = null;
            }
        };

   @Override
    public void onClick(int position) {
        toggleSelection(position);
    }
    
    @Override
    public boolean onLongClick(int position) {
        if (mActionMode == null) {
            mActionMode = startSupportActionMode(mCallback);
        }
        toggleSelection(position);
 
        return true;
    }
 
    private void toggleSelection(int position) {
        mAdapter.toggleSelection(position);
        int count = mAdapter.getSelectedItemCount();
        if (count == 0) {
            mActionMode.finish();
        } else {
            mActionMode.setTitle(String.valueOf(count));
        }
    }

3、在 Adapter 中添加實現變色
    mSelectedItems = new SparseBooleanArray();
    public void toggleSelection(int position) {
        if (mSelectedItems.get(position, false)) {
            mSelectedItems.delete(position);
        } else {
            mSelectedItems.put(position, true);
        }
        notifyItemChanged(position);
    }

通過調用 notifyItemChanged() 來讓 RecyclerView 重新調用 onBindViewHolder(),然後讓背景變色
    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
        holder.title.setText(mDatas.get(position));
        holder.cardView.setBackgroundColor(mSelectedItems.get(position, false) ? Color.parseColor("#883a44b7") : Color.parseColor("#ffffffff"));
    }

這個時候,可以看下效果 GIF.gif
\
現在出現兩個問題,出現2個 "actionbar" ,而且我們要操作的 action bar 背景顏色與我們設計的主題不一致 。另外,當我們點擊了 delete 菜單的時候 ,被選中的 item 顏色並沒有撤消? 如何解決出現2個 "actionbar" 問題
    
windowActionModeOverlay 是表示 action mode 覆蓋 actionbar,actionModeBackground 當然就是 action mode的背景啦,別問我為什麼知道,因為我就是隨便試試就出來了。
如何解決在action mode消失後,選中的 item 背景顏色沒有撤消?我們可以想想,在 ActionModeCallback 消失後,這個時候我們應該通過 notifyItemChanged() 再次讓 recyclerview 來調用 onBindViewHolder() 來刷新 item
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                mAdapter.clearSelectedItems();
                mActionMode = null;
            }
    public void clearSelectedItems() {
        for (int i = 0; i < mSelectedItems.size(); i++) {
            notifyItemChanged(mSelectedItems.keyAt(i));
        }
        mSelectedItems.clear();
    }

onBindViewHolder()就可以再次刷新了
    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
        holder.title.setText(mDatas.get(position));
        holder.cardView.setBackgroundColor(mSelectedItems.get(position, false) ? Color.parseColor("#883a44b7") : Color.parseColor("#ffffffff"));
    }

看下效果 \
GIF.gif
是不是很 perfect ~

4、最後一步,我們要做到刪除選中的 item,這個操作當然是在 ActionMode.Callback中的
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.delete:
                        mAdapter.removeSelectedItems();
                        mActionMode.finish();
                        return true;
                }
                return false;
            }
常規的想,我們可以根據
mSelectedItems = new SparseBooleanArray();
mSelectedItems中的 key 值 ,也就是 item 的 postion ,來一個一個刪除 ,但是並不能很好如我們如願,這就是涉及到 recyclerview 的一個 update 過程 ,當我們刪除了其中一個 item 時候 ,它會重新排列 item ,這個時候第個 item 的 positon 就變了,也就是說,如果 key 值依次為 [1,4,3] ,那麼實際中我們要刪除的 positon 為 [1,3,2],當時我有點懵B了,後來 google 了下,在這個項目中找到答案 ,我們可以對這個 key 值進行從大到小排序 ,這樣 [1,.4,3] 就變為了 [4,3,1] ,這樣我們在刪除第5個的時候 ,前面的順序還是沒變,這樣沒不影響了,實在是屌 ~
    public void removeItem(int position) {
        mDatas.remove(position);
        notifyItemRemoved(position);
    }
 
    public void removeSelectedItems() {
        List positions = new ArrayList<>();
        for (int i = 0; i < mSelectedItems.size(); i++) {
            positions.add(mSelectedItems.keyAt(i));
        }
 
        Collections.sort(positions, new Comparator() {
            @Override
            public int compare(Integer lhs, Integer rhs) {
                return rhs - lhs;
            }
        });
 
        for (int i = 0; i < positions.size(); i++) {
            removeItem(positions.get(i));
        }
    }

從這篇我們可以看到了 RecyclerView 和 Toolbar 的靈活性,但是這裡講述的也只是一角,後續我會繼續完善,並對Android support Library 的新控件進行探討~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved