Android自定義圓點(diǎn)指示器
本文實(shí)例為大家分享了Android自定義圓點(diǎn)指示器的具體代碼,供大家參考,具體內(nèi)容如下
先上效果圖
大概思路就是自定義View 從左至右繪制圓點(diǎn) 然后在ViewPager的OnPageChangeListener中設(shè)置當(dāng)前頁面的圓點(diǎn)
下面是代碼
先定義屬性
<resources> <attr name="selectedColor" format="color"/> <attr name="unselectedColor" format="color"/> <declare-styleable name="Indicator"> <attr name="selectedColor"/> <attr name="unselectedColor"/> </declare-styleable> </resources>
接下來是自定義的View
public class Indicator extends View{ private static final int DEFAULT_TOTAL_INDEX = 5; private static final int DEFAULT_CURRENT_INDEX = 0; private static final int DEFAULT_CIRCLE_DISTANCE = 40; private static final int DEFAULT_CIRCLE_RADIUS = 8; private static final int DEFAULT_CIRCLE_SELECTED_RADIUS = 11; private int selectedColor; private int unselectedColor; private int currentIndex; private int totalIndex; private Paint paint; private int startX; private int startSelectedY; private int startY; private int centreX; public Indicator(Context context) { this(context,null); } public Indicator(Context context, AttributeSet attrs) { this(context, attrs,0); } public Indicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.Indicator,defStyleAttr,0); selectedColor = typedArray.getColor(R.styleable.Indicator_selectedColor, Color.LTGRAY); unselectedColor = typedArray.getColor(R.styleable.Indicator_unselectedColor,Color.WHITE); typedArray.recycle(); totalIndex = DEFAULT_TOTAL_INDEX; currentIndex = DEFAULT_CURRENT_INDEX; paint = new Paint(); }
從TypedArray中獲取自定義的屬性,totalIndex是總的圓點(diǎn)個(gè)數(shù),currentIndex是當(dāng)前頁面的圓點(diǎn)
接下來是重寫的OnDraw()方法
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); centreX = getWidth() / 2; startSelectedY = getHeight() / 2 - DEFAULT_CIRCLE_SELECTED_RADIUS; startY = getHeight() / 2 - DEFAULT_CIRCLE_RADIUS; if (totalIndex % 2 == 0){ startX = centreX - (int)(1.0 * (totalIndex - 1)/2 * DEFAULT_CIRCLE_DISTANCE); }else{ startX = centreX - totalIndex / 2 * DEFAULT_CIRCLE_DISTANCE; } paint.setAntiAlias(true); paint.setColor(unselectedColor); int tempX = startX; for(int i = 0 ; i < totalIndex ; i++ ){ RectF rectF = new RectF(tempX - DEFAULT_CIRCLE_RADIUS,startY, tempX + DEFAULT_CIRCLE_RADIUS,startY + 2 * DEFAULT_CIRCLE_RADIUS); if (i == currentIndex) { paint.setColor(selectedColor); rectF = new RectF(tempX - DEFAULT_CIRCLE_SELECTED_RADIUS,startSelectedY, tempX + DEFAULT_CIRCLE_SELECTED_RADIUS,startSelectedY + 2 * DEFAULT_CIRCLE_SELECTED_RADIUS); } canvas.drawOval(rectF,paint); if (paint.getColor() == selectedColor) paint.setColor(unselectedColor); tempX += DEFAULT_CIRCLE_DISTANCE; } }
因?yàn)楫?dāng)前頁面的圓點(diǎn)和未選中頁面的圓點(diǎn)要設(shè)置不同的大小 所以分別設(shè)置每個(gè)圓點(diǎn)的坐標(biāo) 然后用for循環(huán)繪制圓點(diǎn)
這里有一點(diǎn)要注意 new RectF() 的四個(gè)參數(shù)分別是圓點(diǎn)外面的矩形的左上角的X,Y和右下角的X,Y
接下來是設(shè)置當(dāng)前頁面的圓點(diǎn)的方法
public void setCurrentIndex(int currentIndex){ //if (currentIndex < 0) // currentIndex += totalIndex ; //if (currentIndex > totalIndex - 1) // currentIndex %= totalIndex; this.currentIndex = currentIndex; invalidate(); }
注釋里的代碼是當(dāng)頁面可以循環(huán)的時(shí)候設(shè)置的
接下來是設(shè)置總的圓點(diǎn)個(gè)數(shù)的方法
public void setTotalIndex(int totalIndex){ int oldTotalIndex = this.totalIndex; if (totalIndex < 1) return; if (totalIndex < oldTotalIndex){ if (currentIndex == totalIndex ) currentIndex = totalIndex - 1; } this.totalIndex = totalIndex; invalidate(); }
當(dāng)刪除圓點(diǎn)的時(shí)候 如果currentIndex是最后一個(gè) 讓currentIndex向前移動(dòng)
接下來是重寫的OnMeasure()方法
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec)); } private int measureHeight(int measureSpec){ int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); int desired = DEFAULT_CIRCLE_SELECTED_RADIUS * 2 + getPaddingBottom() + getPaddingTop(); if(specMode == MeasureSpec.EXACTLY) { result = Math.max(desired,specSize); }else{ if(specMode == MeasureSpec.AT_MOST){ result = Math.min(desired,specSize); } else result = desired; } return result; } private int measureWidth(int measureSpec){ int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); int desired = (totalIndex - 1) * DEFAULT_CIRCLE_DISTANCE + DEFAULT_CIRCLE_SELECTED_RADIUS * 2 + getPaddingLeft() + getPaddingRight(); if(specMode == MeasureSpec.EXACTLY) { result = Math.max(desired,specSize); }else{ if(specMode == MeasureSpec.AT_MOST){ result = Math.min(desired,specSize); }else result = desired; } return result; }
下面是MainActivity的布局代碼,很簡單
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.lzh123.learnviewpager.MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.example.lzh123.learnviewpager.Indicator app:selectedColor="#FFFFFF" app:unselectedColor="#C7C7C7" android:id="@+id/indicator" android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
下面是MainActivity的代碼
public class MainActivity extends AppCompatActivity { View layout1,layout2,layout3; ViewPager viewPager; Indicator indicator; List<View> viewList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewPager); LayoutInflater inflater = getLayoutInflater(); layout1 = inflater.inflate(R.layout.layout1,null); layout2 = inflater.inflate(R.layout.layout2,null); layout3 = inflater.inflate(R.layout.layout3,null); viewList = new ArrayList<>(); viewList.add(layout1); viewList.add(layout2); viewList.add(layout3); indicator = (Indicator) findViewById(R.id.indicator); indicator.setTotalIndex(viewList.size()); PagerAdapter pagerAdapter = new PagerAdapter() { @Override public int getCount() { return viewList.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(viewList.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(viewList.get(position)); return position; } @Override public boolean isViewFromObject(View view, Object object) { return view == viewList.get(Integer.parseInt(object.toString())); } }; viewPager.setAdapter(pagerAdapter); viewPager.setOnPageChangeListener(new PageChangeListener()); } public class PageChangeListener implements ViewPager.OnPageChangeListener{ @Override public void onPageSelected(int position) { indicator.setCurrentIndex(position); } @Override public void onPageScrollStateChanged(int state) { } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } }
ViewPager里添加了三個(gè)空頁面 然后設(shè)置指示器的圓點(diǎn)個(gè)數(shù),最后在ViewPager的OnPageChangeListener中設(shè)置當(dāng)前的 頁面的圓點(diǎn)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android ViewPager小圓點(diǎn)指示器
- Android實(shí)現(xiàn)引導(dǎo)頁的圓點(diǎn)指示器
- Android之帶group指示器的ExpandableListView(自寫)
- Android之IphoneTreeView帶組指示器的ExpandableListView效果
- Android TabLayout設(shè)置指示器寬度的方法
- Android實(shí)現(xiàn)仿網(wǎng)易新聞的頂部導(dǎo)航指示器
- Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
- Android實(shí)現(xiàn)基于ViewPager的無限循環(huán)自動(dòng)播放帶指示器的輪播圖CarouselFigureView控件
- Android開發(fā)實(shí)現(xiàn)的ViewPager引導(dǎo)頁功能(動(dòng)態(tài)加載指示器)詳解
- Android progressbar實(shí)現(xiàn)帶底部指示器和文字的進(jìn)度條
相關(guān)文章
Android5.0+ CollapsingToolbarLayout使用詳解
這篇文章主要為大家詳細(xì)介紹了Android5.0+ CollapsingToolbarLayout使用,感興趣的小伙伴們可以參考一下2016-09-09關(guān)于Android中WebView遠(yuǎn)程代碼執(zhí)行漏洞淺析
這篇文章主要給大家介紹了關(guān)于Android中WebView遠(yuǎn)程代碼執(zhí)行漏洞的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05Android實(shí)現(xiàn)手機(jī)拍照功能
這篇文章主要介紹了Android實(shí)現(xiàn)手機(jī)拍照功能,感興趣的小伙伴們可以參考一下2015-12-12Android使用Jni實(shí)現(xiàn)壓力鍋數(shù)據(jù)檢測效果示例
這篇文章主要介紹了Android使用Jni實(shí)現(xiàn)壓力鍋數(shù)據(jù)檢測效果,涉及Android結(jié)合Jni實(shí)現(xiàn)進(jìn)度條模擬壓力鍋數(shù)據(jù)監(jiān)測效果的相關(guān)操作技巧,需要的朋友可以參考下2017-12-12Android系統(tǒng)添加Linux驅(qū)動(dòng)
今天小編就為大家分享一篇關(guān)于Android系統(tǒng)添加Linux驅(qū)動(dòng)的文章,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10Android TraceView和Lint使用詳解及性能優(yōu)化
這篇文章主要介紹了Android TraceView和Lint使用詳解及性能優(yōu)化的相關(guān)資料,需要的朋友可以參考下2017-03-03