zoukankan      html  css  js  c++  java
  • android尺子的自定义view——RulerView

    项目中用到自定义尺子的样式:

    原代码在github上找的,地址:https://github.com/QQabby/HorizontalRuler

    原效果为

    因为跟自己要使用的view稍有不同  所以做了一些修改,修改的注释都放在代码中了,特此记录一下。

    首先是一个自定义View:

      1 public class RuleView extends View {
      2 
      3     private Paint paint;
      4 
      5     private Context context;
      6 
      7     private int maxValue = 500;
      8     /**
      9      * 起点x的坐标
     10      */
     11     private float startX ;
     12 
     13     private float startY ;
     14     /**
     15      * 刻度线的长度
     16      */
     17     private float yLenght ;
     18     /**
     19      * 刻度的间隙
     20      */
     21 //    private float gap = 8f;
     22     private float gap = 10;
     23     /**
     24      * 文本的间隙
     25      */
     26     private float textGap = 10f;
     27     /**
     28      * 短竖线的高度
     29      */
     30     private float smallHeight = 10f;
     31     /**
     32      * 长竖线的高度
     33      */
     34     private float largeHeight = 22f;
     35     
     36     /**
     37      * 文本显示格式化
     38      */
     39     private DecimalFormat format;
     40 
     41     private DisplayMetrics metrics = null;
     42     /**
     43      * 文本的字体大小
     44      */
     45     private float mFontSize;
     46 
     47     private Handler mScrollHandler = null;
     48 
     49     private MyHorizontalScrollView horizontalScrollView;
     50 
     51     private int mCurrentX = -999999999;
     52     /**
     53      * 刻度进制
     54      */
     55 //    private float unit = 10f;
     56     private int unit = 10;//隔unit个刻度写一个数字
     57     //每个大刻度代表值iValue
     58     private int iValue = 10;
     59 
     60     boolean isDraw = true;
     61 
     62     public RuleView(Context context) {
     63         super(context);
     64         this.context = context;
     65         init();
     66     }
     67 
     68     public void setHorizontalScrollView(
     69             MyHorizontalScrollView horizontalScrollView) {
     70         this.horizontalScrollView = horizontalScrollView;
     71 
     72         this.horizontalScrollView.setOnTouchListener(new OnTouchListener() {
     73 
     74             @Override
     75             public boolean onTouch(View v, MotionEvent event) {
     76 
     77                 final int action = event.getAction();
     78                 switch (action) {
     79                 case MotionEvent.ACTION_DOWN:
     80 
     81                     break;
     82                 case MotionEvent.ACTION_MOVE:
     83 
     84                     mScrollHandler.removeCallbacks(mScrollRunnable);
     85                     break;
     86                 case MotionEvent.ACTION_UP:
     87 
     88                     mScrollHandler.post(mScrollRunnable);
     89                     break;
     90                 }
     91                 return false;
     92             }
     93         });
     94     }
     95 
     96     public RuleView(Context context, AttributeSet attrs) {
     97         super(context, attrs);
     98         this.context = context;
     99 
    100         init();
    101     }
    102 
    103     public void init() {
    104 
    105 //        format = new DecimalFormat("0.0");
    106         format = new DecimalFormat("0");//不使用浮点数格式
    107 
    108         metrics = new DisplayMetrics();
    109         WindowManager wmg = (WindowManager) context
    110                 .getSystemService(Context.WINDOW_SERVICE);
    111         wmg.getDefaultDisplay().getMetrics(metrics);
    112 
    113         paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    114         paint.setStyle(Paint.Style.FILL);
    115         paint.setStrokeWidth(getResources().getDimension(R.dimen.ui_1_dip));
    116 //        paint.setStrokeWidth(2);
    117         paint.setColor(Color.parseColor("#999999"));
    118 
    119         mFontSize = ScreenUtil.dip2px(context, 16);
    120 //        startY = ScreenUtil.dip2px(context, 20f);
    121         startY = ScreenUtil.dip2px(context, 0);//Y轴由0开始,即最顶端,不用设置适配布局文件RuleView的android:layout_marginTop="-20dp"
    122         yLenght = ScreenUtil.dip2px(context, 10);
    123 //        gap = ScreenUtil.dip2px(context, 8f);
    124         gap = ScreenUtil.dip2px(context, 10);
    125 //        startX = ScreenUtil.getScreenWidth(context)/ 2.0f- getResources().getDimension(R.dimen.ui_10_dip)  ;
    126         startX = ScreenUtil.getScreenWidth(context)/ 2.0f;//X轴不减去10dp,则三角形顶点可以刚好最准0位置
    127 
    128         // + getResources().getDimension(R.dimen.text_h2)/2.0f
    129         // Util.dip2px(context, 13f) +
    130 
    131         mScrollHandler = new Handler(context.getMainLooper());
    132 
    133     }
    134 
    135     @Override
    136     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    137 
    138         float width =  maxValue * gap + ScreenUtil.getScreenWidth(context) - getResources().getDimension(R.dimen.ui_10_dip)*2.0f ;
    139 
    140         // int widthMode = MeasureSpec.getMode(heightMeasureSpec);
    141         // if(widthMode == MeasureSpec.AT_MOST){
    142         // Log.d("TAG", "mode::AT_MOST");
    143         // }else if(widthMode == MeasureSpec.EXACTLY){
    144         // Log.d("TAG", "mode::EXACTLY");
    145         // }else if(widthMode == MeasureSpec.UNSPECIFIED){
    146         // Log.d("TAG", "mode::UNSPECIFIED");
    147         // }
    148 
    149         setMeasuredDimension((int) width, heightMeasureSpec);
    150     }
    151 
    152     @Override
    153     protected void onDraw(final Canvas canvas) {
    154         super.onDraw(canvas);
    155 
    156         // 画刻度线
    157         paint.setColor(getResources().getColor(R.color.gray_bg_high));// 刻度颜色
    158         for (int i = 0; i <= maxValue; i++) {
    159 
    160             if (i % 5 == 0) {
    161                 yLenght = ScreenUtil.dip2px(context, largeHeight);
    162             } else {
    163                 yLenght = ScreenUtil.dip2px(context, smallHeight);
    164             }
    165             canvas.drawLine(i * gap + startX, startY, i * gap + startX, yLenght
    166                     + startY, paint);
    167         }
    168 
    169         paint.setTextSize(mFontSize);
    170 
    171         // 每10个刻度写一个数字
    172         textGap = gap * unit;
    173 
    174         // 画刻度文字30
    175         paint.setColor(getResources().getColor(R.color.textGray));// 文字颜色
    176         for (int i = 0; i <= maxValue / unit; i++) {
    177 
    178 //            String text = format.format(i + 1) + "";//从0开始计数时不用加1
    179             String text = format.format(i * iValue) + "";//乘以每刻度的值iValue
    180             // 获取文本的宽度
    181             float width = ScreenUtil.px2dip(context, calculateTextWidth(text)) / 2f;
    182 
    183             canvas.drawText(
    184                     text,
    185                     startX - width + i * textGap,
    186                     (startY + ScreenUtil.dip2px(context, largeHeight))
    187                             + ScreenUtil.dip2px(context, 24), paint);//字体大小
    188         }
    189     }
    190 
    191     /**
    192      * 获取TextView中文本的宽度
    193      */
    194     private float calculateTextWidth(String text) {
    195         if (TextUtils.isEmpty(text)) {
    196             return 0;
    197         }
    198         TextPaint textPaint = new TextPaint();
    199         textPaint.setTextSize(mFontSize * metrics.scaledDensity);
    200         final float textWidth = textPaint.measureText(text);
    201 
    202         return textWidth;
    203     }
    204 
    205     DecimalFormat df = new DecimalFormat("0.0");
    206 
    207     /**
    208      * 当滑动尺子的时候
    209      */
    210     int scrollWidth = 0;
    211 
    212     public void setScrollerChanaged(int l, int t, int oldl, int oldt) {
    213         // 滑动的距离
    214         scrollWidth = l;
    215 
    216         float number = scrollWidth / gap;
    217         float result = number / unit;
    218 
    219         listener.onSlide(result);
    220     }
    221 
    222     public onChangedListener listener;
    223 
    224     public interface onChangedListener {
    225 
    226         void onSlide(float number);
    227     }
    228 
    229     public void onChangedListener(onChangedListener listener) {
    230         this.listener = listener;
    231     }
    232 
    233     /**
    234      * 滚动监听线程
    235      */
    236     private Runnable mScrollRunnable = new Runnable() {
    237 
    238         @Override
    239         public void run() {
    240             if (mCurrentX == horizontalScrollView.getScrollX()) {// 滚动停止了
    241 
    242                 try {
    243 
    244                     float x = horizontalScrollView.getScrollX();
    245                     float value = (x / (gap * unit));// 当前的值
    246                     String s = df.format(value);
    247 
    248                     // 滑动到11.0 ok
    249                     int scrollX = (int) (Double.parseDouble(s) * gap * unit);
    250 
    251                     horizontalScrollView.smoothScrollTo(scrollX, 0);
    252 
    253                 } catch (NumberFormatException numExp) {
    254                     numExp.printStackTrace();
    255                 }
    256                 mScrollHandler.removeCallbacks(this);
    257             } else {
    258                 mCurrentX = horizontalScrollView.getScrollX();
    259                 mScrollHandler.postDelayed(this, 50);
    260             }
    261         }
    262     };
    263 
    264     /**
    265      * 设置默认刻度尺的刻度值,不会滚动到相应的位置
    266      * 
    267      * @param scaleValue
    268      */
    269     public void setDefaultScaleValue(float scaleValue) {
    270 
    271 //        final int scrollX = (int) ((scaleValue - 1.0f) * gap * unit);//从0开始计数时不用减去1
    272         final int scrollX = (int) (scaleValue * gap * unit / 10);//每个值在设置刻度时会乘以10,所以除去
    273 
    274         new Handler().postDelayed(new Runnable() {
    275 
    276             @Override
    277             public void run() {
    278 
    279                 horizontalScrollView.smoothScrollTo(scrollX, 0);
    280             }
    281         }, 100);
    282     }
    283 
    284     /**
    285      * 设置刻度值
    286      */
    287     public void setScaleValue(int iValue) {
    288         this.iValue = iValue;
    289     }
    290 
    291     /**
    292      * 设置刻度最小值
    293      */
    294     public void setMinScaleValue(Float minScaleValue) {
    295         // this.minScaleValue = minScaleValue;
    296     }
    297 
    298     /**
    299      * 获取刻度最大值
    300      */
    301     public Float getMaxScaleValue() {
    302         // return maxScaleValue;
    303         return 33.0f;
    304     }
    305 
    306     /**
    307      * 设置刻度最大值
    308      */
    309     public void setMaxScaleValue(Float maxScaleValue) {
    310         // this.maxScaleValue = maxScaleValue;
    311     }
    312 
    313     /**
    314      * 设置当前刻度尺的刻度值,并滚动到相应的位置
    315      * 
    316      * @param scaleValue
    317      */
    318     public void setScaleScroll(float scaleValue) {
    319 
    320         int scrollX = (int) ((scaleValue - 1.0f) * gap * unit);
    321 
    322         horizontalScrollView.smoothScrollTo(scrollX, 0);
    323     }
    324 }

    另外用到一个自定义的scrollView:

     1 public class MyHorizontalScrollView extends HorizontalScrollView {
     2 
     3     private OnScrollListener onScrollListener = null;
     4 
     5     public MyHorizontalScrollView(Context context) {
     6         this(context, null);
     7     }
     8     public MyHorizontalScrollView(Context context, AttributeSet attrs) {
     9         this(context, attrs, 0);
    10     }
    11     public MyHorizontalScrollView(Context context, AttributeSet attrs,
    12             int defStyleAttr) {
    13         super(context, attrs, defStyleAttr);
    14     }
    15 
    16     @Override
    17     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    18         super.onScrollChanged(l, t, oldl, oldt);
    19         if(onScrollListener != null){
    20             onScrollListener.onScrollChanged(l, t, oldl, oldt);
    21         }
    22     }
    23 
    24     public interface OnScrollListener {
    25         public void onScrollChanged(int l, int t, int oldl, int oldt);
    26     }
    27 
    28     public void setOnScrollListener(OnScrollListener onScrollListener) {
    29         this.onScrollListener = onScrollListener;
    30     }
    31 }

    直尺上的黄色三角标其实是嵌在布局上的,在drawble文件中实现

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:id="@+id/shape_id">
            <!--&lt;!&ndash; 正三角 &ndash;&gt;-->
            <!--<rotate-->
            <!--android:fromDegrees="45"-->
            <!--android:toDegrees="45"-->
            <!--android:pivotX="-40%"-->
            <!--android:pivotY="80%">-->
            <!-- 倒三角 -->
            <rotate
                android:fromDegrees="45"
                android:toDegrees="45"
                android:pivotX="135%"
                android:pivotY="15%"
                >
                <shape android:shape="rectangle">
                    <solid android:color="@color/main_yellow"/>
                </shape>
            </rotate>
        </item>
    
    </layer-list>
    shape_triangle

    下面是布局文件,注意RuleView是嵌在ScrollView中的:

    <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="300px"
                android:layout_marginTop="30px"
                android:background="#fff">
            <MyHorizontalScrollView
                android:id="@+id/hor_scrollview"
                android:layout_width="match_parent"
                android:layout_height="300px"
                android:scrollbars="none" >
    
    
                <RuleView
                    android:id="@+id/rule_view"
                    android:background="@color/main_white"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_gravity="top"/>
            </MyHorizontalScrollView>
                <View
                    android:layout_width="match_parent"
                    android:layout_height="1px"
                    android:background="@color/gray_bg"
                    android:layout_centerHorizontal="true"
                    android:layout_alignParentBottom="true" />
                <View
                    android:layout_width="30px"
                    android:layout_height="30px"
                    android:layout_centerHorizontal="true"
                    android:layout_alignParentTop="true"
                    android:background="@drawable/shape_triangle" />
            </RelativeLayout>

    最后在界面中的使用:

            ruleView = (RuleView) findViewById(R.id.rule_view);
    
            horizontalScrollView = (MyHorizontalScrollView) findViewById(R.id.hor_scrollview);
            horizontalScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);// 去掉超出滑动后出现的阴影效果
    
            // 设置水平滑动
            ruleView.setHorizontalScrollView(horizontalScrollView);
            ruleView.setDefaultScaleValue(num);
    
            // 当滑动尺子的时候
            horizontalScrollView.setOnScrollListener(new MyHorizontalScrollView.OnScrollListener() {
    
                @Override
                public void onScrollChanged(int l, int t, int oldl, int oldt) {
    
                    ruleView.setScrollerChanaged(l, t, oldl, oldt);
                }
            });
    
    
            ruleView.onChangedListener(new RuleView.onChangedListener() {
                @Override
                public void onSlide(float number) {
    
                    int num = (int) (number * 10);
                    tvNum.setText(num+"");
                }
            });
  • 相关阅读:
    CI框架 -- 核心文件 之 Loader.php(加载器)
    CI框架 -- 核心文件 之 Lang.php(加载语言包)
    CI框架 -- 核心文件 之 Input.php(输入数据处理文件)
    CI框架 -- 核心文件 之 Hooks.php
    CI框架 -- 核心文件 之 Exceptions.php
    CI框架 -- 配置文件config.php
    网站后台发通知页面效果图
    校内通知-Notifications表增加老师,家长,学生发送范围字段
    jqGrid设置指定行的背景色
    SQLServer数据库监控代码
  • 原文地址:https://www.cnblogs.com/Sharley/p/9229907.html
Copyright © 2011-2022 走看看