自定義底部導航欄圖示
底部導航欄我門一般的實現方式就是
RadioGroup 和RadioButton這種組合.但是這樣會有很多弊端.比如有個訊息提示.比如要隨時改變圖示
/** * Created by sdx on 2016/12/28. * 底部導航欄圖示 */ public class TabView extends View { private String mText; private Bitmap mBitmap; private Bitmap mClickBitmap; /** * 字型的大小.預設是12 */ private float textSize = 12f; private Rect tvRect; private Paint tvPaint; private RectF ivRect; private int padding; private int ivWidth; private int color; private int msgCount; /** * 條目普通的顏色 */ private static final int normalColor = 0X999999; /** * 條目點選的顏色 */ private static final int clickColor = 0XEF6160; /** * 訊息的背景顏色(訊息的數字是白色) */ private static final int msgColor = 0XEF6160; /** * 設定當前的條目是否是點選狀態 */ private boolean isClick = false; public TabView(Context context) { this(context, null); } public TabView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TabView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TabView); int indexCount = typedArray.getIndexCount(); for (int i = 0; i < indexCount; i++) { int index = typedArray.getIndex(i); switch (index) { case R.styleable.TabView_tab_text: mText = typedArray.getString(index); break; case R.styleable.TabView_tab_image: BitmapDrawable mBitmapDraawable = (BitmapDrawable) typedArray.getDrawable(index); mBitmap = mBitmapDraawable.getBitmap(); break; case R.styleable.TabView_tab_text_size: textSize = typedArray.getDimension(index, 12); break; case R.styleable.TabView_tab_click_image: BitmapDrawable clickDrawable = (BitmapDrawable) typedArray.getDrawable(index); mClickBitmap = clickDrawable.getBitmap(); break; } } typedArray.recycle(); tvRect = new Rect(); tvPaint = new Paint(); reText(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); padding = UIUtils.dp2px(getContext(), 4); int width = getMeasuredWidth() - padding * 2; int height = getMeasuredHeight() - padding * 2 - tvRect.height(); ivWidth = Math.min(width, height); int left = getMeasuredWidth() / 2 - ivWidth / 2; int top = (getMeasuredHeight() - tvRect.height() - ivWidth) / 2; ivRect = new RectF(left, top, left + ivWidth, top + ivWidth); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (isClick) { drawBitmap(canvas, mClickBitmap); color = clickColor; } else { drawBitmap(canvas, mBitmap); color = normalColor; } drawText(canvas); if (msgCount > 0) { drawMessage(canvas); } } /** * 繪製訊息 * * @param canvas */ private void drawMessage(Canvas canvas) { //數字畫筆內容大小等建立 Paint textPaint = new Paint(); Rect textRect = new Rect(); String text = msgCount > 99 ? "99+" : msgCount + ""; int size ; if (text.length() == 1) { size = UIUtils.dp2px(getContext(), 10); } else if (text.length() == 2) { size = UIUtils.dp2px(getContext(), 9); } else { size = UIUtils.dp2px(getContext(), 7); } textPaint.setColor(Color.WHITE); textPaint.setFakeBoldText(true); textPaint.setAntiAlias(true); textPaint.setTextSize(size); textPaint.setTypeface(Typeface.MONOSPACE); textPaint.getTextBounds(text, 0, text.length(), textRect); textPaint.setTextAlign(Paint.Align.CENTER); Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); //畫圓 int width = UIUtils.dp2px(getContext(), 17); Paint paint = new Paint(); paint.setColor(msgColor); paint.setAlpha(255); paint.setStyle(Paint.Style.FILL); paint.setAntiAlias(true); RectF messageRectF = new RectF(ivRect.right - width / 2, ivRect.top, ivRect.right + width / 2, ivRect.top + width); canvas.drawOval(messageRectF, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); //畫數字 float x = messageRectF.right - messageRectF.width() / 2f; float y = messageRectF.bottom - messageRectF.height() / 2f - fontMetrics.descent + (fontMetrics.descent - fontMetrics.ascent) / 2; canvas.drawText(text, x, y, textPaint); } private void drawBitmap(Canvas canvas, Bitmap bitmap) { Bitmap bitmapTem = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvasTem = new Canvas(bitmapTem); Paint paint = new Paint(); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); canvasTem.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); canvasTem.drawOval(ivRect, paint); canvasTem.drawBitmap(bitmap, null, ivRect, paint); canvas.drawBitmap(bitmapTem, 0, 0, null); } private void drawText(Canvas canvas) { tvPaint.setColor(color); tvPaint.setAlpha(255); float x = getMeasuredWidth() / 2 - tvRect.width() / 2; float y = ivRect.bottom + tvRect.height(); canvas.drawText(mText, x, y, tvPaint); } /** * 重繪 */ private void invalidateView() { if (Looper.getMainLooper() == Looper.myLooper()) { invalidate(); } else { postInvalidate(); } } public void setClick(boolean isClick) { this.isClick = isClick; invalidateView(); } /** * 設定一個網路的地址.加載出來bitmap * * @param src */ private String lastSrc; public void setSrc(String src) { if (src == null) return; //如果兩次傳進來的地址一樣.就沒必要重新繪製bitmap if (src.equals(lastSrc)) return; lastSrc = src; Observable.just(src).observeOn(Schedulers.io()).subscribe(new Action1<String>() { @Override public void call(String s) { try { mBitmap = mClickBitmap = Picasso.with(getContext()).load(s).transform(new Transformation() { @Override public Bitmap transform(Bitmap source) { int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); if (squaredBitmap != source) { source.recycle(); } Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); paint.setShader(shader); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); squaredBitmap.recycle(); return bitmap; } @Override public String key() { return "circleImageTransformation"; } }).get(); invalidateView(); } catch (IOException e) { e.printStackTrace(); } } }); } /** * 設定訊息的數量 * * @param count 訊息的數量 */ public void setMessage(int count) { this.msgCount = count; invalidateView(); } /** * 設定文字 * * @param text tab的文字 */ public void setText(String text) { this.mText = text; reText(); invalidateView(); } private void reText() { tvPaint.setTextSize(textSize); tvPaint.getTextBounds(mText, 0, mText.length(), tvRect); tvPaint.setAntiAlias(true); } private final static String KEY_NORMAL = "key_normal"; private final static String KEY_STATE = "key_state"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putBoolean(KEY_STATE, isClick); bundle.putParcelable(KEY_NORMAL, super.onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; isClick = bundle.getBoolean(KEY_STATE); super.onRestoreInstanceState(bundle.getParcelable(KEY_NORMAL)); } else { super.onRestoreInstanceState(state); } } /** * 設定背景圖片 * * @param normal 普通狀態的drawable * @param click 點選狀態的drawable */ public void setImageView(final int normal, final int click) { Observable.just(normal).observeOn(Schedulers.io()).subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { try { mBitmap = Picasso.with(getContext()).load(normal).get(); mClickBitmap = Picasso.with(getContext()).load(click).get(); invalidateView(); } catch (IOException e) { e.printStackTrace(); } } }); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); } }
<declare-styleable name="TabButton"> <!--初始顯示的圖示--> <attr name="image" format="reference"/> <!--選中之後顯示的圖示--> <attr name="clickimage" format="reference"/> <!--選中之後顯示的顏色--> <attr name="clickcolor" format="color"/> <attr name="normalcolor" format="color"/> <!--圖示下顯示的文字,不要太長!--> <attr name="text" format="string"/> <!--文字的大小--> <attr name="text_size" format="dimension"/> </declare-styleable>
<com.ui.widgets.TabView android:id="@+id/tab_my" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" app:tab_click_image="@drawable/ic_tab_mine_s" app:tab_image="@drawable/ic_tab_mine_f" app:tab_text="我的" app:tab_text_size="12sp" />
因為專案裡邊用到了picasso和Rxjava所以這裡就直接用了.其實就是在子執行緒獲取到網路圖片的bitmap,然後繪製到view上;
參考: http://blog.csdn.net/tyzlmjj/article/details/47186249
相關推薦
自定義底部導航欄圖示
底部導航欄我門一般的實現方式就是 RadioGroup 和RadioButton這種組合.但是這樣會有很多弊端.比如有個訊息提示.比如要隨時改變圖示 /** * Created by sdx on 2016/12/28. * 底部導航欄圖示 */ public
NavigationTabBar 自定義底部導航欄
先來頁面效果 匯入依賴 implementation 'devlight.io:navigationtabbar:1.2.5' 先建立三個Fragment ,貼出其中一個Fragment 的程式碼 fragment_home.xml <?xml vers
android 自定義底部導航欄
1.編寫佈局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+
小程式自定義底部導航欄樣式
1.微信app.json檔案中全域性配置小程式API "tabBar": { "color": "#fff", "selectedColor": "red", "backgroundColor": "skyblue", "list": [ { "pagePath": "pa
帶有指示器的自定義底部導航欄的實現
轉載請註明出處:http://blog.csdn.net/zhaokaiqiang1992 今天這篇文章,主要是給大家實現一個自定義的帶有指示器的底部導航欄。 先看一下實現的效果吧。 這個自定義控制元件的使用要注意以下幾個方面:
vue自定義底部導航欄Tabbar
如圖所示,要完成類似的一個底部導航切換。 首先。我們需要分為5個大的VUE檔案。可以根據自己的習慣來放在不同的位置。 我將5個主要的VUE檔案放在了5個不同的資料夾 然後,在元件資料夾裡新建Tabbar.vue /以及Item.vue檔案 Item.vue檔案
微信小程序-自定義底部導航
tool vda www 程序 redirect pub otool lin 初始 代碼地址如下:http://www.demodashi.com/demo/14258.html 一、前期準備工作 軟件環境:微信開發者工具 官方下載地址:https://mp.weixi
React Native:自定義一個導航欄,改變狀態列背景,隱藏狀態列
設計開發過程中,導航欄都會有所不同,這時候使用RN就需要自定義一個想要的導航欄了,RN中文網有講專門ios的導航欄(NavigatorIOS),可以不用自定義。 首先定義自定義導航欄的一些屬性的約束,記得npm install --save prop-types然後引入import Prop
微信小程式——自定義底部導航樣式切換
1、以下截圖是靜態展示部分 解析: 1、catchtap='goHome' 是點選事件,點選的時候傳遞data-num='1',點選事件方法名都是一樣的,只是傳入的data-num值不同,通過這個不同的值,使用三元運算子來判斷需要顯示的樣式和圖示 2、圖示切換,通過
Recat Native:自定義一個導航欄,改變狀態列背景,隱藏狀態列
設計開發過程中,導航欄都會有所不同,這時候使用RN就需要自定義一個想要的導航欄了,RN中文網有講專門ios的導航欄(NavigatorIOS),可以不用自定義。 首先定義自定義導航欄的一些屬性的約束,記得npm install --save prop-types然後引入im
小程式自定義底部選單欄
問題:小程式的底部選單欄基本的樣式根本不能滿足我們的審美要求,所以我們可以通過自己來自定義一套小程式底部欄,可以設定透明背景喲,想要什麼樣式都可以自己定義,好了,廢話不多說,直接上程式碼! 首先在和pages同一級建錄建立tabbar.xml,如右截圖所示 具體的t
微信小程式自定義頂部導航欄,新增背景圖,透明色等.
在微信小程式中,導航欄的顏色可以在app.json. window裡面新增navigationBarBackgroundColor屬性,但是顏色只能為純色.不能使用rgb,或者rgba的色號. 但是這
自定義UINavigationController導航欄背景
方法一:自定義一個BaseNavigationViewController : UINavigationController 在初始化方法中加入以下程式碼,之後就使用BaseNavigationViewController [self.navigatio
微信小程式自定義底部導航帶跳轉
index.wxml <!--底部導航 --> <view class='footer'> <view class='footer_list' data-id='{{
微信小程式-自定義底部導航
之前我的做微信小程式的時候,需要一個底部導航樣式,但是我搜索的時候,大部分都是寫的一些小程式自定義的tabBar的樣式,而當時我在網上有一個地方找到了這個模板,現在介紹給大家參考參考WXML程式碼:<import src="../../template/nav" /&g
自定義的導航欄如何增加右滑動返回的手勢
這幾天產品增加了個新需求,要求增加滑動返回的手勢。安卓上有返回按鈕,但是iOS上沒有返回按鈕,增加一個返回的手勢可以較大的提高使用者體驗。iOS7剛出來的時候系統增加了滑動返回手勢,感覺特別好,但是發現把導航欄隱藏,自定義的滑動返回手勢不好使。於是按照這個帖子(http:/
h5底部導航欄圖示切換
.footer_si{position: fixed;bottom: 0;width: 100%;height: 55px;background: #f5f5f5;overflow: hidden;} .footer_si_box{width: 33%;text-align:
再談小程序自定義底部導航
hone const 版本 css custom 打開 單獨 自定義樣式 ram 小程序自定義tabBar再探索 前言 最近有很多微信開發者朋友在QQ上加我好友,忽然意識到大家對微信自定義底部導航欄需求還是挺大的,故而再次整理下底部導航欄組件開發思路。和之前的文章還是有些區
【Android自定義控制元件】炫酷的底部導航欄
https://github.com/WakeHao/NavBar 基本使用 使用這個控制元件,只需要簡單的幾部 引入該控制元件到你的專案中 compile 'com.chen.wakehao.library:bottom-navigation-bar:1.0.0'
簡單的自定義BottomBar-仿微信底部導航欄
今天寫一個簡單的自定義的BottomBar。 圖片文字都是比較隨意的,具體實現中自己可以修改。下面是實現圖: 首先我們現在佈局中把想要顯示的整個介面的基本佈局搭建成功。(其實主要在於設定你的Tab。 如果專案中用到Bootmbar的地方比較多 或者是你想複用性高一點的話