精华内容
下载资源
问答
  • 滚动

    2013-07-01 09:40:23
    滚动
  • 主要为大家详细介绍了Android自定义半圆形圆盘滚动选择器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 3D圆形球体滚动flash动画是一款滚动的圆球倒影动画下载。
  • unity 卡片椭圆方向循环滚动
  • 主要为大家详细介绍了UGUI实现卡片椭圆方向滚动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 自定义圆形滚动菜单

    2015-11-16 17:02:06
    自定义圆形滚动菜单,其中最重要的还是摆放控件的一些测量和那些几何算法
  • 旋转方向,旋转幅度 旋转时间 动画时间 都可以设定相应的时间。
  • 功能要求:两边的半圆形转盘可以转动,转盘上的图标也一起滚动,蓝红色图标指着的小图标变成高亮选中状态。 第一眼看到这个需求就想到这个必须要用自定义控件来做才行,于是产生了这样的思路: 半圆形的滚动...

    本文为原创作品,转载请注明出处:https://blog.csdn.net/wjj1996825/article/details/80646526

    前段时间公司项目要求做一个特效的滑动选择器,效果如下图的样子:

    功能要求:两边的半圆形转盘可以转动,转盘上的图标也一起滚动,蓝红色图标指着的小图标变成高亮选中状态。
    第一眼看到这个需求就想到这个必须要用自定义控件来做才行,于是产生了这样的思路:
    半圆形的滚动的转盘自定义view继承viewgroup,重写滑动事件,自定义圆盘上图片的摆放角度,至于蓝色和红色箭头图标指向的选中状态可以用坐标数组绘制一个区域来判断是否有符合条件的图标滚动到了这个位置,如果有的话就将这个图标所在的控件透明度设置为1,如果没到这个位置就设置为非选中状态0.5透明度 ,思路这样定下来了,预计可以行得通,于是开始进行实际的尝试写代码实现这个自定义的控件和功能。
    下面我直接把核心代码附上,注释比较清晰:
    attrs.xml文件代码:

    <!--自定义半圆形展示效果转盘选择器控件-->
        <declare-styleable name="ringview_half">
            <attr name="image_angle_rh" format="integer" />
            <attr name="image_padding_rh" format="integer" />
            <attr name="max_speed_rh" format="integer" />
            <attr name="min_speed_rh" format="integer" />
            <attr name="list_rh" format="integer" />
            <attr name="can_scroll_rh" format="boolean" />
            <attr name="is_right_select_icon_rh" format="boolean" />
        </declare-styleable>
    

    自定义控件的类代码:

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Rect;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import com.wj.R;
    import com.wj.utils.DensityUtil;
    import com.wj.utils.ScreenUtils;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @time 2018/6/8
     * @author JunJieW
     * @since 1376881525@qq.com
     * @description  自定义半圆形展示效果转盘选择器控件
     */
    public class RingViewHalf extends ViewGroup {
        /**
         * 上一次滑动的坐标
         */
        private float mLastX;
        private float mLastY;
        /**
         * 检测按下到抬起时使用的时间
         */
        private long mDownTime;
        /**
         * 自动滚动线程
         */
        private ScrollResetRunnable mScrollResetRunnable;
        /**
         * 检测按下到抬起时旋转的角度
         */
        private float mTmpAngle;
        /**
         * 每秒最大移动角度
         */
        private int mMax_Speed;
        /**
         * 如果移动角度达到该值,则屏蔽点击
         */
        private int mMin_Speed;
        /**
         * 圆的直径
         */
        private int mRadius;
        /**
         * 判断是否正在自动滚动
         */
        private boolean isMove;
        /**
         * 布局滚动角度
         */
        private int mStartAngle = 0;
        /**
         * 中间条的宽度
         */
        private int mCircleLineStrokeWidth;
        /**
         * 图片内容偏移角度
         */
        private int mImageAngle;
        /**
         * 是否初始化布局
         */
        private boolean isChekc = false;
        /**
         * 布局view
         */
        private List<Integer> mImageList = new ArrayList<>();
        /**
         * 是否可点击
         */
        private boolean isCanClick = true;
    
        /**
         * 图片与环之间的padding
         */
        private int mPadding;
        /**
         * 是否是右边居中的图标为选中图标
         */
        private boolean is_right_select_icon = true;
        /**
         * 是否是右边居中的图标为选中图标
         */
        private Rect select_icon_rect = new Rect();
    
    
        //是否能转动
        private boolean mCanScrool;
    
        public RingViewHalf(Context context) {
            this(context, null, 0);
        }
    
        public RingViewHalf(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public RingViewHalf(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //获取自定义控件设置的值
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ringview_half, 0, 0);
            mMax_Speed = array.getInteger(R.styleable.ringview_half_max_speed_rh, 300);
            mMin_Speed = array.getInteger(R.styleable.ringview_half_min_speed_rh, 3);
            mImageAngle = array.getInteger(R.styleable.ringview_half_image_angle_rh, 0);
            mPadding = array.getInteger(R.styleable.ringview_half_image_padding_rh, 0);
            mCanScrool = array.getBoolean(R.styleable.ringview_half_can_scroll_rh, true);
            is_right_select_icon = array.getBoolean(R.styleable.ringview_half_is_right_select_icon_rh, true);
    
            //获取xml定义的资源文件
            TypedArray mList = context.getResources().obtainTypedArray(array.getResourceId(R.styleable.ringview_half_list_rh, 0));
            int len = mList.length();
            if (len > 0) {
                for (int i = 0; i < len; i++)
                    mImageList.add(mList.getResourceId(i, 0));
            } else {
                mImageList.add(R.mipmap.icon);
                mImageList.add(R.mipmap.icon);
                mImageList.add(R.mipmap.icon);
            }
            mList.recycle();
            array.recycle();
    
            int [] location =new int [2];
            getLocationInWindow(location);
            Log.d("locationInWindow",">>>>X=="+location[0]+"y=="+location[1]);
            addImgIcon();
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if (!isChekc) {
                initView();
                mRadius = getWidth();
                isChekc = true;
            }
    
        }
    
        /**
         * 测量
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int childCount = this.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = this.getChildAt(i);
                this.measureChild(child, widthMeasureSpec, heightMeasureSpec);
                child.getMeasuredWidth();
            }
    
        }
    
        /**
         * 排版布局
         */
        private void initView() {
            int width = this.getWidth();
            int height = this.getHeight();
            if (width != height) {
                int min = Math.min(width, height);
                width = min;
                height = min;
            }
            //不同屏幕分辨率下做不同的处理
            float instPadding = 70f;
            if (ScreenUtils.getScreenWidth(getContext())<=720){
                instPadding = 55f;
            }
    
            //图片摆放的圆弧半径
            mCircleLineStrokeWidth = getChildAt(0).getMeasuredHeight() + DensityUtil.dip2px(getContext(),instPadding) + mPadding;
            //计算图片圆的半径
            final int mContent = width / 2 - mCircleLineStrokeWidth / 2;
            for (int i = 0; i < getChildCount(); i++) {
                View child = this.getChildAt(i);
                //计算每个图片摆放的角度
                int mAnGle = 360 / mImageList.size() * (i + 1) + mImageAngle;
                //获取每个图片摆放的左上角的x和y坐标
                float left = (float) (width / 2 + mContent * Math.cos(mAnGle * Math.PI / 180)) - child.getMeasuredWidth() / 2;
                float top = (float) (height / 2 + mContent * Math.sin(mAnGle * Math.PI / 180)) - child.getMeasuredHeight() / 2;
                /**
                 * 一四象限
                 */
                if (getQuadrantByAngle(mAnGle) == 1 || getQuadrantByAngle(mAnGle) == 4) {
    //                child.setRotation(mAnGle - 270);
                    /**
                     * 二三象限
                     */
                } else {
    //                child.setRotation(mAnGle + 90);
                }
    
                child.layout((int) left, (int) top, (int) left + child.getMeasuredWidth(), (int) top + child.getMeasuredHeight());
    
    
            }
    
        }
    
        
        
    
        /**
         * 添加子控件
         */
        private void addImgIcon() {
            for (int i = 1; i < mImageList.size() + 1; i++) {
                //新建imageview
                final ImageView mImageView = new ImageView(getContext());
                mImageView.setImageResource(mImageList.get(i - 1));
                LayoutParams layoutParams = null;
    
                mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
                if (is_right_select_icon){
                    //右侧icon为选中状态
                    if (i==mImageList.size()){
                        mImageView.setAlpha(1f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }else {
                        mImageView.setAlpha(0.5f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }
                }else {
                    // 左侧icon为选中状态
                    if (i==5){
                        mImageView.setAlpha(1f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }else {
                        mImageView.setAlpha(0.5f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }
                }
    
                mImageView.setLayoutParams(layoutParams);
                final int finalI = i;
                //添加点击事件
                mImageView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (isCanClick) {
    //                        Toast.makeText(getContext(),finalI + "   ---", Toast.LENGTH_SHORT).show();
                            if (mOnLogoItemClick != null)
                                mOnLogoItemClick.onItemClick(view, finalI - 1);
                        }
    
                    }
                });
                //添加view
                addView(mImageView);
            }
            //添加view点击事件
            setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (isCanClick) {
                    }
                }
            });
    
        }
    
        /**
         * 触摸监听
         */
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            if (mCanScrool) {
                float x = event.getX();
                float y = event.getY();
    
    
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
    
                        mLastX = x;
                        mLastY = y;
                        mDownTime = System.currentTimeMillis();
                        mTmpAngle = 0;
    
                        // 如果当前已经在快速滚动
                        if (isMove) {
                            // 移除快速滚动的回调
                            removeCallbacks(mScrollResetRunnable);
                            isMove = false;
                            return true;
                        }
    
                        break;
                    case MotionEvent.ACTION_MOVE:
                        /**
                         * 获得开始的角度
                         */
                        float start = getAngle(mLastX, mLastY);
                        /**
                         * 获得当前的角度
                         */
                        float end = getAngle(x, y);
                        Log.e("TAG", "start = " + start + " , end =" + end);
                        // 一四象限
                        if (getQuadrant(x, y) == 1 || getQuadrant(x, y) == 4) {
                            mStartAngle += end - start;
                            mTmpAngle += end - start;
                            //二三象限
                        } else {
                            mStartAngle += start - end;
                            mTmpAngle += start - end;
                        }
                        // 重新布局
                        getCheck();
    
                        break;
                    case MotionEvent.ACTION_UP:
                        // 获取每秒移动的角度
                        float anglePerSecond = mTmpAngle * 1000
                                / (System.currentTimeMillis() - mDownTime);
                        // 如果达到最大速度
                        if (Math.abs(anglePerSecond) > mMax_Speed && !isMove) {
                            // 惯性滚动
                            post(mScrollResetRunnable = new ScrollResetRunnable(anglePerSecond));
                            return true;
                        }
    
                        // 如果当前旋转角度超过minSpeed屏蔽点击
                        if (Math.abs(mTmpAngle) > mMin_Speed) {
                            return true;
                        }
    
                        break;
                }
            }
            return super.dispatchTouchEvent(event);
        }
    
        /**
         * 获取移动的角度
         */
        private float getAngle(float xTouch, float yTouch) {
            double x = xTouch - (mRadius / 2d);
            double y = yTouch - (mRadius / 2d);
            return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
        }
    
        /**
         * 根据当前位置计算象限
         */
        private int getQuadrant(float x, float y) {
            int tmpX = (int) (x - mRadius / 2);
            int tmpY = (int) (y - mRadius / 2);
            if (tmpX >= 0) {
                return tmpY >= 0 ? 4 : 1;
            } else {
                return tmpY >= 0 ? 3 : 2;
            }
    
        }
    
        /**
         * 在activity的onCreate方法中获取当前自定义view中在屏幕中的绝对坐标始终为0,
         * 改成在onWindowFocusChanged函数中获取即可,这时view都已经加载完成
         * 但这里特别注意一点要:如果是fragment种使用该自定义view的话,这里的方法就应该注释掉
         * 因为不但获取到的矩形的值是空的,而且当你的fragment执行了跳转的逻辑后,再返回后会发
         * 一种特别恶心的异常,你获取到判断选中位置的矩形的left,top,right,bottom的值会和
         * 初始化的时候不一样,导致你选中时候的状态出现异常情况,本人已经被坑过,希望后面的同学
         * 一定注意吸取教训
         */
        @Override
        public void onWindowFocusChanged(boolean hasWindowFocus) {
            super.onWindowFocusChanged(hasWindowFocus);
    
            getSelectIconReft();
    
        }
        //获取选中icon位置的矩形范围
        private void getSelectIconReft() {
    
            int [] location = new int [2];
            getLocationOnScreen(location);
            //计算出右侧选中时图标的位置
            if (is_right_select_icon){
                //选中的icon动态设置宽高为60,没选中宽高55,这里60/2为选中按钮的宽度或者高度的一半,即中心点
                select_icon_rect.left = location[0]+getWidth()-mCircleLineStrokeWidth/2-DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.top =(location[1]+getHeight()/2)-DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.right = location[0]+getWidth()-mCircleLineStrokeWidth/2+DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.bottom = (location[1]+getHeight()/2)+DensityUtil.dip2px(getContext(),40f)/2;
            }else {
                //计算出左侧选中时图标的位置
                //选中的icon动态设置宽高为60,没选中宽高55,这里60/2为选中按钮的宽度或者高度的一半,即中心点
                select_icon_rect.left = location[0]+mCircleLineStrokeWidth/2-DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.top = (location[1]+getHeight()/2)-DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.right = location[0]+mCircleLineStrokeWidth/2+DensityUtil.dip2px(getContext(),40f)/2;
                select_icon_rect.bottom =  (location[1]+getHeight()/2)+DensityUtil.dip2px(getContext(),40f)/2;
            }
            Log.d("onFocusChanged","-----getHeight=="+getChildAt(0).getHeight()+";getWidth=="+getChildAt(0).getWidth());
        }
    
    
        /**
         * 通过角度判断象限
         */
        private int getQuadrantByAngle(int angle) {
            if (angle <= 90) {
                return 4;
            } else if (angle <= 180) {
                return 3;
            } else if (angle <= 270) {
                return 2;
            } else {
                return 1;
            }
        }
    
        /**
         * 惯性滚动
         */
        private class ScrollResetRunnable implements Runnable {
    
            private float angelPerSecond;
    
            public ScrollResetRunnable(float velocity) {
                this.angelPerSecond = velocity;
            }
    
            public void run() {
                //小于20停止
                if ((int) Math.abs(angelPerSecond) < 20) {
                    isMove = false;
                    return;
                }
                isMove = true;
                // 滚动时候不断修改滚动角度大小
    //            mStartAngle += (angelPerSecond / 30);
                mStartAngle += (angelPerSecond / 40);
                //逐渐减小这个值
                angelPerSecond /= 1.0666F;
                postDelayed(this, 30);
                // 重新布局
                getCheck();
            }
        }
    
    
        /**
         * 点击事件接口
         */
        public interface OnLogoItemClick {
            void onItemClick(View view, int pos);
        }
    
        private OnLogoItemClick mOnLogoItemClick;
        private OnIconSelectedListener mOnIconSelectedListener;
    
        /**
         * 设置点击事件
         * @param mOnLogoItemClick
         */
        public void addOnItemClick(OnLogoItemClick mOnLogoItemClick) {
            this.mOnLogoItemClick = mOnLogoItemClick;
        }
    
        /**
         * 到选中位置后选中事件接口
         */
        public interface OnIconSelectedListener{
            void onIconSelected( int pos);
        }
    
        /**
         * 设置点击事件
         * @param mOnIconSelectedListener
         */
        public void addOnIconSelectedListener(OnIconSelectedListener mOnIconSelectedListener) {
            this.mOnIconSelectedListener = mOnIconSelectedListener;
        }
        /**
         * 旋转圆盘
         */
        private void getCheck() {
            mStartAngle %= 360;
            setRotation(mStartAngle);
            //改变选中的icon的状态
            setSelectedIcon();
    
        }
    
        //改变选中的icon的状态
        private void setSelectedIcon() {
            if (select_icon_rect.left==0&&select_icon_rect.top==0){
                //fragment中onWindowFocusChanged会出现计算select_icon_rect.left和select_icon_rect.top等于0的情况,
                // 所以做下判断,如果为0则重新调用下计算方法
                getSelectIconReft();
            }
            for (int j =0;j<getChildCount();j++){
                LayoutParams layoutParams = null;
                int [] location = new int [2];
                getChildAt(j).getLocationOnScreen(location);
                Log.d("getCheck","location[0]=="+location[0]+";select_icon_rect.left=="+select_icon_rect.left+"location[1]=="+location[1]+";select_icon_rect.top=="+select_icon_rect.top);
                if (is_right_select_icon){
                    //右边icon是选中状态的时候
                    if (select_icon_rect.left-22<=location[0]&&location[0]<=select_icon_rect.right+22){
                        if (select_icon_rect.top-22<=location[1]&&location[1]<=select_icon_rect.bottom+22){
                            getChildAt(j).setAlpha(1);
                            layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                            //把选中的icon所在list中的position通过接口回传过去
                            if (mOnIconSelectedListener!=null){
                                mOnIconSelectedListener.onIconSelected(j);
                            }
                        }else {
                            getChildAt(j).setAlpha(0.5f);
                            layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                        }
                    }else {
                        getChildAt(j).setAlpha(0.5f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }
    
                }else {
                    //左边icon是选中状态的时候
                    if (select_icon_rect.left-22<=location[0]&&location[0]<=select_icon_rect.right+22){
                        if (select_icon_rect.top-22<=location[1]&&location[1]<=select_icon_rect.bottom+22){
                            getChildAt(j).setAlpha(1);
                            layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                            //把选中的icon所在list中的position通过接口回传过去
                            if (mOnIconSelectedListener!=null){
                                mOnIconSelectedListener.onIconSelected(j);
    
                            }
                        }else {
                            getChildAt(j).setAlpha(0.5f);
                            layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                        }
                    }else {
                        getChildAt(j).setAlpha(0.5f);
                        layoutParams = new LayoutParams(DensityUtil.dip2px(getContext(),40f), DensityUtil.dip2px(getContext(),40f));
                    }
                }
                getChildAt(j).setLayoutParams(layoutParams);
                getChildAt(j).invalidate();
                Log.d("getChildCount","=="+j+";class=="+getChildAt(j).getClass()+";left=="+getChildAt(j).getLeft()+";top=="+getChildAt(j).getTop()+";right=="+getChildAt(j).getRight()+";bottom=="+getChildAt(j).getBottom()+";getLocationOnScreen:x="+location[0]+"y="+location[1]+";getRotationX=="+getRotationX()+";getRotationY=="+getRotationY());
            }
        }
    
    }
    

    然后就是你在activity中根据回调方法获取选中的对象:
    //左右侧方法相同,这里列出左侧圆盘获取方法:

    view.ringView_half_left.addOnIconSelectedListener { position ->
               //  ToDo      根据postion从你的list中获取对应的选中的对象的bean类属性即可
               
            }
    

    最后贴下布局文件:

    <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
    
    
                <RelativeLayout
                    android:id="@+id/ring_left_outside_rl"
                    android:layout_width="@dimen/dp_350"
                    android:layout_height="@dimen/dp_350"
                    android:layout_alignParentLeft="true"
                    android:layout_marginLeft="-240dp">
    
                    <com.wj.views.RingViewHalf
                        android:id="@+id/ringView_half_left"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:background="@drawable/bg_compatibility"
                        app:image_angle_rh="15"
                        app:image_padding_rh="20"
                        app:is_right_select_icon_rh="true"
                        app:list_rh="@array/zodiac_list" />
    
                    <ImageView
                        android:layout_width="70dp"
                        android:layout_height="70dp"
                        android:layout_alignParentLeft="true"
                        android:layout_centerVertical="true"
                        android:layout_marginLeft="@dimen/dp_220"
                        android:src="@drawable/icon_match_boy" />
    
    
                </RelativeLayout>
    
    
                <RelativeLayout
                    android:id="@+id/ring_right_outside_rl"
                    android:layout_width="@dimen/dp_350"
                    android:layout_height="@dimen/dp_350"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="-240dp">
    
                    <com.wj.views.RingViewHalf
                        android:id="@+id/ringView_half_right"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_alignParentRight="true"
                        android:layout_centerVertical="true"
                        android:background="@drawable/bg_compatibility"
                        app:image_angle_rh="15"
                        app:image_padding_rh="20"
                        app:is_right_select_icon_rh="false"
                        app:list_rh="@array/zodiac_list" />
    
    
                    <ImageView
                        android:layout_width="70dp"
                        android:layout_height="70dp"
                        android:layout_alignParentRight="true"
                        android:layout_centerVertical="true"
                        android:layout_marginRight="@dimen/dp_220"
                        android:src="@drawable/icon_match_girl" />
    
    
                </RelativeLayout>
    
    
    
                <Button
                    android:id="@+id/check_btn"
                    android:layout_width="@dimen/dp_265"
                    android:layout_height="@dimen/dp_46"
                    android:layout_alignParentBottom="true"
                    android:layout_marginBottom="@dimen/dp_25"
                    android:layout_marginTop="@dimen/dp_25"
                    android:layout_centerHorizontal="true"
                    android:alpha="0.5"
                    android:enabled="true"
                    android:clickable="true"
                    android:background="@drawable/check" />
    
    
            </RelativeLayout>    
    

    //这里是放半圆形转盘选择器上显示的图片list,我这里是用的xml静态传进去的,也可以改为动态方式传递

    app:list_rh="@array/zodiac_list" 
    

    然后在values下面创建一个arrays.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <string-array name="zodiac_list">
            <item>@drawable/zodiac_1</item>
            <item>@drawable/zodiac_2</item>
            <item>@drawable/zodiac_3</item>
            <item>@drawable/zodiac_4</item>
            <item>@drawable/zodiac_5</item>
            <item>@drawable/zodiac_6</item>
            <item>@drawable/zodiac_7</item>
            <item>@drawable/zodiac_8</item>
            <item>@drawable/zodiac_9</item>
            <item>@drawable/zodiac_10</item>
            <item>@drawable/zodiac_11</item>
            <item>@drawable/zodiac_12</item>
        </string-array>
    </resources>
    
    

    到此就可以了~,喜欢的可以在文章底部留言交流或者探讨,最后附上GitHub源码地址,喜欢的记得点亮星星。
    https://github.com/15115134369/RingviewHalfDemo

    展开全文
  • css3圆球顺时针滚动效果纯css3动画效果,占用内存极低,且使用方便,直接复制相关html以及css到你的页面中即可,动画呈顺时针方向加速再减速运行
  • 图片动态椭圆滚动

    2013-08-09 16:45:10
    滚动
  • jquery圆形平滑滚动导航菜单,供大家一起共同分享学习。
  • 文章目录概述元素圆角与滚动条方案一方案二方案实现自定义滚动条扩展遗留问题 概述 我们在写 web 页面的时候,除了页面原生的滚动条,比如 HTML 的滚动条,BODY 的滚动条之外,还有一种比较常见的滚动条,那就是元素...

    概述

    我们在写 web 页面的时候,除了页面原生的滚动条,比如 HTML 的滚动条,BODY 的滚动条之外,还有一种比较常见的滚动条,那就是元素内部滚动条,我们在利用元素内部滚动条的时候会遇到什么问题呢,我们如何自定义滚动条。

    元素圆角与滚动条

    比如迅雷客户端,除了最右边的滚动条是页面滚动条,其他两个都是元素内部滚动条。
    在这里插入图片描述

    在面板区域,我们的内部滚动条,因为外部元素的圆角给裁剪掉了,这在视觉上是不行的,那我们想办法解决。
    在这里插入图片描述

    方案一

    给这个元素添加一个 margin 让元素与底部有一定距离,这个距离我们认为是圆角的大小,即能解决问题,但是这也会造成元素底部一直有空隙,而不是一个完整的可滚动区域,视觉体验上还是欠佳。

    方案二

    想到原生滚动条上下有两个箭头,那我们是不是可以把这个箭头改造一下,让它的高度等于圆角的大小,同时透明不可见呢,这样我们就实现了滚动条距离底部有一定距离,不会被外部圆角所裁剪,也能保证完整的滚动区域,保证用户体验。

    这是 Chrome 默认的滚动条样式,当然我们还应该知道,滚动条应该四个箭头,上面两个,下面两个,都是用来自增或自减的。
    在这里插入图片描述

    方案实现

    自定义滚动条,我们平时用的多的可能是自定义滚动条的轨道,颜色,大小等,但上下箭头一般是隐藏的,所以我们需要去查一下浏览器对于滚动条有哪些CSS选择器

    ::-webkit-scrollbar — 整个滚动条.
    ::-webkit-scrollbar-button — 滚动条上的按钮 (上下箭头).
    ::-webkit-scrollbar-thumb — 滚动条上的滚动滑块.
    ::-webkit-scrollbar-track — 滚动条轨道.
    ::-webkit-scrollbar-track-piece — 滚动条没有滑块的轨道部分.
    ::-webkit-scrollbar-corner — 当同时有垂直滚动条和水平滚动条时交汇的部分.
    ::-webkit-resizer — 某些元素的corner部分的部分样式(例:textarea的可拖动按钮).
    

    除了常用的 ::-webkit-scrollbar::-webkit-scrollbar-thumb::-webkit-scrollbar-track 之外,我们还找到了我们想要的选择器 ::-webkit-scrollbar-button

    我们只需要将滚动条四个箭头隐藏三个就行,先认识一下这些选择器

    // 滚动条所有箭头按钮
    ::-webkit-scrollbar-button
    
    // 垂直方向的滚动条箭头
    ::-webkit-scrollbar-button:vertical 
    
    // 垂直滚动条上方箭头
    ::-webkit-scrollbar-button:vertical:start
    
    // 垂直滚动条上方渐箭头
    ::-webkit-scrollbar-button:vertical:start:increment
    
    // 垂直滚动条上方渐减箭头
    ::-webkit-scrollbar-button:vertical:start:decrement
    
    // 垂直滚动条下方箭头
    ::-webkit-scrollbar-button:vertical:end
    
    // 垂直滚动条下方渐增箭头
    ::-webkit-scrollbar-button:vertical:end:increment
    
    // 垂直滚动条下方渐减箭头
    ::-webkit-scrollbar-button:vertical:end:decrement
    

    代码实现:

    // 隐藏所有箭头按钮
    ::-webkit-scrollbar-button{
    	display: none;
    }
    // 垂直滚动条下方渐增或渐减箭头显示其一
    ::-webkit-scrollbar-button:vertical:end:increment{
    	display: block;
    	height: 5px;
        background-color: transparent;
    }
    

    最终效果:
    在这里插入图片描述

    自定义滚动条扩展

    参考:https://www.cnblogs.com/rubylouvre/archive/2011/03/01/1968057.html

    <!doctype html>
    <html>
      <head>
        <title>自定义滚动条</title>
     
      </head>
      <body>
      <style>
        /* Turn on a 13x13 scrollbar */
        ::-webkit-scrollbar {
          width: 13px;/*对垂直流动条有效*/
          height: 13px;/*对水平流动条有效*/
        }
        /*垂直滚动条的按钮*/
        ::-webkit-scrollbar-button:vertical {
          background-color: red;
          border: 1px dashed blue;
        }
        /*CSS的坐标系,左上角为(0,0),往右往下为增加,往上往左为减少*/
        /*显示滚动条上方的渐增按钮*/
        ::-webkit-scrollbar-button:start:decrement,
        /*显示滚动条上方的渐减按钮*/
        ::-webkit-scrollbar-button:end:increment {
          display: block
        }
     
        /*隐藏滚动条上方的渐增按钮*/
        ::-webkit-scrollbar-button:vertical:start:increment,
        ::-webkit-scrollbar-button:vertical:end:decrement {
          display: none;
        }
        
        /* 定义垂直滚动条渐增按扭的样式 */
        ::-webkit-scrollbar-button:vertical:increment {
          background-color: white;
          border: 1px dashed blue;
        }
     
        /* 定义垂直滚动条渐减按扭的样式 */
        ::-webkit-scrollbar-button:vertical:decrement {
          background-color: purple;
          border: 1px dashed blue;
        }
        /*  scrollbar-track    上面是 scrollbar-track-piece  */
        /*  scrollbar-track-piece 上面是 四个按扭与scrollbar-track-piece:start与scrollbar-track-piece:end与scrollbar-thumb */
        /* 垂直滚动条的第一层轨道*/
        ::-webkit-scrollbar-track:vertical {
          background-color: blue;
          border: 1px dashed pink;
        }
     
     
        /* 垂直滚动条的第二层轨道 */
        ::-webkit-scrollbar-track-piece {
          background-color: green;
        }
        /* 垂直滚动条的第三层轨道的上段 */
        ::-webkit-scrollbar-track-piece:vertical:start {
          border: 1px solid #000;
        }
     
        /* 垂直滚动条的第三层轨道的下段 */
        ::-webkit-scrollbar-track-piece:vertical:end {
          border: 1px dashed pink;
        }
     
        /* 垂直滚动条的滑动块 */
        ::-webkit-scrollbar-thumb:vertical {
          height: 50px;
          background-color: yellow;
        }
     
        /* Corner */
        ::-webkit-scrollbar-corner:vertical {
          background-color: black;
        }
        /*  http://www.cssportal.com/css-properties/resize.htm  */
        /* Resizer */
        ::-webkit-scrollbar-resizer:vertical {
          background-color:orange;
        }
      </style>
     
     
      <div style="width:200px;height: 200px;overflow: scroll;resize:both;">
        <div style="background: red;width:400px;height: 400px;"></div>
      </div>
    </body>
    </html>
    

    遗留问题

    目前我还有一个疑问就是,内部滚动条,默认都是贴边的,这在一定程度上是不满足视觉要求的,操作起来也不是很好,因为我们自定义滚动条一般定义的不会很宽。

    当然通过多一层容器包裹,外层容器首先就有一个margin,里面的滚动条自然会与边界有边距,这是目前我所采用的方案,期待有更好的解决办法。

    展开全文
  • 圆形滚动效果 CircleView ,CircleView 实现了在一个圆形上滚动 UITableViewCells 的方案
  • css3圆球顺时针滚动效果 纯css3动画效果,占用内存极低,且使用方便,直接复制相关html以及css到你的页面中即可,动画呈顺时针方向加速再减速运行
  • 点的轨迹:1 有一大一小两个,小贴在大内侧,且大不动,小贴在大内侧滚动,求小内指定一点的运动轨迹。要求:用户通过圆心坐标和半径输入两个,并输入坐标指定小内的指定点,程序必须判断用户输入...

    先把题目mark下。

    点的轨迹:

    1 有一大一小两个圆,小圆贴在大圆内侧,且大圆不动,小圆贴在大圆内侧滚动,求小圆内指定一点的运动轨迹。要求:用户通过圆心坐标和半径输入两个圆,并输入坐标指定小圆内的指定点,程序必须判断用户输入和合法性(小圆贴在大院内侧,指定点在小圆内),然后计算并绘制出两个圆的初始位置和指定点的运动轨迹。
    2 与第一问类似,但小圆贴在大圆外侧,并沿大圆外侧滚动。
    3 与第一问类似,但小圆不动,大圆贴在校园外侧滚动,且指定点在大圆内。
    注意:用设计模式等优化程序可获得加分。

    第一问轨迹为内摆线,参考内摆线

    展开全文
  • 圆形几何视差滚动404模板是一款创意风格的404页面UI动画模板下载。提示:本模板调用到谷歌字体库,可能会出现页面打开比较缓慢。
  • 滚动的圆形菜单

    2021-04-05 09:28:36
    作者BCsl,源码CursorWheelLayout,可以滚动的圆形菜单,喜欢的朋友可以参考一下这个案例,安卓源码频道。
  • 波浪滚动圆球View

    2016-01-28 23:50:29
    博客地址:http://blog.csdn.net/zxt0601/article/details/49808157 仿魅族,华为等波浪滚动圆球自定义VIew。
  • 今回给大家介绍个圆形旋转的效果,基于圆形的物理特性,又上任意一点可以作为一个控制按钮,然后拖动它来使图片轮换。
  • 带圆点导航满屏滚动

    2014-06-30 10:26:42
    带圆点导航满屏滚动代码,实现满屏下翻一页
  • 模拟单位圆在直线上滚动,获取圆周上固定点的轨迹,获得圆滚动动态图。MATLAB语言。
  • 实现CSS3圆圈滚动

    千次阅读 2019-02-21 23:29:20
    下面来学习一下CSS3的滚动,我们知道有一些按钮是可以跳动,其实这些跳动的按钮不一定要用JS才能实现,用CSS3也可以实现按钮的跳动。下面是我用CSS3来实现圆圈的滚动。 首先我设置了两个类,分别给两个类设置样式(如...

    下面来学习一下CSS3的滚动,我们知道有一些按钮是可以跳动,其实这些跳动的按钮不一定要用JS才能实现,用CSS3也可以实现按钮的跳动。下面是我用CSS3来实现圆圈的滚动。
    首先我设置了两个类,分别给两个类设置样式(如图)
    在这里插入图片描述
    在box类设置边框,然后在里面包裹着一个小圆圈为deto的类。给tdfole设置要滚动的时间,次数,方向等。
    在这里插入图片描述
    设置@keyframes的关键帧,给一个要调用的类名为tdfole。
    在这里插入图片描述
    这样CSS3圆圈滚动就完成了。
    实现的效果图如下:
    在这里插入图片描述
    学习总结:通过这次学习我明白了如何运用CSS3的滚动的功能,这样有利于我做项目的时候要运用跳动按钮的帮助。

    展开全文
  • css实现圆球顺时针滚动

    千次阅读 2015-07-17 19:03:02
    round是细框,test是小球,inner是实心。其实动的不是小球,是细框,但是因为小球在细框里所以带着小球一起动。可以get的技能:margin为负值,定位的方法,css animation的用法, 不同浏览器的兼容(-webkit- ......
  • 在线段上滚动.exe

    2011-12-18 20:40:04
    在线段上滚动.exe
  • 为ViewPager添加圆点指示器,支持自动滚动和循环。压缩包里包括一个library和demo,demo需要引用library。(由于里面有几个图片,所以比较大) 用法介绍见:...
  • css3滚动的圆球动画特效
  • unity UGUI实现卡片椭圆方向滚动

    千次阅读 2017-06-22 11:54:31
    搭建简单的场景 运行效果 控制脚本: using UnityEngine; using System.Collections; using UnityEngine.UI; using DG.Tweening; public class CardMove : MonoBehaviour { GameObject[] sprites;... Vector

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 58,251
精华内容 23,300
关键字:

圆能滚动吗