为了账号安全,请及时绑定邮箱和手机立即绑定

正在回答

4 回答

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);
    }
}


1 回复 有任何疑惑可以回复我~


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);
    }






}


1 回复 有任何疑惑可以回复我~

。。。

0 回复 有任何疑惑可以回复我~

我也想要源码,自己打的,有点问题,没找到错在哪了

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消

最后一页了,原码呢?

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信