課程
/移動(dòng)開(kāi)發(fā)
/Android
/不一樣的自定義實(shí)現(xiàn)輪播圖效果
最后一頁(yè)了,原碼呢?
2017-10-22
源自:不一樣的自定義實(shí)現(xiàn)輪播圖效果 3-1
正在回答
import?android.content.Context; import?android.graphics.Bitmap; import?android.graphics.Color; import?android.os.Build; import?android.support.annotation.NonNull; import?android.support.annotation.Nullable; import?android.util.AttributeSet; import?android.view.Gravity; import?android.view.ViewGroup; import?android.widget.FrameLayout; import?android.widget.ImageView; import?android.widget.LinearLayout; import?com.example.administrator.asapplication.ImageVariable; import?com.example.administrator.asapplication.R; import?java.util.List; public?class?ImageBarnnerFramLayout?extends?FrameLayout?implements?ImageBarnnerViewGroup.ImageBarnnerViewGroupLisnner,?ImageBarnnerViewGroup.ImageBarnnerLister{ ????private?ImageBarnnerViewGroup?imageBarnnerViewGroup; ????private?LinearLayout?linearLayout; ????private?FramLayoutLisenner?lisenner; ????public?FramLayoutLisenner?getLisenner()?{ ????????return?lisenner; ????} ????public?void?setLisenner(FramLayoutLisenner?lisenner)?{ ????????this.lisenner?=?lisenner; ????} ????public?ImageBarnnerFramLayout(@NonNull?Context?context)?{ ????????super(context); ????????initImageBarnnerViewGroup(); ????????initDotLinearLayout(); ????} ????public?ImageBarnnerFramLayout(@NonNull?Context?context,?@Nullable?AttributeSet?attrs)?{ ????????super(context,?attrs); ????????initImageBarnnerViewGroup(); ????????initDotLinearLayout(); ????} ????public?ImageBarnnerFramLayout(@NonNull?Context?context,?@Nullable?AttributeSet?attrs,?int?defStyleAttr)?{ ????????super(context,?attrs,?defStyleAttr); ????????initImageBarnnerViewGroup(); ????????initDotLinearLayout(); ????} ????public?void?addBitmap(?List<Bitmap>?list){ ????????for(int?i?=?0;?i<list.size();?i++){ ????????????Bitmap?bitmap?=?list.get(i); ????????????addBitmapToImageBarnnerViewGroup(bitmap); ????????????addDotToLinearlayout(); ????????} ????} ????private?void?addBitmapToImageBarnnerViewGroup(Bitmap?bitmap){ ????????ImageView?iv?=?new?ImageView(getContext()); ????????iv.setScaleType(ImageView.ScaleType.CENTER_CROP); ????????iv.setLayoutParams(new?ViewGroup.LayoutParams(ImageVariable.WIDTH,?ImageVariable.HEIGHT/4)); ????????iv.setImageBitmap(bitmap); ????????imageBarnnerViewGroup.addView(iv); ????} ????private?void??addDotToLinearlayout(){ ????????ImageView?iv?=?new?ImageView(getContext()); ????????LinearLayout.LayoutParams?lp?=?new?LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,?LinearLayout.LayoutParams.WRAP_CONTENT); ????????lp.setMargins(5,?5,?5?,5); ????????iv.setLayoutParams(lp); ????????iv.setImageResource(R.drawable.dot_normal); ????????linearLayout.addView(iv); ????} ????/** ?????*?初始化我們自定義圖片輪播圖功能的核心類 ?????*/ ????private?void?initImageBarnnerViewGroup(){ ????????imageBarnnerViewGroup?=?new?ImageBarnnerViewGroup(getContext()); ????????FrameLayout.LayoutParams?lp?=?new?FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,?FrameLayout.LayoutParams.MATCH_PARENT); ????????imageBarnnerViewGroup.setLayoutParams(lp); ????????imageBarnnerViewGroup.setBarnnerViewGroupLisnner(this);//這里就是將Lisnner,傳遞給Framlayout ????????imageBarnnerViewGroup.setLister(this); ????????addView(imageBarnnerViewGroup); ????} ????/** ?????*?初始化我們的底部圓點(diǎn)布局 ?????*/ ????private?void?initDotLinearLayout(){ ????????linearLayout?=?new?LinearLayout(getContext()); ????????FrameLayout.LayoutParams?lp?=?new?FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,?40); ????????linearLayout.setLayoutParams(lp); ????????linearLayout.setOrientation(LinearLayout.HORIZONTAL);//方向:水平居中 ????????linearLayout.setGravity(Gravity.CENTER); ????????linearLayout.setBackgroundColor(Color.RED);//輪播圖圓點(diǎn)的背景顏色 ????????addView(linearLayout); ????????FrameLayout.LayoutParams?layoutParams?=?(LayoutParams)?linearLayout.getLayoutParams(); ????????layoutParams.gravity?=?Gravity.BOTTOM; ????????linearLayout.setLayoutParams(layoutParams); ????????//版本3.0以后的用setAlpha(),3.0之前用的是setAlpha(),但是調(diào)用者不同 ????????if(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.HONEYCOMB){ ????????????linearLayout.setAlpha(0.5f); ????????}else{ ????????????linearLayout.getBackground().setAlpha(100); ????????} ????} ????@Override ????public?void?selectImage(int?index)?{ ????????int?count?=?linearLayout.getChildCount(); ????????for?(int?i?=?0;?i?<?count;?i++)?{ ????????????ImageView?iv?=?(ImageView)?linearLayout.getChildAt(i); ????????????if(?i?==?index){ ????????????????iv.setImageResource(R.drawable.dot_select); ????????????}else?{ ????????????????iv.setImageResource(R.drawable.dot_normal); ????????????} ????????} ????} ????@Override ????public?void?clickImageIndex(int?pos){ ????????lisenner.clickImageIndex(pos); ????} ????public?interface?FramLayoutLisenner{ ????????void?clickImageIndex(int?pos); ????} }
import?android.content.Context; import?android.os.Handler; import?android.os.Message; import?android.util.AttributeSet; import?android.view.GestureDetector; import?android.view.MotionEvent; import?android.view.View; import?android.view.ViewGroup; import?android.widget.Scroller; import?android.widget.Toast; import?java.util.Timer; import?java.util.TimerTask; /** ?*?該類是實(shí)現(xiàn)輪播圖的核心類 ?*/ public?class?ImageBarnnerViewGroup?extends?ViewGroup{ ????private?int?children;//子視圖的總個(gè)數(shù) ????private?int?childheight;//子視圖的高度 ????private?int?childwidth;//子視圖的寬度 ????private?int?x;//此時(shí)x的值,代表第一次按下位置的橫坐標(biāo),每次輪播圖移動(dòng)都是橫坐標(biāo)移動(dòng) ????private?int?index?=?0;//代表每個(gè)圖片的索引 ????private?Scroller?scroller; ????/** ?????*?要想實(shí)現(xiàn)圖片單擊事件的獲取 ?????*?方法:??利用一個(gè)單擊變量開(kāi)關(guān)進(jìn)行判斷,在用戶離開(kāi)屏幕的一瞬間, ?????*?我們?nèi)ヅ袛嘧兞块_(kāi)關(guān)來(lái)判斷用戶的操縱是點(diǎn)擊還是移動(dòng) ?????*/ ????private?boolean?isClick;//true的時(shí)候,代表點(diǎn)擊事件;flase代表的不是點(diǎn)擊事件 ????private?ImageBarnnerLister?lister; ????public?ImageBarnnerLister?getLister()?{ ????????return?lister; ????} ????public?void?setLister(ImageBarnnerLister?lister)?{ ????????this.lister?=?lister; ????} ????public?interface?ImageBarnnerLister{ ????????void?clickImageIndex(int?pos);//pos代表當(dāng)前圖片的索引值 ????} ????private?ImageBarnnerViewGroupLisnner?barnnerViewGroupLisnner; ????public?ImageBarnnerViewGroupLisnner?getBarnnerViewGroupLisnner()?{ ????????return?barnnerViewGroupLisnner; ????} ????public?void?setBarnnerViewGroupLisnner(ImageBarnnerViewGroupLisnner?barnnerViewGroupLisnner)?{ ????????this.barnnerViewGroupLisnner?=?barnnerViewGroupLisnner; ????} ????/** ?????*?要想實(shí)現(xiàn)輪播圖底部圓點(diǎn)?以及?圓點(diǎn)切換的功能思路: ?????*?1.我們需要自定義一個(gè)繼承自FrameLayout的布局,利用FrameLayout ?????*????布局的特性(在同一位置放置不同view,最終顯示最后一個(gè)view),我們就可以實(shí)現(xiàn)底部圓點(diǎn)的布局。 ?????*?2.我們需要準(zhǔn)備素材,就是底部的素材---圓點(diǎn)。利用Drawable的功能,去實(shí)現(xiàn)一個(gè)圓點(diǎn)圖片的展示。 ?????*?3.我們還需要繼承FramLayout?來(lái)自定義一個(gè)類,在該類的實(shí)現(xiàn)過(guò)程中,我們?nèi)ゼ虞d我們剛才自定義的 ?????*???ImageBarnnerViewGroup核心類?和?步驟2的底部圓點(diǎn)的布局LinearLayout布局來(lái)實(shí)現(xiàn)。 ?????*/ ????//自動(dòng)輪播 ????private?boolean?isAuto?=?true;//默認(rèn)輪播圖是開(kāi)啟狀態(tài) ????private?Timer?timer?=?new?Timer(); ????private?TimerTask?task; ????private?Handler?autoHandler?=?new?Handler(){ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ???????????switch?(msg.what)?{ ???????????????case?0://此時(shí)圖片自動(dòng)輪播 ?????????????????if(++index?>=?children)//如果輪播圖圖片是最后一張,那么從第一張圖片重新開(kāi)始滑動(dòng) ?????????????????????index?=?0; ?????????????????scrollTo(childwidth?*?index,?0); ?????????????????barnnerViewGroupLisnner.selectImage(index); ???????????????break; ???????????} ????????} ????}; ????private?void?startAuto(){ ????????isAuto?=?true; ????} ????private?void?stopAuto(){ ????????isAuto?=?false; ????} ????public?ImageBarnnerViewGroup(Context?context)?{ ????????super(context); ????????initObj(); ????} ????public?ImageBarnnerViewGroup(Context?context,?AttributeSet?attrs)?{ ????????super(context,?attrs); ????????initObj(); ????} ????public?ImageBarnnerViewGroup(Context?context,?AttributeSet?attrs,?int?defStyleAttr)?{ ????????super(context,?attrs,?defStyleAttr); ????????initObj(); ????} ????private??void?initObj(){ ????????scroller?=?new?Scroller(getContext()); ????????task?=?new?TimerTask()?{ ????????????@Override ????????????public?void?run()?{ ????????????????if(isAuto){//開(kāi)啟輪播圖 ????????????????????autoHandler.sendEmptyMessage(0); ????????????????} ????????????} ????????}; ????????timer.schedule(task,100,3000); ????} ????@Override ????public?void?computeScroll()?{ ????????super.computeScroll(); ????????if(scroller.computeScrollOffset()){ ????????????scrollTo(scroller.getCurrX(),0); ????????????invalidate(); ????????} ????} ????/** ?????*?我們?cè)谧远xViewGroup方法中,我們必須實(shí)現(xiàn)的有?測(cè)量=》布局=》繪制 ?????*?測(cè)量?就是onMeasure()方法 ?????*?布局?就是onLayout()方法 ?????*?繪制?就是()方法 ?????*/ ????/** ?????*?對(duì)于繪制來(lái)說(shuō),因?yàn)槲覀兪亲远xViewGroup容器,針對(duì)于容器的繪制 ?????*?其實(shí)就是容器內(nèi)部子控件的繪制過(guò)程,調(diào)用系統(tǒng)自帶的繪制即可。 ?????*?即,對(duì)于ViewGroup的繪制過(guò)程,我們不需要重寫(xiě)該方法,調(diào)用系統(tǒng)自帶即可 ?????*/ ????@Override ????protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{ ????????super.onMeasure(widthMeasureSpec,?heightMeasureSpec); ????????/** ?????????*?由于我們實(shí)現(xiàn)的ViewGroup容器,那么 ?????????*?我們應(yīng)該知道該容器中的所有子視圖。 ?????????*?我們想要測(cè)量ViewGroup的寬度和高度,那么我們必須先去測(cè)量子視圖的 ?????????*?寬度和高度之和,才能知道ViewGroup的寬度和高度為多少 ?????????*/ ????????//第1步。求出的子視圖的個(gè)數(shù) ????????children?=?getChildCount();//獲取子視圖的個(gè)數(shù) ????????if(?children?==?0){?//如果子視圖個(gè)數(shù)為0.就不需要求子視圖的高度和寬度 ????????????setMeasuredDimension(0,0);//測(cè)量寬度和高度為0 ????????}else{ ????????????//第2步。求出子視圖的測(cè)量寬度和測(cè)量高度 ????????????measureChildren(widthMeasureSpec,heightMeasureSpec); ????????????//此時(shí),我們第一個(gè)子視圖的寬度,就是我們第一個(gè)ViewGroup的寬度?乘以?子視圖的個(gè)數(shù) ????????????//子視圖的高度,就是我們vGroup的高度. ????????????View?view?=?getChildAt(0);//因?yàn)榈谝粋€(gè)視圖存在的,所以編號(hào)為0 ????????????//第3步。根據(jù)子視圖的寬度和高度,來(lái)求出ViewGroup的寬度和高度 ????????????childheight?=?view.getMeasuredHeight(); ????????????childwidth?=?view.getMeasuredWidth(); ????????????int?width?=?view.getMeasuredWidth()?*?children;//所有子視圖寬度總和 ????????????//重新賦值,測(cè)量完畢 ????????????setMeasuredDimension(width,childheight); ????????} ????} ????/** ?????*?繼承ViewGroup必須實(shí)現(xiàn)布局onLayout方法 ?????* ?????*?@param?changed?代表ViewGroup布局位置是否發(fā)生變化,是則為true,不是則為false ?????*/ ????@Override ????protected?void?onLayout(boolean?changed,?int?l,?int?t,?int?r,?int?b)?{ ????????if(changed){ ????????????int?leftMargin?=?0; ????????????for(int?i=0;?i<children;?i++){ ????????????????//拿出每個(gè)視圖 ????????????????View?view?=?getChildAt(i); ????????????????//對(duì)每個(gè)視圖的子布局進(jìn)行布局 ????????????????view.layout(leftMargin,?0,?leftMargin?+?childwidth,?childheight); ????????????????leftMargin?=?leftMargin?+?childwidth; ????????????} ????????} ????} ????/** ?????*?事件傳遞過(guò)程中的調(diào)用方法,我們需要??調(diào)用??容器內(nèi)部的攔截方法 ?????*?針對(duì)于該方法,我們可以理解為?該方法的返回值為true,我們自定義的ViewGroup容器就會(huì)處理此次攔截事件 ?????*?返回值為flase,我們自定義ViewGroup容器則不會(huì)接受此次事件的處理過(guò)程,將會(huì)向下傳遞該事件 ?????*?針對(duì)于我們自定義的ViewGroup,我們當(dāng)然希望我們的ViewGroup容器處理接受事件,那么我們的返回值就為true ?????*?如果返回值為true,那么真正處理該事件的方法為onTouch方法 ?????*/ ????@Override ????public?boolean?onInterceptTouchEvent(MotionEvent?ev)?{ ????????return?true; ????} ????@Override ????public?boolean?onTouchEvent(MotionEvent?event)?{ ????//另一種方法,手勢(shì)探測(cè)類?GestureDetector ???????? ????????switch?(event.getAction()){ ????????????case?MotionEvent.ACTION_DOWN://表示??用戶按下的一瞬間 ????????????????stopAuto(); ????????????????if(!scroller.isFinished()){ ????????????????????scroller.abortAnimation(); ????????????????} ????????????????isClick?=?true; ????????????????x=?(int)?event.getX(); ????????????????break; ????????????case?MotionEvent.ACTION_MOVE://表示??用戶按下之后在屏幕上移動(dòng)的過(guò)程 ????????????????int?moveX?=?(int)?event.getX(); ????????????????int?distance?=?moveX?-?x; ????????????????scrollBy(-distance,?0); ????????????????x?=?moveX; ????????????????isClick?=?false; ????????????????break; ????????????case?MotionEvent.ACTION_UP://表示??用戶抬起的一瞬間 ????????????????int?scrollx?=?getScrollX(); ????????????????index?=?(scrollx?+?childwidth/2)?/?childwidth; ????????????????if(index<0){//說(shuō)明圖片劃到最左邊 ????????????????????index?=?0; ????????????????}else?if(index?>?children?-?1){//說(shuō)明圖片劃到最右邊 ????????????????????index?=?children?-?1; ????????????????} ????????????????if(isClick){//代表點(diǎn)擊事件 ????????????????????lister.clickImageIndex(index); ????????????????}else{ ????????????????????int?dx?=?index?*?childwidth?-?scrollx; ????????????????????scroller.startScroll(scrollx,0,dx,0); ????????????????????postInvalidate(); ????????????????????barnnerViewGroupLisnner.selectImage(index); ????????????????} ??????????????????startAuto(); //????????????????scrollTo(index?*?childwidth,?0); ????????????????break; ?????????????default: ?????????????????break; ????????} ????????return?true;//返回true,是告訴ViewGroup容器的父容器,我們已經(jīng)處理好該事件 ????} ????public?interface?ImageBarnnerViewGroupLisnner{ ????????void?selectImage(int?index); ????} }
。。。
我也想要源碼,自己打的,有點(diǎn)問(wèn)題,沒(méi)找到錯(cuò)在哪了
舉報(bào)
Android開(kāi)發(fā)自定義實(shí)現(xiàn)輪播圖效果案例實(shí)現(xiàn),從無(wú)到有讓你會(huì)懂會(huì)用
2 回答滑動(dòng)圖片從第一張直接跳到最后一張
2 回答為什么這一節(jié)的內(nèi)容加上之后運(yùn)行時(shí),一點(diǎn)擊程序就崩掉了?
2 回答為什么我加了timer和handler以后圖片就看不到了
1 回答求源碼 代碼有錯(cuò)誤
1 回答第二張 圖滑動(dòng) 直接會(huì)切換到第一張圖去了
Copyright ? 2025 imooc.com All Rights Reserved | 京ICP備12003892號(hào)-11 京公網(wǎng)安備11010802030151號(hào)
購(gòu)課補(bǔ)貼聯(lián)系客服咨詢優(yōu)惠詳情
慕課網(wǎng)APP您的移動(dòng)學(xué)習(xí)伙伴
掃描二維碼關(guān)注慕課網(wǎng)微信公眾號(hào)
2018-10-09
2018-10-09
2017-12-03
。。。
2017-11-21
我也想要源碼,自己打的,有點(diǎn)問(wèn)題,沒(méi)找到錯(cuò)在哪了