android 自定義圓角button效果的實(shí)例代碼(自定義view Demo)
概述
在平時(shí)開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)碰到需要使用圓角button的情況,一般也會(huì)包括很多其他小功能,比如要在里面添加img,設(shè)置不同的圓角大小等。
針對(duì)這樣的場(chǎng)景,直接使用創(chuàng)建多個(gè)shape,定義多個(gè)xml文件也是可以實(shí)現(xiàn)的。但是如果使用非常頻繁,那么直接自定義一個(gè)就會(huì)來(lái)的非常方便。
甚至在一些情況下,不是可以用shape定義的規(guī)則圖形,比如需要用到貝塞爾曲線等。
如果全局需要這樣風(fēng)格的view,那么自定義一個(gè)View是非常必要的。
本文主要是個(gè)demo記錄,如有需要的讀者可以借鑒學(xué)習(xí)。
Demo
主要實(shí)現(xiàn)功能:
- 自定義圓角大小
- 支持設(shè)置leftDrawable,和自定義文字內(nèi)容(文字和img默認(rèn)居中)
- 支持點(diǎn)擊效果
源碼
RoundRadiusButton.java
/** * author: xujiajia * description: * 1、drawable只有在設(shè)置textString的時(shí)候才會(huì)生效(居中效果兩個(gè)一起測(cè)量) */ public class RoundRadiusButton extends View { //data private int width = 0; private int height = 0; private int roundRadius = 16; private int bgColor = Color.LTGRAY; private boolean isTouching = false; //img and text private Drawable leftDrawable = null; private int drawableWidth = 20; private int drawableHeight = 20; private int leftDrawablePaddingRight = 0; private String textString; private int textSize = 30; private int textColor = Color.BLACK; //onDraw Paint paint; Path path; RectF rectF; Rect rect; public RoundRadiusButton(Context context, int width, int height) { super(context); this.width = width; this.height = height; this.setLayoutParams(new ViewGroup.LayoutParams(width, height)); this.setClickable(true); } public RoundRadiusButton(Context context, AttributeSet attrs) { super(context, attrs); getDataFromAttrs(context, attrs); this.setClickable(true); } public RoundRadiusButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); getDataFromAttrs(context, attrs); this.setClickable(true); } private void getDataFromAttrs(Context context, AttributeSet attrs) { if (attrs == null) { return; } TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundRadiusButton); roundRadius = ta.getDimensionPixelOffset(R.styleable.RoundRadiusButton_roundRadius, 16); bgColor = ta.getColor(R.styleable.RoundRadiusButton_bgColor, Color.LTGRAY); leftDrawable = ta.getDrawable(R.styleable.RoundRadiusButton_leftDrawable); drawableWidth = ta.getDimensionPixelOffset(R.styleable.RoundRadiusButton_drawableWidth, 0); drawableHeight = ta.getDimensionPixelOffset(R.styleable.RoundRadiusButton_drawableHeight, 0); leftDrawablePaddingRight = ta.getDimensionPixelOffset(R.styleable.RoundRadiusButton_leftDrawablePaddingRight, 0); textString = ta.getString(R.styleable.RoundRadiusButton_textString); textSize = ta.getDimensionPixelOffset(R.styleable.RoundRadiusButton_textSize, 0); textColor = ta.getColor(R.styleable.RoundRadiusButton_textColor, Color.BLACK); ta.recycle(); } public void setRoundRadius(int roundRadius) { this.roundRadius = roundRadius; invalidate(); } public void setBgColor(int bgColor) { this.bgColor = bgColor; invalidate(); } public void setLeftDrawable(Drawable leftDrawable, int drawableWidth, int drawableHeight, int paddingRight) { this.leftDrawable = leftDrawable; this.drawableWidth = drawableWidth; this.drawableHeight = drawableHeight; this.leftDrawablePaddingRight = paddingRight; invalidate(); } public void setTextString(String textString) { this.textString = textString; invalidate(); } public void setTextColor(int textColor) { this.textColor = textColor; invalidate(); } public void setTextSize(int textSize) { this.textSize = textSize; invalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { if (isClickable()) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isTouching = true; invalidate(); break; case MotionEvent.ACTION_UP: isTouching = false; invalidate(); break; } } return super.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (width == 0 || height == 0) { width = getWidth(); height = getHeight(); } if (paint == null) { paint = new Paint(); } if (path == null) { path = new Path(); } if (rectF == null) { rectF = new RectF(); } if (rect == null) { rect = new Rect(); } paint.setColor(bgColor); paint.setAntiAlias(true);//抗鋸齒 paint.setStrokeWidth(0);//線的寬度設(shè)為0,避免畫(huà)圓弧的時(shí)候部分圓弧與邊界相切 paint.setStyle(Paint.Style.FILL_AND_STROKE); path.setFillType(Path.FillType.WINDING); //左上圓角 path.moveTo(0, roundRadius); rectF.set(0, 0, 2 * roundRadius, 2 * roundRadius); path.addArc(rectF, 180, 90); //上邊 path.lineTo(width - roundRadius, 0); //右上圓角 rectF.set(width - roundRadius * 2, 0, width, roundRadius * 2); path.addArc(rectF, -90, 90); //右邊 path.lineTo(width, height - roundRadius); //右下圓角 rectF.set(width - roundRadius * 2, height - roundRadius * 2, width, height); path.addArc(rectF, 0, 90); //下邊 path.lineTo(roundRadius, height); //左下圓角 rectF.set(0, height - roundRadius * 2, 2 * roundRadius, height); path.addArc(rectF, 90, 90); //左邊 path.lineTo(0, roundRadius); path.close(); canvas.drawPath(path, paint); if (isTouching) { paint.setColor(getContext().getResources().getColor(R.color.black_tran_30)); canvas.drawPath(path, paint); } //填充背景中間空白的部分 path.moveTo(0, roundRadius); path.lineTo(width - roundRadius, 0); path.lineTo(width, height - roundRadius); path.lineTo(roundRadius, height); path.close(); canvas.drawPath(path, paint); if (isTouching) { paint.setColor(getContext().getResources().getColor(R.color.black_tran_30)); canvas.drawPath(path, paint); } //text, drawable兩個(gè)一起計(jì)算位置 if (!TextUtils.isEmpty(textString)) { paint.setStrokeWidth(1.5f); paint.setColor(textColor); paint.setTextSize(textSize); rect.setEmpty(); paint.getTextBounds(textString, 0, textString.length(), rect); float leftBitmap = 0; float topBitmap = 0; if (leftDrawable != null) { if (leftDrawable != null) { leftBitmap = (1.0f * width - drawableWidth - rect.width() - leftDrawablePaddingRight) / 2; topBitmap = (1.0f * height - drawableHeight) / 2; leftDrawable.setBounds((int) leftBitmap, (int) topBitmap, (int) (leftBitmap + drawableWidth), (int) (topBitmap + drawableHeight)); leftDrawable.draw(canvas); } } float textX = 0; float textY = 1.0f * height / 2 + paint.getTextSize() / 2 - paint.getFontMetrics().descent / 2; if (leftBitmap == 0 && topBitmap == 0) { textX = width / 2 - rect.width() / 2; } else { textX = leftBitmap + drawableWidth + leftDrawablePaddingRight; } canvas.drawText(textString, textX, textY, paint); } } }
MainActivity.java
public class MainActivity extends AppCompatActivity { private LinearLayout llContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { llContainer = findViewById(R.id.ll_container); RoundRadiusButton roundRadiusButton = new RoundRadiusButton(this, 500, 200); roundRadiusButton.setBgColor(Color.LTGRAY); roundRadiusButton.setRoundRadius(40); //text roundRadiusButton.setTextString("testtesttest"); roundRadiusButton.setTextColor(Color.WHITE); roundRadiusButton.setTextSize(40); //drawable roundRadiusButton.setLeftDrawable(getResources().getDrawable(R.mipmap.ic_launcher), 60, 60, 80); roundRadiusButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "testest", Toast.LENGTH_LONG).show(); } }); roundRadiusButton.setClickable(false); llContainer.addView(roundRadiusButton); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/ll_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#868684" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity" > <com.example.newbuttiontest.RoundRadiusButton android:layout_width="300dp" android:layout_height="200dp" app:bgColor="#FFEB3B" app:drawableHeight="18dp" app:drawableWidth="18dp" app:leftDrawable="@mipmap/ic_launcher" app:leftDrawablePaddingRight="5dp" app:roundRadius="30dp" app:textColor="#FF4329" app:textSize="16dip" app:textString="testtesttest" /> </LinearLayout>
attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundRadiusButton"> <attr name="roundRadius" format="dimension" /> <attr name="bgColor" format="color" /> <attr name="leftDrawable" format="reference" /> <attr name="leftDrawablePaddingRight" format="dimension" /> <attr name="drawableWidth" format="dimension" /> <attr name="drawableHeight" format="dimension" /> <attr name="textString" format="string" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color" /> </declare-styleable> </resources>
colors.xml
<resources> <color name="black_tran_30">#30000000</color> </resources>
總結(jié)
以上所述是小編給大家介紹的android 自定義圓角button效果的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
android studio 4.0 新建類沒(méi)有修飾符的方法
這篇文章主要介紹了android studio 4.0 新建類沒(méi)有修飾符的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10Android計(jì)時(shí)器控件Chronometer應(yīng)用實(shí)例
這篇文章主要為大家詳細(xì)介紹了Android計(jì)時(shí)器控件Chronometer應(yīng)用實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09android實(shí)現(xiàn)滑動(dòng)標(biāo)簽頁(yè)效果的代碼解析
這篇文章主要介紹了android實(shí)現(xiàn)滑動(dòng)標(biāo)簽頁(yè)效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04詳解Android Material Design自定義動(dòng)畫(huà)的編寫(xiě)
這篇文章主要介紹了詳解Android Material Design自定義動(dòng)畫(huà)的編寫(xiě),其中對(duì)Activity的過(guò)渡動(dòng)畫(huà)進(jìn)行了重點(diǎn)講解,需要的朋友可以參考下2016-04-04Android使用HttpURLConnection實(shí)現(xiàn)網(wǎng)絡(luò)訪問(wèn)流程
早些時(shí)候其實(shí)我們都習(xí)慣性使用HttpClient,但是后來(lái)Android6.0之后不再支持HttpClient,需要添加Apache的jar才行,所以,就有很多開(kāi)發(fā)者放棄使用HttpClient了,HttpURLConnection畢竟是標(biāo)準(zhǔn)Java接口(java.net) ,適配性還是很強(qiáng)的2022-12-12Android自定義View實(shí)現(xiàn)可以拖拽的GridView
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)可以拖拽的GridView,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06Android筆記之:App模塊化及工程擴(kuò)展的應(yīng)用
這篇文章是android開(kāi)發(fā)人員的必備知識(shí),是我特別為大家整理和總結(jié)的,不求完美,但是有用2013-04-04Android開(kāi)發(fā)事件處理的代碼如何寫(xiě)手摸手教程
這篇文章主要為大家介紹了Android開(kāi)發(fā)事件處理的代碼如何寫(xiě)手摸手教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Android開(kāi)發(fā)必備技巧之高效字符串篩選
在開(kāi)發(fā)過(guò)程中或多或少都要使用一些方法去篩選符合我們要求的字符串,所以下面我們就來(lái)介紹一些在開(kāi)發(fā)工作中常用到的字符串篩選方法,讓大家都能掌握高效的字符串篩選技巧吧2023-06-06