課程
/移動開發
/Android
/不一樣的自定義實現輪播圖效果
最后一頁了,原碼呢?
2017-10-22
源自:不一樣的自定義實現輪播圖效果 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); ????} ????/** ?????*?初始化我們的底部圓點布局 ?????*/ ????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);//輪播圖圓點的背景顏色 ????????addView(linearLayout); ????????FrameLayout.LayoutParams?layoutParams?=?(LayoutParams)?linearLayout.getLayoutParams(); ????????layoutParams.gravity?=?Gravity.BOTTOM; ????????linearLayout.setLayoutParams(layoutParams); ????????//版本3.0以后的用setAlpha(),3.0之前用的是setAlpha(),但是調用者不同 ????????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; /** ?*?該類是實現輪播圖的核心類 ?*/ public?class?ImageBarnnerViewGroup?extends?ViewGroup{ ????private?int?children;//子視圖的總個數 ????private?int?childheight;//子視圖的高度 ????private?int?childwidth;//子視圖的寬度 ????private?int?x;//此時x的值,代表第一次按下位置的橫坐標,每次輪播圖移動都是橫坐標移動 ????private?int?index?=?0;//代表每個圖片的索引 ????private?Scroller?scroller; ????/** ?????*?要想實現圖片單擊事件的獲取 ?????*?方法:??利用一個單擊變量開關進行判斷,在用戶離開屏幕的一瞬間, ?????*?我們去判斷變量開關來判斷用戶的操縱是點擊還是移動 ?????*/ ????private?boolean?isClick;//true的時候,代表點擊事件;flase代表的不是點擊事件 ????private?ImageBarnnerLister?lister; ????public?ImageBarnnerLister?getLister()?{ ????????return?lister; ????} ????public?void?setLister(ImageBarnnerLister?lister)?{ ????????this.lister?=?lister; ????} ????public?interface?ImageBarnnerLister{ ????????void?clickImageIndex(int?pos);//pos代表當前圖片的索引值 ????} ????private?ImageBarnnerViewGroupLisnner?barnnerViewGroupLisnner; ????public?ImageBarnnerViewGroupLisnner?getBarnnerViewGroupLisnner()?{ ????????return?barnnerViewGroupLisnner; ????} ????public?void?setBarnnerViewGroupLisnner(ImageBarnnerViewGroupLisnner?barnnerViewGroupLisnner)?{ ????????this.barnnerViewGroupLisnner?=?barnnerViewGroupLisnner; ????} ????/** ?????*?要想實現輪播圖底部圓點?以及?圓點切換的功能思路: ?????*?1.我們需要自定義一個繼承自FrameLayout的布局,利用FrameLayout ?????*????布局的特性(在同一位置放置不同view,最終顯示最后一個view),我們就可以實現底部圓點的布局。 ?????*?2.我們需要準備素材,就是底部的素材---圓點。利用Drawable的功能,去實現一個圓點圖片的展示。 ?????*?3.我們還需要繼承FramLayout?來自定義一個類,在該類的實現過程中,我們去加載我們剛才自定義的 ?????*???ImageBarnnerViewGroup核心類?和?步驟2的底部圓點的布局LinearLayout布局來實現。 ?????*/ ????//自動輪播 ????private?boolean?isAuto?=?true;//默認輪播圖是開啟狀態 ????private?Timer?timer?=?new?Timer(); ????private?TimerTask?task; ????private?Handler?autoHandler?=?new?Handler(){ ????????@Override ????????public?void?handleMessage(Message?msg)?{ ???????????switch?(msg.what)?{ ???????????????case?0://此時圖片自動輪播 ?????????????????if(++index?>=?children)//如果輪播圖圖片是最后一張,那么從第一張圖片重新開始滑動 ?????????????????????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){//開啟輪播圖 ????????????????????autoHandler.sendEmptyMessage(0); ????????????????} ????????????} ????????}; ????????timer.schedule(task,100,3000); ????} ????@Override ????public?void?computeScroll()?{ ????????super.computeScroll(); ????????if(scroller.computeScrollOffset()){ ????????????scrollTo(scroller.getCurrX(),0); ????????????invalidate(); ????????} ????} ????/** ?????*?我們在自定義ViewGroup方法中,我們必須實現的有?測量=》布局=》繪制 ?????*?測量?就是onMeasure()方法 ?????*?布局?就是onLayout()方法 ?????*?繪制?就是()方法 ?????*/ ????/** ?????*?對于繪制來說,因為我們是自定義ViewGroup容器,針對于容器的繪制 ?????*?其實就是容器內部子控件的繪制過程,調用系統自帶的繪制即可。 ?????*?即,對于ViewGroup的繪制過程,我們不需要重寫該方法,調用系統自帶即可 ?????*/ ????@Override ????protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{ ????????super.onMeasure(widthMeasureSpec,?heightMeasureSpec); ????????/** ?????????*?由于我們實現的ViewGroup容器,那么 ?????????*?我們應該知道該容器中的所有子視圖。 ?????????*?我們想要測量ViewGroup的寬度和高度,那么我們必須先去測量子視圖的 ?????????*?寬度和高度之和,才能知道ViewGroup的寬度和高度為多少 ?????????*/ ????????//第1步。求出的子視圖的個數 ????????children?=?getChildCount();//獲取子視圖的個數 ????????if(?children?==?0){?//如果子視圖個數為0.就不需要求子視圖的高度和寬度 ????????????setMeasuredDimension(0,0);//測量寬度和高度為0 ????????}else{ ????????????//第2步。求出子視圖的測量寬度和測量高度 ????????????measureChildren(widthMeasureSpec,heightMeasureSpec); ????????????//此時,我們第一個子視圖的寬度,就是我們第一個ViewGroup的寬度?乘以?子視圖的個數 ????????????//子視圖的高度,就是我們vGroup的高度. ????????????View?view?=?getChildAt(0);//因為第一個視圖存在的,所以編號為0 ????????????//第3步。根據子視圖的寬度和高度,來求出ViewGroup的寬度和高度 ????????????childheight?=?view.getMeasuredHeight(); ????????????childwidth?=?view.getMeasuredWidth(); ????????????int?width?=?view.getMeasuredWidth()?*?children;//所有子視圖寬度總和 ????????????//重新賦值,測量完畢 ????????????setMeasuredDimension(width,childheight); ????????} ????} ????/** ?????*?繼承ViewGroup必須實現布局onLayout方法 ?????* ?????*?@param?changed?代表ViewGroup布局位置是否發生變化,是則為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++){ ????????????????//拿出每個視圖 ????????????????View?view?=?getChildAt(i); ????????????????//對每個視圖的子布局進行布局 ????????????????view.layout(leftMargin,?0,?leftMargin?+?childwidth,?childheight); ????????????????leftMargin?=?leftMargin?+?childwidth; ????????????} ????????} ????} ????/** ?????*?事件傳遞過程中的調用方法,我們需要??調用??容器內部的攔截方法 ?????*?針對于該方法,我們可以理解為?該方法的返回值為true,我們自定義的ViewGroup容器就會處理此次攔截事件 ?????*?返回值為flase,我們自定義ViewGroup容器則不會接受此次事件的處理過程,將會向下傳遞該事件 ?????*?針對于我們自定義的ViewGroup,我們當然希望我們的ViewGroup容器處理接受事件,那么我們的返回值就為true ?????*?如果返回值為true,那么真正處理該事件的方法為onTouch方法 ?????*/ ????@Override ????public?boolean?onInterceptTouchEvent(MotionEvent?ev)?{ ????????return?true; ????} ????@Override ????public?boolean?onTouchEvent(MotionEvent?event)?{ ????//另一種方法,手勢探測類?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://表示??用戶按下之后在屏幕上移動的過程 ????????????????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){//說明圖片劃到最左邊 ????????????????????index?=?0; ????????????????}else?if(index?>?children?-?1){//說明圖片劃到最右邊 ????????????????????index?=?children?-?1; ????????????????} ????????????????if(isClick){//代表點擊事件 ????????????????????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容器的父容器,我們已經處理好該事件 ????} ????public?interface?ImageBarnnerViewGroupLisnner{ ????????void?selectImage(int?index); ????} }
。。。
我也想要源碼,自己打的,有點問題,沒找到錯在哪了
舉報
Android開發自定義實現輪播圖效果案例實現,從無到有讓你會懂會用
2 回答滑動圖片從第一張直接跳到最后一張
2 回答為什么這一節的內容加上之后運行時,一點擊程序就崩掉了?
2 回答為什么我加了timer和handler以后圖片就看不到了
1 回答求源碼 代碼有錯誤
1 回答第二張 圖滑動 直接會切換到第一張圖去了
Copyright ? 2025 imooc.com All Rights Reserved | 京ICP備12003892號-11 京公網安備11010802030151號
購課補貼聯系客服咨詢優惠詳情
慕課網APP您的移動學習伙伴
掃描二維碼關注慕課網微信公眾號
2018-10-09
2018-10-09
2017-12-03
。。。
2017-11-21
我也想要源碼,自己打的,有點問題,沒找到錯在哪了