編輯:關於Android編程
這一篇我們介紹兩個相似的控件,分別是Actionbar和Toolbar。
Actionbar是Android3.0之後的一個重要的交互元素,Actionbar位於Activity的頂部,用於顯示圖標、菜單、標題,廣泛用於View的交互、導航等功能。在Android3.0之後,Actionbar是默認添加的,只要你新建的Activity繼承於AppCompatActivity,Actionbar是默認添加的。
我們看一下theme主題配置文件中的樣式,圖片來源於網絡
Android3.0是默認添加Actionbar的,我們講一下Actionbar的移除
在Activity的屬性中設置主題風格為NoTitleBar
例如:
在代碼中修改,通過在代碼中調用下面一句代碼,可以隱藏Actionbar
getSupportActionBar().hide();
注意的是:這一句是當前的Activity繼承與AppcompatActivity的時候,如果是直接繼承於Activity的話,需要在setContent()之前調用:
requestWindowFeature(Window.FEATURE_NO_TITLE)
介紹完Actionbar的添加和移除,下面我們來介紹一下Actionbar的使用
我們可以在代碼中,通過調用getSupportActionBar()獲取到Actionbar實例對象,然後通過相應的方法設置一些屬性,Actionbar的屬性設置方法有:
show()方法:顯示Actionbar
setTitle(CharSequence title)方法:設置Actionbar的標題,重載方法有:setTitle(int resId)
setSubtitle(CharSequence subtitle)方法:設置Actionbar的字幕,重載方法有:setSubtitle(int resId)
setSplitBackgroundDrawable(Drawable d)方法:設置Actionbar的分隔背景
setStackedBackgroundDrawable(Drawable d)方法:設置Actionbar的重疊背景
setLogo(Drawable logo)方法:設置Actionbar的logo,重載方法是:setLogo(int resId)
setIcon(Drawable icon)方法:設置Actionbar的icon,重載方法是:setIcon(int resId)
setHomeButtonEnabled(boolean enabled)方法:設置是否允許返回按鈕
setHomeAsUpIndicator(Drawable indicator)方法:設置顯示一個返回圖片
setHomeActionContentDescription(CharSequence description)方法,當允許的時候,設置返回上一個Activity的描述信息,重載方法是:setHomeActionContentDescription(int resId)
setHideOnContentScrollEnabled(boolean hideOnContentScroll)方法:設置在內容滾動的是時候是否顯示Actionbar
setDisplayShowTitleEnabled(boolean showTitle)方法:設置是否顯示標題
setDisplayUseLogoEnabled(boolean useLogo)方法:設置是否顯示logo
setDisplayShowHomeEnabled(boolean showHome)方法:設置是否顯示返回
setDisplayShowCustomEnabled(boolean showCustom)方法:設置是否顯示一個自定義View
setDisplayOptions(int options)方法:設置顯示的選項
setDisplayOptions(int options, int mask)方法:設置選中的選項
setCustomView(View view)方法:設置自定義的View,重載:setCustomView(View view, ActionBar.LayoutParams layoutParams)
setBackgroundDrawable(Drawable d)方法:設置背景
removeOnMenuVisibilityListener(ActionBar.OnMenuVisibilityListener listener)方法:移除一個可見的菜單時的監聽
hide()方法:隱藏Actionbar
getTitle()方法:獲取標題
簡單的介紹一下Actionbar的常用方法,我們獲取到Actionbar的實例之後可以調用這些方法去設置相應的屬性,這裡就不在做詳細的代碼演示了
將Actionbar中所有的ActionItem定義在menu中,主要講item的幾個屬性:
title屬性:設置標題
icon屬性:設置圖標
showAsAction屬性:設置Item的顯示方式,有幾個值可以選擇:ifRoom,當有4個或者4個以上的時候顯示在overflow裡面;always,總是顯示所有的item;never,不會顯示;withText,盡可能顯示,可能顯示不全;collapseActionView,折疊在一個按鈕裡面,點擊按鈕會顯示,一般與ifRoom一起使用。
下面我們用一個例子講解一下:
首先是menu資源文件:
這裡我們有5個,所以用了ifRoom屬性。需要在Activity中重寫兩個方法:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_app: ToastUtil.showToast(this, "蘋果"); break; case R.id.menu_vitis: ToastUtil.showToast(this, "葡萄"); break; case R.id.menu_banana: ToastUtil.showToast(this, "香蕉"); break; case R.id.menu_pineapple: ToastUtil.showToast(this, "菠蘿"); break; case R.id.menu_orange: ToastUtil.showToast(this, "橘子"); break; } return super.onOptionsItemSelected(item); }
onCreateOptionsMenu(Menu menu)方法是將menu掛載到Actionbar中,onOptionsItemSelected(MenuItem item)方法是對item選中進行處理
實現的效果是:
布局資源文件代碼:
這裡的布局文件比較簡單,就直接顯示兩個文本,可以按需要做更復雜的布局,這裡只是演示,接下來是Activity中的代碼:
private TextView bar_title; private TextView bar_right; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(false); actionBar.setDisplayShowHomeEnabled(true); actionBar.setDisplayUseLogoEnabled(true); //設置顯示自定義的View,如果不設置這個屬性,自定義的View不會起作用 actionBar.setDisplayShowCustomEnabled(true); View view = LayoutInflater.from(this).inflate(R.layout.custom_action_bar, null); bar_title = (TextView) view.findViewById(R.id.bar_title); bar_right = (TextView) view.findViewById(R.id.bar_right); actionBar.setCustomView(view); bar_title.setText("第三個Activity"); bar_title.setTextColor(Color.WHITE); bar_right.setText("搜索"); bar_right.setTextColor(Color.WHITE); setContentView(R.layout.activity_third); }
在這裡,記住必須要調用這個setDisplayShowCustomEnabled(true)方法,設置為true,否則自定義的View不會起作用
實現效果
這裡只是比較簡單地實現一下自定義Actionbar中的View。還有一個常用的就是可以打開Actionbar的返回圖標,只需要在actionbar中調用setDisplayHomeAsUpEnabled(true)設置為true,然後在onOptionsItemSelected(MenuItem item)中監聽點擊返回圖標,然後做出相應的操作就可以了,我們用例子說明一下:
ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); break; } return super.onOptionsItemSelected(item); }
這裡監聽的id必須是android.R.id.home,我們在這裡操作就是點擊圖標就finish掉當前的Activity,實現的效果是:
Actionbar就簡單介紹到這裡,如果你有其他更好的用法,歡迎留言交流!
Toolbar是Android5.0之後推出的一個符合Material Design風格的導航控件,google推薦我們使用這個代替Actionbar,與Actionbar相比,Toolbar更加靈活,不會只局限於固定在頁面頂部,可以固定在頁面的任何地方。除此之外,google在設置Toolbar的時候給我們開發者預留了許多可以定制Toolbar的地方,下面我們來一起學習一下Toolbar這個控件吧!
根據官方文檔的介紹,Toolbar提供給我們開發者很大的修改余地,例如:
設置導航欄圖標
設置App的logo
支持設置標題和子標題
支持添加一個或多個的自定義控件(Toolbar是一個ViewGroup,我們可以添加多個控件)
支持Action Menu
我們先來學習一下Toolbar裡面的屬性設置方法:
collapseActionView()方法:折疊當前展開的View dismissPopupMenus()方法:關閉當前顯示的菜單,包括overflow和子菜單 generateLayoutParams(AttributeSet attrs)方法:根據提供的屬性值獲取到新的布局參數 getContentInsetEnd()方法:獲取結束位置的內容 getContentInsetLeft()方法:獲取左邊的內容 getContentInsetRight()方法:獲取右邊內容 getContentInsetStart()方法:獲取開始位置的內容 getLogo()方法:獲取logo getLogoDescription()方法:獲取Toolbarlogo的描述信息 getMenu()方法:獲取menu getNavigationContentDescription()方法:獲取導航描述信息 getNavigationIcon()方法:獲取導航圖標 getOverflowIcon()方法:獲取到overflow的icon getSubtitle()方法:獲取到Toolbar的子標題 hasExpandedActionView()方法:檢測是否有展開的View inflateMenu(int resId)方法:將menu資源inflate到toolbar裡面 isOverflowMenuShowing()方法:檢查是否有顯示menu onHoverEvent(MotionEvent ev)方法:處理toolbar的懸停事件 onRtlPropertiesChanged(int layoutDirection)方法:文本對齊方式 onTouchEvent(MotionEvent ev)方法:處理觸摸事件 setContentInsetsAbsolute(int contentInsetLeft, int contentInsetRight)方法:設置toolbar絕對位置內容 setContentInsetsRelative(int contentInsetStart, int contentInsetEnd)方法:設置toolbar相對位置內容 setLogo(int resId)方法、setLogo(Drawable drawable)方法:設置toolbar的logo setLogoDescription(int resId)方法、setLogoDescription(CharSequence description)方法:設置logo的描述信息 setNavigationContentDescription(int resId)方法、setNavigationContentDescription(CharSequence description)方法:設置導航按鈕的描述信息 setNavigationIcon(Drawable icon)方法、setNavigationIcon(int resId)方法:設置導航按鈕的圖標 setNavigationOnClickListener(View.OnClickListener listener)方法:設置導航按鈕的監聽事件 setOnMenuItemClickListener(Toolbar.OnMenuItemClickListener listener)方法:設置menu條目的點擊事件 setOverflowIcon(Drawable icon)方法:設置overflow的icon setPopupTheme(int resId)方法:設置彈出式菜單的theme setSubtitle(int resId)方法、setSubtitle(CharSequence subtitle)方法:設置toolbar的子標題 setSubtitleTextAppearance(Context context, int resId)方法:設置子標題文本的樣式 setSubtitleTextColor(int color)方法:設置子標題文本顏色 setTitle(int resId)方法、setTitle(CharSequence title)方法:設置toolbar的標題 setTitleTextAppearance(Context context, int resId)方法:設置toolbar標題文本樣式 setTitleTextColor(int color)方法:設置標題顏色 showOverflowMenu()方法:顯示overflow注意的是:Toolbar是google在Android API21的時候推出的,所以AndroidAPI低於21的需要引入 appcompat-v7支持包,否則在低版本上不能用。
使用Toolbar之前,需要在Activity中去掉原來的Actionbar,移除Actionbar的方法在上面我們介紹Actionbar的時候介紹過,這裡就不在做介紹了,注意的一個是:
如果Activity是繼承AppCompatActivity的話,可以調用下面一句代碼:supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
如果是繼承Activity的話,可以直接調用: requestWindowFeature(Window.FEATURE_NO_TITLE)
去掉Actionbar之後,就可以正常使用Toolbar了,下面,我們介紹一下Toolbar的簡單使用:
布局文件代碼:
Activity代碼:
public class ToolbarTestActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_tool_bar_test); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); } public static void startActivity(Context mContext) { mContext.startActivity(new Intent(mContext, ToolbarTestActivity.class)); } }
實現效果:
這裡實現的效果跟Actionbar一樣,也沒有什麼可以詳細說的,下面我們用Toolbar實現一個比較復雜的效果,在這個實例中,我們整合ToolBar,DrawerLayout,ActionBarDrawerToggle一起實現。
首先看一下效果圖:
下面我們看一下具體的代碼:
首先是布局資源文件代碼:
這裡是左邊策滑出來頁面的布局文件,有點復雜,實現的效果好一點,下面我們看一下Activity的代碼:
package com.example.huawen.asdebug; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Gravity; import android.view.View; import android.view.Window; import android.widget.TextView; import java.util.Iterator; import java.util.LinkedHashMap; /** * Created by Huawen on 2016/9/2. */ public class ToolbarDemoActivity extends AppCompatActivity implements View.OnClickListener { private DrawerLayout drawerlayout; private Toolbar mToolbar; private ActionBarDrawerToggle mActionBarDrawerToggle; private TextView tv_left_music; private TextView tv_left_movie; private TextView tv_left_novel; private TextView tv_left_image; private TextView tv_left_article; private TextView tv_left_about; private TextView tv_left_setting; private FragmentManager mFragmentManager; private LinkedHashMapmFragments = new LinkedHashMap<>(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_toolbar_demo); mToolbar = (Toolbar) findViewById(R.id.toolbar_demo); setSupportActionBar(mToolbar); drawerlayout = (DrawerLayout) findViewById(R.id.drawerlayout); mActionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerlayout, mToolbar, R.string.open, R.string.close); mActionBarDrawerToggle.syncState(); tv_left_music = (TextView) findViewById(R.id.tv_left_music); tv_left_movie = (TextView) findViewById(R.id.tv_left_movie); tv_left_novel = (TextView) findViewById(R.id.tv_left_novel); tv_left_image = (TextView) findViewById(R.id.tv_left_image); tv_left_article = (TextView) findViewById(R.id.tv_left_article); tv_left_about = (TextView) findViewById(R.id.tv_left_about); tv_left_setting = (TextView) findViewById(R.id.tv_left_setting); tv_left_music.setOnClickListener(this); tv_left_movie.setOnClickListener(this); tv_left_novel.setOnClickListener(this); tv_left_image.setOnClickListener(this); tv_left_article.setOnClickListener(this); tv_left_about.setOnClickListener(this); tv_left_setting.setOnClickListener(this); mFragmentManager = getSupportFragmentManager(); //設置首選項 changeFragment(MainFragment.POSITION_MUSIC); } public static void startActivity(Context mContext) { mContext.startActivity(new Intent(mContext, ToolbarDemoActivity.class)); } /** * 切換Fragment * * @param position */ public void changeFragment(int position) { FragmentTransaction transaction = mFragmentManager.beginTransaction(); hideAllFragment(transaction); drawerlayout.closeDrawer(Gravity.LEFT); MainFragment mainFragment = mFragments.get(position); if (mainFragment == null) { mainFragment = new MainFragment(position); transaction.add(R.id.main_content, mainFragment); mFragments.put(position, mainFragment); } else { transaction.show(mainFragment); } transaction.commit(); } /** * 先隱藏所有的fragment * * @param transaction */ private void hideAllFragment(FragmentTransaction transaction) { if (mFragments != null) { Iterator iterator = mFragments.entrySet().iterator(); while (iterator.hasNext()) { LinkedHashMap.Entry entry = (LinkedHashMap.Entry ) iterator.next(); MainFragment mainFragment = entry.getValue(); transaction.hide(mainFragment); } } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_left_music: changeFragment(MainFragment.POSITION_MUSIC); break; case R.id.tv_left_movie: changeFragment(MainFragment.POSITION_MOVIE); break; case R.id.tv_left_novel: changeFragment(MainFragment.POSITION_NOVEL); break; case R.id.tv_left_image: changeFragment(MainFragment.POSITION_IMAGE); break; case R.id.tv_left_article: changeFragment(MainFragment.POSITION_ARTICLE); break; case R.id.tv_left_about: changeFragment(MainFragment.POSITION_ABOUT); break; case R.id.tv_left_setting: changeFragment(MainFragment.POSITION_SETTING); break; } } }
這裡的話通過點擊相應的條目切換不同的Fragment,將Fragment保存在一個HashMap中,每次切換就先隱藏所有的Fragment,然後再顯示點擊出來的Fragment,這樣達到互斥的效果,接下來看一下 MainFragment的代碼:
package com.example.huawen.asdebug; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * Created by Huawen on 2016/9/2. */ public class MainFragment extends Fragment { private TextView mTextView; private int position; public static final int POSITION_MUSIC = 1001; public static final int POSITION_MOVIE = 1002; public static final int POSITION_NOVEL = 1003; public static final int POSITION_IMAGE = 1004; public static final int POSITION_ARTICLE = 1005; public static final int POSITION_ABOUT = 1006; public static final int POSITION_SETTING = 1007; public MainFragment(int position) { this.position = position; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_main, container, false); mTextView = (TextView) view.findViewById(R.id.tv_main_text); switch (position) { case POSITION_MUSIC: mTextView.setText(R.string.menu_music); break; case POSITION_MOVIE: mTextView.setText(R.string.menu_movie); break; case POSITION_NOVEL: mTextView.setText(R.string.menu_novel); break; case POSITION_IMAGE: mTextView.setText(R.string.menu_image); break; case POSITION_ARTICLE: mTextView.setText(R.string.menu_article); break; case POSITION_ABOUT: mTextView.setText(R.string.menu_about); break; case POSITION_SETTING: mTextView.setText(R.string.menu_setting); break; } return view; } }
MainFragment裡面就是根據點擊的位置,顯示不同的文本,這裡就讓他顯示一個文本,做一個演示。如果各位有需要可以根據這個做一個比較復雜的布局。
這裡就不在做很多的描述了,最後總結一下Toolbar使用過程中的一些坑:
有時在Xml中設置屬性不生效,用相應的Java方法設置或者在根布局加入自定義屬性的命名空間,例如xmlns:toolbar=”http://schemas.android.com/apk/res-auto”
改變字體顏色,自定義theme,設置actionMenuTextColor無效,將actionMenuTextColor換成android:textColorPrimary 即可
魅族FlymeOS for 三星i9500在經過數輪內測後終於發布,目前僅支持三星i9500。使用刷機精靈可以一鍵刷入,建議使用。Flyme OS
前言雅虎天氣的界面上滑的時候背景圖片會跟著移動,最重要的是背景圖片會根據手指上下移動的距離來進行不同程度的模糊,感覺甚為驚奇,畢竟大家都知道,在Android平台上進行模
Android自定義控件實戰——滾動選擇器PickerView &n
由於研究生畢業項目需要完成一個基於移動終端的場景文字識別系統,雖然離畢業尚早,但出於興趣的緣故,近一段抽時間完成了這樣一套系統。基本的架構如下: 客戶端: