From 07a4e46efd0d180f881a9761c6f737e5d1c47848 Mon Sep 17 00:00:00 2001
From: JLChen <551775569@qq.com>
Date: 星期五, 08 一月 2021 10:36:41 +0800
Subject: [PATCH] 2021-01-08 1.HDL_Widget Android和iOS精简版的库,去掉高德SDK,和iOS裁剪方法
---
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress.png | 0
HDL_Widget_XM/HDLWidget_Android/.idea/misc.xml | 4
HDL_Widget_XM/HDLWidget_Android/.idea/runConfigurations.xml | 12
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/Masonry.h | 29
HDL_Widget_XM/HDLWidget_Android/app/libs/HDLWidgetXM-release.aar | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress_close.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLRollCurtainSeekBar.java | 584 +
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/interfaces/IPickerViewData.java | 8
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_back.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/attrs.xml | 68
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLUtlis.java | 51
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_progress.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_progress.png | 0
HDL_Widget_XM/HDLWidget_Android/app/build.gradle | 36
iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.pbxproj | 668 +
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_top.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_bg.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint+Private.h | 66
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPager.java | 310
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_zoom_out.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.m | 127
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_curtain_seek_bar.xml | 103
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/ILockView.java | 44
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.h | 60
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLWIdgetListActivity.java | 110
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/bg.xml | 9
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CurtainSeekBarActivity.java | 92
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/MainActivity.java | 247
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/styles.xml | 31
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelTime.java | 929 +
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.h | 137
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values-zh/strings.xml | 26
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASShorthandAdditions.h | 41
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_time.xml | 58
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/OnItemSelectedListener.java | 6
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectListener.java | 13
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/OptionsPickerBuilder.java | 278
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/DiyImageSeekBarActivity.java | 90
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.m | 682 +
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_bg.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/LoopViewGestureListener.java | 26
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.h | 32
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_geofence_round.xml | 173
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_wave_seek_bar.xml | 69
HDL_Widget_XM/HDLWidget_Android/build.gradle | 31
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/HDLCropImageActivity.java | 377
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageVerticalSeekBar.java | 549
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelOptions.java | 447
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.m | 144
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/ChinaDate.java | 352
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress2.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/OptionsPickerView.java | 256
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectListener.java | 14
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_open.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/QQLockView.java | 169
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_open.png | 0
HDL_Widget_XM/README.md | 11
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview.xml | 28
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLUtlisXM.java | 228
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_open.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.h | 127
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.m | 517
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_diy_image_horizontal_seek_bar.xml | 75
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.h | 189
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.m | 485
HDL_Widget_XM/HDLWidget_Android/app/src/main/AndroidManifest.xml | 43
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/ic_launcher.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.m | 46
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.h | 49
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.h | 149
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.m | 508
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_out.xml | 18
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_gesture_lock.xml | 55
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.m | 39
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.h | 123
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.m | 132
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.h | 36
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.h | 30
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_bg_top.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_bg.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_add.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.m | 190
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.h | 34
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_bg.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.h | 58
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CheckPermissionsCropImageActivity.java | 199
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_click_effect_select.xml | 11
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_layout_basepickerview.xml | 16
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.h | 161
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.m | 43
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.m | 610 +
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.m | 568
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASUtilities.h | 136
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.h | 22
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.m | 146
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/SmoothScrollTimerTask.java | 64
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/LunarCalendar.java | 429
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/AndroidManifest.xml | 26
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/.gitignore | 1
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.m | 108
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CropImageBean.java | 55
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.h | 16
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.h | 187
iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.h | 61
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/PickerViewActivity.java | 84
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.m | 887 +
.gitignore | 99
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.m | 13
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.m | 502
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerView.java | 521
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_shadow_w.xml | 44
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.h | 107
iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.m | 418
HDL_Widget_XM/HDLWidget_Android/.idea/modules.xml | 13
HDL_Widget_XM/HDLWidget_Android/README.md | 11
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/proguard-rules.pro | 21
HDL_Widget_XM/HDLWidget_Android/app/.gitignore | 1
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_arc_scale_bg.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/TimePickerView.java | 288
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/ISelectTimeCallback.java | 10
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_crop_image.xml | 10
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/ArcScaleSeekBarActivity.java | 73
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.m | 162
HDL_Widget_XM/HDLWidget_Android/gradlew.bat | 84
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/strings.xml | 26
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/view/WheelView.java | 802 +
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/configure/PickerOptions.java | 116
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_picker_view.xml | 57
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectChangeListener.java | 12
iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata | 7
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_w.xml | 6
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.h | 111
HDL_Widget_XM/HDLWidget_Android/.idea/codeStyles/Project.xml | 116
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.h | 132
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLCurtainSeekBar.java | 610 +
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.h | 72
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_hdlwidget_list.xml | 29
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.m | 186
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPagerAdapter.java | 91
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/LockViewFactory.java | 13
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/CustomListener.java | 13
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/dimens.xml | 15
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/ArrayWheelAdapter.java | 46
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_out_bottom.xml | 11
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_mylocation.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_include_pickerview_topbar.xml | 55
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_open.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.h | 33
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_gallery_banner_view_layout.xml | 18
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_in_bottom.xml | 11
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.m | 360
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.h | 32
iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.m | 434
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.h | 41
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.m | 13
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcScaleSeekBar.java | 783 +
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_main.xml | 154
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_progress.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_b.xml | 6
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/adapter/WheelAdapter.java | 25
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/strings.xml | 3
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/colors.xml | 24
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/InertiaTimerTask.java | 79
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnDismissListener.java | 8
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/integers.xml | 5
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_options.xml | 39
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageSeekBar.java | 545
HDL_Widget_XM/HDLWidget_Android/app/proguard-rules.pro | 21
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/GestureLockView.java | 799 +
HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.properties | 6
iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | 8
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/build.gradle | 36
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.m | 312
HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.jar | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/xml/hdl_filepaths.xml | 4
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/PickerViewAnimateUtil.java | 26
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.h | 134
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/NumericWheelAdapter.java | 47
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.m | 498
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.h | 33
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLWaveSeekBar.java | 630 +
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.m | 13
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/QRCodeActivity.java | 146
HDL_Widget_XM/HDLWidget_Android/gradle.properties | 14
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_bg.png | 0
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/colors.xml | 42
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/selector_pickerview_btn.xml | 6
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/styles.xml | 13
HDL_Widget_XM/HDLWidget_Android/settings.gradle | 2
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/CoverTransformer.java | 66
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerViewNT.java | 567
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.m | 501
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/WaveSeekBarActivity.java | 77
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.h | 132
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_search.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_delete.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_bg_top.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.m | 73
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.h | 21
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/TimePickerBuilder.java | 295
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.m | 520
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.m | 68
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.m | 87
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress.png | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_home.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.h | 26
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.h | 33
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.m | 183
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLOACCurtainSeekBar.java | 597 +
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/hdl_seekbar_thumb.xml | 10
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.h | 29
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.m | 165
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.h | 18
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLZoomPageTransformer.java | 83
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.m | 163
iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.h | 78
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_qrcode.xml | 133
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.h | 22
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_progress.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.m | 15
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.h | 39
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_bg.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.m | 891 +
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/MessageHandler.java | 42
HDL_Widget_XM/HDLWidget_Android/.idea/encodings.xml | 4
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.h | 27
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.m | 426
iOS/libHDLWidgetLibrary.a | 0
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_air_button.xml | 73
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectChangeListener.java | 11
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CoverFlowViewActivity.java | 84
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_open.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.m | 40
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_arc_scale_seek_bar.xml | 146
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASShorthandAdditions.h | 133
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/BasePickerView.java | 361
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.h | 25
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.m | 301
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.m | 17
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_cover_flow_view.xml | 68
iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.h | 62
HDL_Widget_XM/HDLWidget_Android/gradlew | 172
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_in.xml | 19
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.h | 272
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_top.png | 0
HDL_Widget_XM/HDLWidget_Android/app/src/main/res/xml/hdl_filepaths.xml | 4
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_now.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.h | 135
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.m | 401
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.m | 13
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.h | 130
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcSeekBar.java | 1006 +
HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/GestureLockActivity.java | 41
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.h | 32
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.h | 146
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.m | 525
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.h | 48
HDL_Widget_XM/HDLWidget_Android/.gitignore | 68
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_g.xml | 6
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.m | 273
HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gps_point.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress_close.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.h | 42
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_open.png | 0
iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close2.png | 0
267 files changed, 34,907 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 3a36c6e..99972b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,14 @@
+
+# Created by https://www.gitignore.io/api/android
+# Edit at https://www.gitignore.io/?templates=android
+
+### Android ###
# Built application files
*.apk
*.ap_
+*.aab
-# Files for the Dalvik VM
+# Files for the ART/Dalvik VM
*.dex
# Java class files
@@ -11,6 +17,8 @@
# Generated files
bin/
gen/
+out/
+release/
# Gradle files
.gradle/
@@ -22,5 +30,92 @@
# Proguard folder generated by Eclipse
proguard/
-#Log Files
+# Log Files
*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+### Android Patch ###
+gen-external-apklibs
+output.json
+
+# End of https://www.gitignore.io/api/android
+
+
+# Xcode
+#
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+*.xcuserstate
+
+# CocoaPods
+#
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
+#
+# Pods/
diff --git a/HDL_Widget_XM/HDLWidget_Android/.gitignore b/HDL_Widget_XM/HDLWidget_Android/.gitignore
new file mode 100644
index 0000000..74ff705
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.gitignore
@@ -0,0 +1,68 @@
+# Built application files
+*.apk
+*.ap_
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/caches
+
+# Keystore files
+# Uncomment the following line if you do not want to check your keystore files in.
+#*.jks
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+
+# Google Services (e.g. APIs or Firebase)
+google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+
+history/
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/.idea/codeStyles/Project.xml b/HDL_Widget_XM/HDLWidget_Android/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..681f41a
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.idea/codeStyles/Project.xml
@@ -0,0 +1,116 @@
+<component name="ProjectCodeStyleConfiguration">
+ <code_scheme name="Project" version="173">
+ <codeStyleSettings language="XML">
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ </indentOptions>
+ <arrangement>
+ <rules>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:android</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:id</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>name</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>style</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>ANDROID_ATTRIBUTE_ORDER</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_ATTRIBUTE />
+ <XML_NAMESPACE>.*</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ </rules>
+ </arrangement>
+ </codeStyleSettings>
+ </code_scheme>
+</component>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/.idea/encodings.xml b/HDL_Widget_XM/HDLWidget_Android/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/.idea/misc.xml b/HDL_Widget_XM/HDLWidget_Android/.idea/misc.xml
new file mode 100644
index 0000000..0d45e8d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
+</project>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/.idea/modules.xml b/HDL_Widget_XM/HDLWidget_Android/.idea/modules.xml
new file mode 100644
index 0000000..a547892
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.idea/modules.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/HDLWidgetXM/HDLWidgetXM.iml" filepath="$PROJECT_DIR$/HDLWidgetXM/HDLWidgetXM.iml" />
+ <module fileurl="file://$PROJECT_DIR$/HDLWidget_Android.iml" filepath="$PROJECT_DIR$/HDLWidget_Android.iml" />
+ <module fileurl="file://$PROJECT_DIR$/HDLWidgetXM/HDLWidget_Android-HDLWidgetXM.iml" filepath="$PROJECT_DIR$/HDLWidgetXM/HDLWidget_Android-HDLWidgetXM.iml" />
+ <module fileurl="file://$PROJECT_DIR$/app/HDLWidget_Android-app.iml" filepath="$PROJECT_DIR$/app/HDLWidget_Android-app.iml" />
+ <module fileurl="file://$PROJECT_DIR$/HDL_Widget_XM-HDLWidget_Android.iml" filepath="$PROJECT_DIR$/HDL_Widget_XM-HDLWidget_Android.iml" />
+ <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
+ </modules>
+ </component>
+</project>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/.idea/runConfigurations.xml b/HDL_Widget_XM/HDLWidget_Android/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunConfigurationProducerService">
+ <option name="ignoredProducers">
+ <set>
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+ </set>
+ </option>
+ </component>
+</project>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/.gitignore b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/build.gradle b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/build.gradle
new file mode 100644
index 0000000..781208e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 28
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 28
+ versionCode 4
+ versionName "1.0.4"
+ }
+
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ repositories {
+ flatDir {
+ dirs 'libs'
+ }
+ }
+
+
+}
+
+dependencies {
+ implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/proguard-rules.pro b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/AndroidManifest.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..159ce9d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.hdl.widgetxm">
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 璇诲彇缂撳瓨鏁版嵁 -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 鐢ㄤ簬璇诲彇鎵嬫満褰撳墠鐨勭姸鎬� -->
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <application>
+ <!--<activity android:name="com.hdl.widget.qrc.QrcCaptureActivity"></activity>-->
+ <activity android:name="com.hdl.widget.cropimage.CheckPermissionsCropImageActivity" />
+ <activity android:name="com.hdl.widget.cropimage.HDLCropImageActivity" />
+
+
+ <!--<provider-->
+ <!--android:name="android.support.v4.content.FileProvider"-->
+ <!--android:authorities="com.hdl.widgetxm.fileprovider"-->
+ <!--android:exported="false"-->
+ <!--android:grantUriPermissions="true">-->
+ <!--<meta-data-->
+ <!--android:name="android.support.FILE_PROVIDER_PATHS"-->
+ <!--android:resource="@xml/hdl_filepaths" />-->
+ <!--</provider>-->
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/CoverTransformer.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/CoverTransformer.java
new file mode 100644
index 0000000..000a833
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/CoverTransformer.java
@@ -0,0 +1,66 @@
+package com.hdl.widget.CoverFlowViewPager;
+
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+/**
+ * Created by JLChen on 2019/8/26
+ */
+public class CoverTransformer implements ViewPager.PageTransformer {
+
+ public static final String TAG = "CoverTransformer";
+
+ public static final float SCALE_MIN = 0.3f;
+ public static final float SCALE_MAX = 1f;
+ public static final float MARGIN_MIN = 0f;
+ public static final float MARGIN_MAX = 50f;
+ public float scale = 0f;
+
+ private float pagerMargin = 0f;
+ private float spaceValue = 0f;
+ private float rotationX = 0f;
+ private float rotationY = 0f;
+
+ public CoverTransformer(float scale, float pagerMargin, float spaceValue, float rotationY) {
+ this.scale = scale;
+ this.pagerMargin = pagerMargin;
+ this.spaceValue = spaceValue;
+ this.rotationY = rotationY;
+ }
+
+ @Override
+ public void transformPage(View page, float position) {
+
+// Log.d(TAG,"position:"+position);
+
+
+ if(rotationY != 0){
+ float realRotationY = Math.min(rotationY,Math.abs(position * rotationY));
+ page.setRotationY(position < 0f ? realRotationY : - realRotationY);
+ }
+
+ if (scale != 0f) {
+ float realScale = getFloat(1 - Math.abs(position * scale), SCALE_MIN, SCALE_MAX);
+ page.setScaleX(realScale);
+ page.setScaleY(realScale);
+ }
+
+ if (pagerMargin != 0) {
+
+ float realPagerMargin = position * (pagerMargin);
+
+ if (spaceValue != 0) {
+ float realSpaceValue = getFloat(Math.abs(position * spaceValue),MARGIN_MIN,MARGIN_MAX);
+ realPagerMargin += (position > 0) ? realSpaceValue : - realSpaceValue;
+ }
+
+ page.setTranslationX(realPagerMargin);
+ }
+
+ }
+
+ private static float getFloat(float value,float minValue,float maxValue){
+ return Math.min(maxValue, Math.max(minValue, value));
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPager.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPager.java
new file mode 100644
index 0000000..bd7d5f8
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPager.java
@@ -0,0 +1,310 @@
+package com.hdl.widget.CoverFlowViewPager;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Handler;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+
+import com.hdl.widgetxm.R;
+
+import java.util.List;
+
+/**
+ * Created by JLChen on 2019/8/22
+ */
+public class HDLCoverFlowViewPager extends RelativeLayout implements ViewPager.OnPageChangeListener {
+ private View mLayout;//甯冨眬
+ private Activity mContext;//涓婁笅鏂�
+ private ViewPager mViewPager;//viewpager
+ private HDLCoverFlowViewPagerAdapter mPagerAdapter;//adapter
+ private List<View> mViewsList;//url鏁扮粍
+ private int currentIndex = 0;//褰撳墠瀹為檯page
+// private int startCurrentIndex = 0;//褰撳墠page
+ private long secondTime = 0, firstTime = 0;
+
+ //private Timer mTimer=null;//瀹氭椂鍣�
+ //private MyTimerTask mTimerTask=null;
+
+ private Handler mHandler = null;
+ private AutoRollRunnable mAutoRollRunnable = null;
+ private int mRollTime = 5000;
+ // private int resId_piont_press= R.mipmap.ic_banner_point_press;
+// private int resId_piont=R.mipmap.ic_banner_point;
+ private boolean isPoint = false;//寮�鍚寚绀哄櫒
+
+
+ private int mScrolledCurrentIndex = 0;
+
+
+ public static interface OnClickGalleryListener {
+ void onGalleryClick(int position);
+
+ void onGalleryPositionChange(int position);
+ }
+
+ private OnClickGalleryListener mOnClickGalleryListener;
+
+ public HDLCoverFlowViewPager addGalleryListener(OnClickGalleryListener listener) {
+ mOnClickGalleryListener = listener;
+ return this;
+ }
+
+ //ui鏇存柊
+// Handler mHandler=mHandler= new Handler(){
+// public void handleMessage(Message msg) {
+// int index = mViewPager.getCurrentItem()+1;//涓嬩竴涓〉
+// mViewPager.setCurrentItem(index);//璁剧疆姝ゆ瑕佹樉绀虹殑pager
+// currentIndex=index%mList.size();
+// setImageBackground(currentIndex);
+// }
+// };
+
+ public HDLCoverFlowViewPager(Context context) {
+ super(context);
+ this.mContext = (Activity) context;
+ }
+
+ public HDLCoverFlowViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ this.mContext = (Activity) context;
+ }
+
+ public HDLCoverFlowViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.mContext = (Activity) context;
+
+ }
+
+ /**
+ * 鍒濆鍖杤iewpager
+ *
+ * @param list view闆嗗悎
+ * @param isGallery 鏄惁浣跨敤3D鐢诲粖鏁堟灉
+ */
+ public HDLCoverFlowViewPager initBanner(List<View> list, boolean isGallery) {
+ mViewsList = list;
+ //寮曞叆甯冨眬
+ mLayout = LayoutInflater.from(mContext).inflate(R.layout.hdl_gallery_banner_view_layout, null);
+ mViewPager = (ViewPager) mLayout.findViewById(R.id.hdl_gallery_viewPager);//鍏抽棴
+// mLineIndicator = (LinearLayout) mLayout.findViewById(R.id.lineIndicator);
+// //鍒濆鍖栦綅缃�
+// currentIndex = startCurrentIndex%mList.size();
+ currentIndex = 0;
+ mPagerAdapter = new HDLCoverFlowViewPagerAdapter(mViewsList);
+ mPagerAdapter.setOnClickViewsListener(new HDLCoverFlowViewPagerAdapter.OnClickViewsListener() {
+ @Override
+ public void onViewsClick(int position) {
+ if (mOnClickGalleryListener != null) {
+ mOnClickGalleryListener.onGalleryClick(position);
+ }
+ }
+ });
+
+ mViewPager.setAdapter(mPagerAdapter);
+ if (isGallery) {
+ mViewPager.setPageTransformer(true, new HDLZoomPageTransformer());
+// mViewPager.setPageTransformer(true, new CoverTransformer(0.8f,0f, 0f,25f));
+ }
+
+ mViewPager.setCurrentItem(currentIndex);
+ mViewPager.setOffscreenPageLimit(2);//璁剧疆棰勫姞杞界殑鏁伴噺锛岃繖閲岃缃簡2,浼氶鍔犺浇涓績item宸﹁竟涓や釜Item鍜屽彸杈逛袱涓狪tem
+ mViewPager.addOnPageChangeListener(this);
+ return this;
+ }
+
+
+ /**
+ * 鍒濆鍖杤iewpager
+ *
+ * @param list view闆嗗悎
+ * @param isGallery 鏄惁浣跨敤3D鐢诲粖鏁堟灉
+ * @param rotationY 鏃嬭浆瑙掑害
+ */
+ public HDLCoverFlowViewPager initBanner(List<View> list, boolean isGallery, float rotationY) {
+ mViewsList = list;
+ rotationY = dip2px(rotationY);
+ //寮曞叆甯冨眬
+ mLayout = LayoutInflater.from(mContext).inflate(R.layout.hdl_gallery_banner_view_layout, null);
+ mViewPager = (ViewPager) mLayout.findViewById(R.id.hdl_gallery_viewPager);//鍏抽棴
+ mPagerAdapter = new HDLCoverFlowViewPagerAdapter(mViewsList);
+ mPagerAdapter.setOnClickViewsListener(new HDLCoverFlowViewPagerAdapter.OnClickViewsListener() {
+ @Override
+ public void onViewsClick(int position) {
+ if (mOnClickGalleryListener != null) {
+ mOnClickGalleryListener.onGalleryClick(position);
+ }
+ }
+ });
+
+ mViewPager.setAdapter(mPagerAdapter);
+ if (isGallery) {
+// mViewPager.setPageTransformer(true, new HDLZoomPageTransformer(alpha));
+ mViewPager.setPageTransformer(true, new CoverTransformer(0.3f,0f, 0f, rotationY));
+
+ }
+ mViewPager.setCurrentItem(currentIndex);
+ mViewPager.setOffscreenPageLimit(2);//璁剧疆棰勫姞杞界殑鏁伴噺锛岃繖閲岃缃簡2,浼氶鍔犺浇涓績item宸﹁竟涓や釜Item鍜屽彸杈逛袱涓狪tem
+ mViewPager.addOnPageChangeListener(this);
+ return this;
+ }
+
+// /**
+// * 娣诲姞鍦嗚
+// * @param corners
+// * @return
+// */
+// public HDLGalleryViewPager addRoundCorners(int corners){
+// mPagerAdapter.setmRoundCorners(corners);
+// return this;
+// }
+
+ /**
+ * @param columnMargin 涓や釜Page涔嬮棿鐨勮窛绂�
+ * @param rowMargin page鐨勫杈硅窛
+ * 娉ㄦ剰褰撴坊鍔犱簡3D鐢诲粖鏁堟灉鏃�,columnMargin灏介噺璁惧皬銆傚簲璇ユ湰鏄凡缁忚繘琛屼簡x銆亂鐨勭缉鏀�
+ */
+ public HDLCoverFlowViewPager addPageMargin(int columnMargin, int rowMargin) {
+
+ mViewPager.setPageMargin(dip2px(columnMargin));
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(dip2px(rowMargin), 0, dip2px(rowMargin), 0);
+ mViewPager.setLayoutParams(layout);
+ return this;
+ }
+
+//
+
+ /**
+ * 閰嶇疆瀹屾垚,灏嗗竷灞�娣诲姞鍒扮埗瀹瑰櫒
+ */
+ public HDLCoverFlowViewPager finishConfig() {
+ this.addView(mLayout);
+ return this;
+ }
+
+ /**
+ * 璁剧疆鏄惁寮�濮嬭嚜鍔ㄨ疆鎾紝骞惰缃椂闂撮棿闅�
+ */
+ public HDLCoverFlowViewPager addStartTimer(int time) {
+ mRollTime = time;
+ if (mHandler == null) {
+ mHandler = new Handler();
+ }
+ if (mAutoRollRunnable == null) {
+ mAutoRollRunnable = new AutoRollRunnable();
+ }
+
+ mAutoRollRunnable.start();
+ return this;
+ }
+
+ // 鍋滄杞挱
+ public void stopTimer() {
+ if (mAutoRollRunnable != null) {
+ mAutoRollRunnable.stop();
+ }
+ }
+
+ private class AutoRollRunnable implements Runnable {
+ //鏄惁鍦ㄨ疆鎾殑鏍囧織
+ boolean isRunning = false;
+
+ @Override
+ public void run() {
+ if (isRunning) {
+ int index = mViewPager.getCurrentItem() + 1;//涓嬩竴涓〉
+ mViewPager.setCurrentItem(index);//璁剧疆姝ゆ瑕佹樉绀虹殑pager
+ currentIndex = index % mViewsList.size();
+// setImageBackground(currentIndex);
+ mHandler.postDelayed(this, 1000 * mRollTime);
+ }
+ }
+
+ public void start() {
+ if (!isRunning) {
+ isRunning = true;
+ mHandler.removeCallbacks(this);
+ mHandler.postDelayed(this, 1000 * mRollTime);
+ }
+ }
+
+ public void stop() {
+ if (isRunning) {
+ mHandler.removeCallbacks(this);
+ isRunning = false;
+ }
+ }
+ }
+
+
+ /**
+ * 鏍规嵁鎵嬫満鐨勫垎杈ㄧ巼浠� dp 鐨勫崟浣� 杞垚涓� px(鍍忕礌)
+ */
+ public int dip2px(float dpValue) {
+ final float scale = mContext.getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ //---------------viewpager婊戝姩浜嬩欢-----------------
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+ if(mScrolledCurrentIndex == position) return;
+
+ mScrolledCurrentIndex = position;
+
+ if (mOnClickGalleryListener != null) {
+ mOnClickGalleryListener.onGalleryPositionChange(mScrolledCurrentIndex);
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+
+ /**
+ * 婊戝姩鏃跺悓姝ユ敼鍙樺簳閮ㄥ皬鍦嗙偣
+ *
+ * @param position
+ */
+ @Override
+ public void onPageSelected(int position) {
+ currentIndex = position;
+ }
+
+
+ public void updateViewsList(List<View> list){
+ mViewsList = list;
+ if(mPagerAdapter != null) {
+ mPagerAdapter.updateViewsList(mViewsList);
+ refreshViewPager();
+ }
+ }
+
+ private void refreshViewPager(){
+ currentIndex = 0;
+ mPagerAdapter.notifyDataSetChanged();
+ if(mViewsList.size() > 1) {
+ mViewPager.setCurrentItem(currentIndex + 1);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mViewPager.setCurrentItem(currentIndex);
+ }
+ }, 1);
+ }
+ }
+
+ public void setCurrentItem(int item){
+ currentIndex = item;
+ mViewPager.setCurrentItem(item);
+ }
+}
+
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPagerAdapter.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPagerAdapter.java
new file mode 100644
index 0000000..80cc588
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLCoverFlowViewPagerAdapter.java
@@ -0,0 +1,91 @@
+package com.hdl.widget.CoverFlowViewPager;
+
+import android.support.v4.view.PagerAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+/**
+ * Created by JLChen on 2019/8/22
+ */
+public class HDLCoverFlowViewPagerAdapter extends PagerAdapter {
+ private List<View> mList;
+ private int mRoundCorners = -1;
+
+ /**
+ * 璁剧疆鍦嗚
+ *
+ * @param mRoundCorners
+ */
+ public void setmRoundCorners(int mRoundCorners) {
+ this.mRoundCorners = mRoundCorners;
+ }
+
+ /**
+ * 鐐瑰嚮鍥炶皟
+ */
+ public static interface OnClickViewsListener {
+ void onViewsClick(int position);
+
+// void onViewsChange(int position);
+ }
+
+ private OnClickViewsListener mOnClickViewsListener;
+
+ public void setOnClickViewsListener(OnClickViewsListener listener) {
+ mOnClickViewsListener = listener;
+
+ }
+
+ public HDLCoverFlowViewPagerAdapter(List<View> list) {
+ this.mList = list;
+// this.mContext = context;
+ }
+
+ @Override
+ public int getCount() {
+ return this.mList.size();
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ container.removeView((View) object);
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, final int position) {
+// final int index = position % mList.size();
+ View view = mList.get(position);
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mOnClickViewsListener.onViewsClick(position);
+ }
+ });
+
+ container.addView(view);
+ return view;
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ // 鏈�绠�鍗曡В鍐� notifyDataSetChanged() 椤甸潰涓嶅埛鏂伴棶棰樼殑鏂规硶
+ return POSITION_NONE;
+ }
+
+ public void updateViewsList(List<View> list){
+ mList = list;
+// notifyDataSetChanged();
+ }
+
+
+
+}
+
+
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLZoomPageTransformer.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLZoomPageTransformer.java
new file mode 100644
index 0000000..df8b816
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/CoverFlowViewPager/HDLZoomPageTransformer.java
@@ -0,0 +1,83 @@
+package com.hdl.widget.CoverFlowViewPager;
+
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+/**
+ * Created by JLChen on 2019/8/22
+ */
+public class HDLZoomPageTransformer implements ViewPager.PageTransformer {
+
+ private static final float MAX_SCALE = 1.0f;//0缂╂斁
+
+ private static final float MIN_SCALE = 0.85f;//0.85缂╂斁
+
+ private float MIN_ALPHA = 1.0f;//鏈�灏忛�忔槑搴�
+
+ public static final float MARGIN_MIN = 0f;
+ public static final float MARGIN_MAX = 50f;
+
+ public HDLZoomPageTransformer() {
+ }
+
+ public HDLZoomPageTransformer(float MIN_ALPHA) {
+ this.MIN_ALPHA = MIN_ALPHA;
+ }
+
+ @Override
+ public void transformPage(View view, float position) {
+ //setScaleY鍙敮鎸乤pi11浠ヤ笂
+ /**
+ * (-oo,-1) 鐩稿浜庡乏杈圭涓�椤碉紝鍏跺乏杈圭殑鎵�鏈夐〉闈� **
+ * x銆亂鎷変几涓篗IN_SCALE銆侀�忔槑搴IN_ALPHA
+ */
+ if (position < -1) {
+ view.setScaleX(MIN_SCALE);
+ view.setScaleY(MIN_SCALE);
+ view.setAlpha(MIN_ALPHA);
+ }
+ /**
+ * [-1, 1 )褰撳墠椤电殑宸﹀彸绗竴椤�
+ */
+ else if (position < 1) {
+ float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
+ //[0, 1 锛� 鐩稿浜庡綋鍓嶉�変腑椤碉紝鍏跺彸杈圭涓�椤� **
+ if (position > 0) {
+ view.setTranslationX(-scaleFactor);
+ }
+ // [-1, 0 ) 鐩稿浜庡綋鍓嶉�変腑椤碉紝鍏跺乏杈圭殑绗竴椤�**
+ else if (position < 0) {
+ view.setTranslationX(scaleFactor);
+ }
+ view.setScaleY(scaleFactor);
+ view.setScaleX(scaleFactor);
+
+ // float alpha = 1f - Math.abs(position) * (1 - );
+
+ float alpha = MIN_ALPHA + (1 - MIN_ALPHA) * (1 - Math.abs(position));
+ view.setAlpha(alpha);
+
+ }
+ /**
+ * [1,+oo锛� 鐩稿浜庡彸杈圭涓�椤碉紝鍏跺彸杈圭殑鎵�鏈夐〉闈�
+ * x銆亂鎷変几涓篗IN_SCALE銆侀�忔槑搴IN_ALPHA
+ */
+ else { // (1,+Infinity]
+ view.setScaleX(MIN_SCALE);
+ view.setScaleY(MIN_SCALE);
+ view.setAlpha(MIN_ALPHA);
+ }
+
+
+ float realRotationY = Math.min(25f, Math.abs(position * 25f));
+ view.setRotationY(position < 0f ? realRotationY : - realRotationY);
+
+
+
+ }
+
+ private static float getFloat(float value,float minValue,float maxValue){
+ return Math.min(maxValue, Math.max(minValue, value));
+ }
+
+}
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcScaleSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcScaleSeekBar.java
new file mode 100644
index 0000000..7d93a44
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcScaleSeekBar.java
@@ -0,0 +1,783 @@
+package com.hdl.widget;
+
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+
+public class HDLArcScaleSeekBar extends View {
+ private static final String TAG = "HDLArcScaleSeekBar";
+
+ private static final int DEFAULT_ROUND_BORDER_COLOR = 0xFFEAEAEB;
+ private static final float CIRCLE_ANGLE = 360; // 鍦嗗懆瑙�
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+
+ private float mSeekBarWidth;
+ private float mSeekBarHeight;
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+ // 鐢诲渾寮х殑鐢荤瑪
+ private Paint mRoundPaint;
+ // 姝f柟褰㈢殑瀹介珮
+ private int mArcWidth;
+ // 鍦嗗姬鐨勫崐寰�
+ private float mArcRadius;
+ // 鐭╁舰
+ private RectF oval;
+ private float mOpenAngle = 90; // 寮�鍙g殑瑙掑害澶у皬 0 - 360
+ // 鍦嗗姬鐨勮捣濮嬭搴�
+ private float startAngle = 135;
+ private float endAngle = 45;
+
+ // 鍦嗗姬鐨勭粡杩囨�昏寖鍥磋搴﹁搴�
+ private float sweepAngle = 270;
+
+ private float mScaleLineHeight;
+ private float mScaleLineHeightOut;//绐佸嚭闀垮害涓虹嚎闀�1/4
+ private float mScaleLineWidth;
+ private float bgRoundWidth;
+ private float bgRoundPadding;
+ private float mRoundX = 0;
+ private float mLinePadding;
+
+ //寮�濮嬮鑹�
+ private int mStartColor;
+ //缁撴潫棰滆壊
+ private int mEndColor;
+ //褰撳墠棰滆壊
+ private int mNowColor;
+ // 缁樺埗鏂囧瓧
+ private Paint mTextPaint;
+ private float mTextSizeBig;
+ private float mTextSizeSmall;
+ // 瀛樻斁绗竴鏉℃按娉鍊�
+ private float[] firstWaterLine;
+ // 绗簩鏉�
+ private float[] secondWaterLine;
+ // 鐢绘按鐞冪殑鐢荤瑪
+ private Paint waterPaint;
+ // 褰卞搷涓夎鍑芥暟鐨勫垵鐩�
+ private float mWaveMove;
+ // 鍓垏鍦嗙殑鍗婂緞
+ private int clipRadius = 100;
+ // 娉㈡氮鍥哄畾楂樺害
+ private int mWaveHeight = 0;
+ //鍒诲害鐢荤瑪
+ private Paint linePaint;
+ //鍒诲害鎬绘暟
+ private int mLineCount = 100;
+ // 褰撳墠杩涘害鐨勫埢搴︾嚎鏁�
+ private int mTargetCount = 0;
+ //姣忔牸鍒诲害鐨勮搴�
+ private float mAngle;
+
+
+ //鏄惁鍙互鐐瑰嚮
+ private boolean isClickable = true;
+ //杩涘害鍗曚綅绗﹀彿
+ private String mProgressBarUnitSring = "鈩�";
+ //鏄惁鏄剧ず杩涘害鏂囧瓧
+ private boolean isProgressTextShow = true;
+ //鏄惁鏄剧ず绂荤嚎鐘舵��
+ private Paint offlinePaint;
+ private boolean isOffline = false;
+ private int offlineRadius = 10;
+
+// private Bitmap bgBitmap;
+// private float bgHeight;
+// private float bgWidtht;
+
+ public HDLArcScaleSeekBar(Context context) {
+ this(context,null);
+ }
+
+ public HDLArcScaleSeekBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ initData();
+// initView(context);
+ initPaint();
+ }
+
+// private void initImageView(){
+// bgHeight = clipRadius/2.0f;
+// bgWidtht = clipRadius*2.9f/2.0f;
+// bgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_arc_scale_bg);
+// bgBitmap = resizeImage(bgBitmap, (int)bgWidtht, (int) bgHeight);
+//
+// }
+
+ //鍒濆鍖朥I锛屽彲鏍规嵁涓氬姟闇�姹傝缃粯璁ゅ�笺��
+ private void initView(Context context) {
+
+ }
+
+ private float getEndAngle(float mAngle){
+ return 90 - mAngle < 0 ? (90-mAngle +360) : (90-mAngle);
+ }
+
+ /**
+ * 鍒濆鍖栭粯璁ゅ弬鏁�
+ */
+ private void initData() {
+
+ mProgress = 16;
+ mPercent = 0;
+ mMaxValue = 35;
+ mMinValue = 16;
+ mStartColor = 0xff495AF4;
+ mEndColor = 0xffAE50A8;
+ mNowColor = 0xff495AF4;
+ changeOpenAngle();
+ mScaleLineHeight = dp2px(15);
+ mScaleLineHeightOut = mScaleLineHeight/4;
+ mScaleLineWidth = dp2px(2);
+ bgRoundWidth = dp2px(8);
+ bgRoundPadding = dp2px(16);
+ mRoundX = 0;
+ mLinePadding = dp2px(10);
+ mTextSizeBig = getTextSizeDip(30);
+ offlineRadius = dp2px(5);
+// mTextSizeSmall = getTextSizeDip(20);
+// mTextSizeSmall = mTextSizeBig - 20;
+ }
+
+ private void changeOpenAngle(){
+ sweepAngle = CIRCLE_ANGLE - mOpenAngle;
+ startAngle = 90 + mOpenAngle/2;
+ endAngle = getEndAngle(mOpenAngle/2);
+ }
+
+ /**
+ * 澶у皬鏀瑰彉锛屽埛鏂版墍鏈夐噸瑕佺殑鍙傛暟鍊�
+ */
+ private void oncurtainSizeChange() {
+ mRoundX = mScaleLineHeight + bgRoundPadding + mScaleLineHeightOut;
+ clipRadius = (int)(mArcRadius - mRoundX );
+ int ll = (int) ( sweepAngle * Math.PI * mArcRadius) / 180;
+ mLineCount = (int)(ll/(mScaleLineWidth + mLinePadding));
+ mAngle = sweepAngle / mLineCount;
+ mWaveHeight = clipRadius / 3 ;
+ mTargetCount = (int)(mPercent * mLineCount);
+// initImageView();
+ }
+
+ /**
+ * 鍒濆鍖栫敾绗�
+ */
+ private void initPaint() {
+ // 鍒濆鍖栫敾绗�
+ linePaint = new Paint();
+ linePaint.setStrokeWidth(mScaleLineWidth);
+ linePaint.setAntiAlias(true);
+ //鑳屾櫙鍦嗙敾绗�
+ mRoundPaint = new Paint();
+ mRoundPaint.setColor(DEFAULT_ROUND_BORDER_COLOR);
+ mRoundPaint.setStrokeWidth(bgRoundWidth);
+ mRoundPaint.setAntiAlias(true);
+ mRoundPaint.setStyle(Paint.Style.STROKE);
+ //杩涘害鏂囧瓧鐢荤瑪
+ mTextPaint = new Paint();
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ mTextPaint.setTextSize(mTextSizeBig);
+ //娉㈡氮鐢荤瑪
+ waterPaint = new Paint();
+ waterPaint.setAntiAlias(true);
+ //绂荤嚎鐢荤瑪
+ offlinePaint = new Paint();
+ offlinePaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ offlinePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+// mSeekBarHeight = hs;
+// mSeekBarWidth = ws;
+// mCenterX = mSeekBarWidth/2;
+// mCenterY = mSeekBarHeight/2;
+// // 鍙栧嚭鏈�灏忓��
+// mArcWidth = Math.min(ws, hs);
+// oncurtainSizeChange();
+ }
+
+// private int measureSize(int defaultSize,int measureSpec) {
+// int result = defaultSize;
+// int specMode = MeasureSpec.getMode(measureSpec);
+// int specSize = MeasureSpec.getSize(measureSpec);
+//
+// if (specMode == MeasureSpec.EXACTLY) {
+// result = specSize;
+// } else if (specMode == MeasureSpec.AT_MOST) {
+// result = Math.min(result, specSize);
+// }
+// return result;
+// }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+
+ // 鍙栧嚭鏈�灏忓��
+ mArcWidth = Math.min(safeW, safeH);
+ mCenterX = mArcWidth/2;
+ mCenterY = mArcWidth/2;
+ mArcRadius = mArcWidth / 2;
+ firstWaterLine = new float[mArcWidth];
+ secondWaterLine = new float[mArcWidth];
+ oncurtainSizeChange();
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTARCSCALE"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ // 鐢诲埢搴︾嚎
+ drawLine(canvas);
+ // 鐢绘按娉�
+ drawWaterView(canvas);
+ // 鐢诲埢搴︾嚎鍐呯殑鍐呭
+ drawText(canvas);
+ //缁樺埗绂荤嚎閬尅灞�
+ if(isOffline){
+ RectF rectF2 = new RectF(0, 0, mSeekBarWidth, mSeekBarHeight);
+ canvas.drawRoundRect(rectF2, offlineRadius, offlineRadius, offlinePaint);
+ }
+ }
+
+ /**
+ * 鐢绘按鐞冪殑鍔熻兘
+ *
+ * @param canvas
+ */
+ private void drawWaterView(Canvas canvas) {
+ // y = Asin(wx+b)+h 锛寃褰卞搷鍛ㄦ湡锛孉褰卞搷鎸箙锛宧褰卞搷y浣嶇疆锛宐涓哄垵鐩革紱
+ // 灏嗗懆鏈熷畾涓簐iew鎬诲搴�
+ float mCycleFactorW = (float) (2 * Math.PI / mArcWidth);
+
+ // 寰楀埌绗竴鏉℃尝鐨剏鍊�
+ for (int i = 0; i < mArcWidth; i++) {
+ firstWaterLine[i] = (float) (40 * Math
+ .sin(mCycleFactorW * i + mWaveMove) - mWaveHeight);
+ }
+// // 寰楀埌绗竴鏉℃尝鐨剏鍊�
+// for (int i = 0; i < mArcWidth; i++) {
+// secondWaterLine[i] = (float) (45 * Math.sin(mCycleFactorW * i
+// + mWaveMove + 10) - mWaveHeight);
+// }
+
+ // 鐢诲渾褰㈣儗鏅�
+ RectF roundRectF = new RectF(mRoundX, mRoundX, mArcWidth - mRoundX, mArcWidth - mRoundX);
+ canvas.save();
+
+ // 瑁佸壀鎴愬渾褰㈠尯鍩�
+ Path path = new Path();
+ waterPaint.setColor(mNowColor);
+ path.reset();
+ canvas.clipPath(path);
+
+
+ path.addArc(roundRectF, 0, CIRCLE_ANGLE);
+// path.addCircle(mArcWidth / 2, mArcWidth / 2, clipRadius - bgStrokeWidth/2, Path.Direction.CCW);
+ canvas.clipPath(path, android.graphics.Region.Op.REPLACE);
+ // 灏嗗潗鏍囩郴绉诲埌搴曢儴
+ canvas.translate(0, mArcRadius + clipRadius);
+
+ resetmArcProgressBarColor();
+ for (int i = 0; i < mArcWidth; i++) {
+ canvas.drawLine(i, firstWaterLine[i], i, mArcWidth, waterPaint);
+ }
+// for (int i = 0; i < mArcWidth; i++) {
+// canvas.drawLine(i, secondWaterLine[i], i, mArcWidth, waterPaint);
+// }
+
+ canvas.restore();
+// canvas.drawBitmap(bgBitmap, mSeekBarWidth/2- bgWidtht/2 , mSeekBarHeight- mRoundX-bgHeight, new Paint());
+ //缁樺埗鑳屾櫙鍦�
+ canvas.drawArc(roundRectF, 0, CIRCLE_ANGLE, false, mRoundPaint);
+
+ }
+
+ /**
+ * 閲嶇疆 mArcProgressBarColors 棰滆壊
+ */
+ private void resetmArcProgressBarColor() {
+// LinearGradient gradient = new LinearGradient(mCenterX-100, mSeekBarHeight-mWaveHeight, mCenterX+100, mWaveHeight, mStartColor, mEndColor, Shader.TileMode.MIRROR);
+ LinearGradient gradient = new LinearGradient(mRoundX+30, mSeekBarHeight-mRoundX, mArcWidth - mRoundX-30, mSeekBarHeight - mWaveHeight, mStartColor, mEndColor, Shader.TileMode.MIRROR);
+
+ waterPaint.setShader(gradient);
+ }
+
+ /**
+ * 瀹炵幇鐢诲埢搴︾嚎鍐呯殑鍐呭
+ *
+ * @param canvas
+ */
+ private void drawText(Canvas canvas) {
+ if (isProgressTextShow) {
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, mCenterY, mTextPaint);
+ }
+ }
+
+
+
+
+ /**
+ * 瀹炵幇鐢诲埢搴︾嚎鐨勫姛鑳�
+ *
+ * @param canvas
+ */
+ private void drawLine(final Canvas canvas) {
+ // 淇濆瓨涔嬪墠鐨勭敾甯冪姸鎬�
+ canvas.save();
+ // 绉诲姩鐢诲竷锛屽疄闄呬笂鏄敼鍙樺潗鏍囩郴鐨勪綅缃�
+ canvas.translate(mArcRadius, mArcRadius);
+ // 鏃嬭浆鍧愭爣绯�,闇�瑕佺‘瀹氭棆杞搴�
+ canvas.rotate(mOpenAngle/2);
+// move = targetAngle/sweepAngle*mArcWidth;
+
+
+ for (int i = 0; i <= mLineCount; i++) {
+ if (i <= mTargetCount && mTargetCount != 0) {// 濡傛灉绱鐢昏繃鐨勮搴︼紝灏忎簬褰撳墠鏈夋晥鍒诲害
+ float mColorPercent = (float)i / mLineCount;
+ // 璁$畻绱鍒掕繃鐨勫埢搴︾櫨鍒嗘瘮锛堢敾杩囩殑鍒诲害姣斾笂涓叡杩涜繃鐨勫埢搴︼級
+ mNowColor = getCurrentColor(mColorPercent, mStartColor, mEndColor);
+ linePaint.setColor(mNowColor);
+// canvas.drawLine(0, mArcRadius, 0, mArcRadius - mScaleLineHeight, linePaint);
+ if(mTargetCount == i){
+ canvas.drawLine(0, mArcRadius, 0, mArcRadius - mScaleLineHeight - mScaleLineHeightOut, linePaint);
+ }else {
+ canvas.drawLine(0, mArcRadius - mScaleLineHeightOut, 0, mArcRadius - mScaleLineHeight - mScaleLineHeightOut, linePaint);
+ }
+
+ } else {
+ linePaint.setColor(DEFAULT_ROUND_BORDER_COLOR);
+ canvas.drawLine(0, mArcRadius - mScaleLineHeightOut, 0, mArcRadius - mScaleLineHeight - mScaleLineHeightOut, linePaint);
+ }
+ canvas.rotate(mAngle);
+ }
+ // 鎭㈠鐢诲竷鐘舵�併��
+ canvas.restore();
+ }
+
+
+
+
+ /**
+ * 鏍规嵁fraction鍊兼潵璁$畻褰撳墠鐨勯鑹层�� fraction鍊艰寖鍥� 0f-1f
+ */
+ private int getCurrentColor(float fraction, int startColor, int endColor) {
+ int redCurrent;
+ int blueCurrent;
+ int greenCurrent;
+ int alphaCurrent;
+
+ int redStart = Color.red(startColor);
+ int blueStart = Color.blue(startColor);
+ int greenStart = Color.green(startColor);
+ int alphaStart = Color.alpha(startColor);
+
+ int redEnd = Color.red(endColor);
+ int blueEnd = Color.blue(endColor);
+ int greenEnd = Color.green(endColor);
+ int alphaEnd = Color.alpha(endColor);
+
+ int redDifference = redEnd - redStart;
+ int blueDifference = blueEnd - blueStart;
+ int greenDifference = greenEnd - greenStart;
+ int alphaDifference = alphaEnd - alphaStart;
+
+ redCurrent = (int) (redStart + fraction * redDifference);
+ blueCurrent = (int) (blueStart + fraction * blueDifference);
+ greenCurrent = (int) (greenStart + fraction * greenDifference);
+ alphaCurrent = (int) (alphaStart + fraction * alphaDifference);
+
+ return Color.argb(alphaCurrent, redCurrent, greenCurrent, blueCurrent);
+ }
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if(!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+
+ if (!mCanDrag) {
+ break;
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if(!moved){
+ if (isInArcProgress(event.getX(),event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if(mCanDrag) {
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if(isInArcProgress(event.getX(),event.getY())){
+ mCanDrag = true;
+ }else {
+ mCanDrag = false;
+ }
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+ float currentAngle = getCurrentAngle(event.getX(), event.getY());
+
+ //鍒ゆ柇鏄惁鍦ㄧ鍚堣搴�
+ if((currentAngle < startAngle-10) && (currentAngle > endAngle + 10)){
+ return;
+ }
+
+ float diffAngle = currentAngle - startAngle ;
+ if (diffAngle < 0) {
+ if(currentAngle < 90) {
+ diffAngle = (diffAngle + CIRCLE_ANGLE) % CIRCLE_ANGLE;
+ }else {
+ diffAngle = 0;
+ }
+ }
+ float progress = diffAngle / sweepAngle;
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+
+ mPercent = progress;
+ mProgress = (int) (mPercent * (mMaxValue - mMinValue)) + mMinValue;
+ mTargetCount = (int)(mPercent * mLineCount);
+
+ }
+
+ //鍒ゆ柇鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+ private boolean isInArcProgress(float px ,float py) {
+ if(px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight){
+ return false;
+ }else {
+ if(isInOutArc(px, py)){
+ return true;
+ }else {
+ return false;
+ }
+ }
+ }
+
+ //鏄惁鍦ㄥ鍦�
+ private boolean isInOutArc(float px ,float py) {
+ if(getDistanceWithCenter(px, py) < (mArcRadius - mRoundX) ){
+ return false;
+ }else {
+ return true;
+ }
+ }
+
+ // 璁$畻鍧愭爣鍦嗙偣鐨勮窛绂�
+ private double getDistanceWithCenter(float px, float py) {
+ return Math.sqrt((px - mCenterX) * (px - mCenterX) + (py - mCenterY) * (py - mCenterY));
+ }
+
+ // 璁$畻鎸囧畾浣嶇疆涓庡唴瀹瑰尯鍩熶腑蹇冪偣鐨勫す瑙�
+ private float getCurrentAngle(float px, float py) {
+ float angle = (float) ((Math.atan2(py - mCenterY, px - mCenterX)) * 180 / 3.14f);
+ if (angle < 0) {
+ angle += 360;
+ }
+ return angle;
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+ /**
+ * mOnProgressChangeListener
+ */
+ private HDLArcScaleSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLArcScaleSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLArcScaleSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLArcScaleSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLArcScaleSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize){
+ mTextSizeBig = getTextSizeDip(textSize);
+ mTextPaint.setTextSize(mTextSizeBig);
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor){
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ /**
+ * 鎵嬪姩璁剧疆鍒诲害鐩樼殑鍊�
+ */
+ public void setProgress(int progress) {
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+ mProgress = progress;
+ mPercent = (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+
+ mTargetCount = (int)(mPercent * mLineCount);
+
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+ }
+
+ public void setOpenAngle(float openAngle) {
+ mOpenAngle = openAngle;
+ changeOpenAngle();
+ oncurtainSizeChange();
+ }
+
+ public void setScaleLineHeight(float scaleLineHeight) {
+ mScaleLineHeight = scaleLineHeight;
+ mScaleLineHeightOut = mScaleLineHeight/4;
+ oncurtainSizeChange();
+ }
+
+ public void setScaleLineWidth(float scaleLineWidth) {
+ mScaleLineWidth = scaleLineWidth;
+ linePaint.setStrokeWidth(mScaleLineWidth);
+ oncurtainSizeChange();
+
+ }
+
+ public void setBgRoundWidth(float bgRoundWidth) {
+ this.bgRoundWidth = bgRoundWidth;
+ mRoundPaint.setStrokeWidth(bgRoundWidth);
+ }
+
+ public void setBgRoundPadding(float bgRoundPadding) {
+ this.bgRoundPadding = bgRoundPadding;
+ oncurtainSizeChange();
+ }
+
+ public void setLinePadding(float linePadding) {
+ this.mLinePadding = linePadding;
+ oncurtainSizeChange();
+ }
+
+
+ public void setStartColor(int startColor) {
+ this.mStartColor = startColor;
+ }
+
+ public void setEndColor(int endColor) {
+ this.mEndColor = endColor;
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+ /**
+ * 璁剧疆绂荤嚎鐘舵��
+ * @param offline
+ */
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ isClickable = !isOffline;
+ postInvalidate();
+ }
+
+
+ public void setInitConfig(){
+
+
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcSeekBar.java
new file mode 100644
index 0000000..5c3a132
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLArcSeekBar.java
@@ -0,0 +1,1006 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.SweepGradient;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+
+public class HDLArcSeekBar extends View {
+ private static final int DEFAULT_EDGE_LENGTH = 260; // 榛樿瀹介珮
+
+ private static final float CIRCLE_ANGLE = 360; // 鍦嗗懆瑙�
+ private static final int DEFAULT_ARC_WIDTH = 15; // 榛樿瀹藉害 dp
+ private static final float DEFAULT_OPEN_ANGLE = 30; // 寮�鍙h搴�
+ private static final float DEFAULT_ROTATE_ANGLE = 90; // 鏃嬭浆瑙掑害
+ private static final int DEFAULT_BORDER_WIDTH = 0; // 榛樿鎻忚竟瀹藉害
+ private static final int DEFAULT_BORDER_COLOR = 0xffffffff; // 榛樿鎻忚竟棰滆壊
+
+ private static final int DEFAULT_THUMB_COLOR = 0xffffffff; // 鎷栧姩鎸夐挳棰滆壊
+ private static final int DEFAULT_THUMB_WIDTH = 5; // 鎷栧姩鎸夐挳鎻忚竟瀹藉害 dp
+ private static final int DEFAULT_THUMB_RADIUS = 7; // 鎷栧姩鎸夐挳鍗婂緞 dp
+ private static final int DEFAULT_THUMB_SHADOW_RADIUS = 0; // 鎷栧姩鎸夐挳闃村奖鍗婂緞 dp
+ private static final int DEFAULT_THUMB_SHADOW_COLOR = 0xFF000000; // 鎷栧姩鎸夐挳闃村奖棰滆壊
+
+ private static final int DEFAULT_SHADOW_RADIUS = 0; // 榛樿闃村奖鍗婂緞 dp
+ public static final int THUMB_MODE_STROKE = 0; // 鎷栧姩鎸夐挳妯″紡 - 鎻忚竟
+ public static final int THUMB_MODE_FILL = 1; // 鎷栧姩鎸夐挳妯″紡 - 濉厖
+ public static final int THUMB_MODE_FILL_STROKE = 2; // 鎷栧姩鎸夐挳妯″紡 - 濉厖+鎻忚竟
+ private static final int DEFAULT_MAX_VALUE = 100; // 榛樿鏈�澶ф暟鍊�
+ private static final int DEFAULT_MIN_VALUE = 0; // 榛樿鏈�灏忔暟鍊�
+ private static final String KEY_PROGRESS_PRESENT = "PRESENT"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+
+ // 鍙厤缃暟鎹�
+ private int[] mArcColors; // Seek 棰滆壊
+ private float mArcWidth; // Seek 瀹藉害
+ private float mOpenAngle; // 寮�鍙g殑瑙掑害澶у皬 0 - 360
+ private float mRotateAngle; // 鏃嬭浆瑙掑害
+ private int mBorderWidth; // 鎻忚竟瀹藉害
+ private int mBorderColor; // 鎻忚竟棰滆壊
+ private int mThumbColor; // 鎷栧姩鎸夐挳棰滆壊
+ private float mThumbWidth; // 鎷栧姩鎸夐挳瀹藉害
+ private float mThumbRadius; // 鎷栧姩鎸夐挳鍗婂緞
+ private float mThumbShadowRadius;// 鎷栧姩鎸夐挳闃村奖鍗婂緞
+ private int mThumbShadowColor;// 鎷栧姩鎸夐挳闃村奖棰滆壊
+ private int mThumbMode; // 鎷栧姩鎸夐挳妯″紡
+
+ private int mShadowRadius; // 闃村奖鍗婂緞
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+
+ private float mThumbX; // 鎷栧姩鎸夐挳 涓績鐐� X
+ private float mThumbY; // 鎷栧姩鎸夐挳 涓績鐐� Y
+
+ private Path mSeekPath;
+ private Path mBorderPath;
+ private Paint mArcPaint;
+ private Paint mThumbPaint;
+ private Paint mBorderPaint;
+ private Paint mShadowPaint;
+
+ private float[] mTempPos;
+ private float[] mTempTan;
+ private PathMeasure mSeekPathMeasure;
+
+ private float mProgressPresent = 0; // 褰撳墠杩涘害鐧惧垎姣�
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ private boolean mAllowTouchSkip = false; // 鏄惁鍏佽瓒婅繃杈圭晫
+// private GestureDetector mDetector;
+ private Matrix mInvertMatrix; // 閫嗗悜 Matrix, 鐢ㄤ簬璁$畻瑙︽懜鍧愭爣鍜岀粯鍒跺潗鏍囩殑杞崲
+ private Region mArcRegion; // ArcPath鐨勫疄闄呭尯鍩熷ぇ灏�,鐢ㄤ簬鍒ゅ畾鍗曞嚮浜嬩欢
+
+ //***********************鏂板***********************************
+ private static final int DEFAULT_THUMB_DISTANCE_MULTIPLE = 5; //鐐瑰嚮鐨勫潗鏍囩涓巑Thumb鍦嗗績鍧愭爣璺濈锛屽皬浜�5*鍗婂緞锛屽垯鍙互鎷栧姩
+ private static final int DEFAULT_ARC_PROGRESS_BAR_COLOR = 0xFFFFFFFF; // 杩涘害鏉¢鑹�
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+// private static final int DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC = 70;
+ private static final int DEFAULT_PADDING = 80; //鍦嗗姬鑷甫PADDING鍊硷紝涓轰簡鏄剧ず杩涘害test鏂囧瓧
+ private Point mTextPoint; //鏃嬭浆90搴﹀悗鐨勫潗鏍�
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+ private RectF content; //鏄剧ず鍐呭鍖哄煙
+ private float mSweepAngle = 0; //涓庡紑濮嬭搴︾殑澶硅
+ private int mArcProgressBarColor; //褰撳墠杩涘害鍦嗗姬棰滆壊
+ private Paint mArcProgressBarPaint; //褰撳墠杩涘害鍦嗗姬鐢荤瑪
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private double mArcProgressBarRadius; //鍦嗗姬鐨勫崐寰�
+ private boolean isClickable = true;
+ private int mTextDefaultDistance = 70; // 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈 DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC
+ private int[] mArcProgressBarColors; // 褰撳墠杩涘害鍦嗗姬娓愬彉棰滆壊鏁扮粍
+// private int mTextColor; // 鎷栧姩鎸夐挳棰滆壊
+ //***********************鏂板***********************************
+
+
+ public HDLArcSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLArcSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLArcSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+ initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ //--- 鍒濆鍖� -----------------------------------------------------------------------------------
+
+ // 鍒濆鍖栧悇绉嶅睘鎬�
+ private void initAttrs(Context context, AttributeSet attrs) {
+ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HDLArcSeekBar);
+ mArcColors = getArcColors(context, ta);
+ mArcWidth = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_width, dp2px(DEFAULT_ARC_WIDTH));
+ mOpenAngle = ta.getFloat(R.styleable.HDLArcSeekBar_arc_open_angle, DEFAULT_OPEN_ANGLE);
+ mRotateAngle = ta.getFloat(R.styleable.HDLArcSeekBar_arc_rotate_angle, DEFAULT_ROTATE_ANGLE);
+ mMaxValue = ta.getInt(R.styleable.HDLArcSeekBar_arc_max, DEFAULT_MAX_VALUE);
+ mMinValue = ta.getInt(R.styleable.HDLArcSeekBar_arc_min, DEFAULT_MIN_VALUE);
+ // 濡傛灉鐢ㄦ埛璁剧疆鐨勬渶澶у�煎拰鏈�灏忓�间笉鍚堢悊锛屽垯鐩存帴鎸夌収榛樿杩涜澶勭悊
+ if (mMaxValue <= mMinValue) {
+ mMaxValue = DEFAULT_MAX_VALUE;
+ mMinValue = DEFAULT_MIN_VALUE;
+ }
+ int progress = ta.getInt(R.styleable.HDLArcSeekBar_arc_progress, mMinValue);
+ setProgress(progress);
+ mBorderWidth = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_border_width, dp2px(DEFAULT_BORDER_WIDTH));
+ mBorderColor = ta.getColor(R.styleable.HDLArcSeekBar_arc_border_color, DEFAULT_BORDER_COLOR);
+
+ mThumbColor = ta.getColor(R.styleable.HDLArcSeekBar_arc_thumb_color, DEFAULT_THUMB_COLOR);
+ mThumbRadius = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_thumb_radius, dp2px(DEFAULT_THUMB_RADIUS));
+ mThumbShadowRadius = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_thumb_shadow_radius, dp2px(DEFAULT_THUMB_SHADOW_RADIUS));
+ mThumbShadowColor = ta.getColor(R.styleable.HDLArcSeekBar_arc_thumb_shadow_color, DEFAULT_THUMB_SHADOW_COLOR);
+ mThumbWidth = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_thumb_width, dp2px(DEFAULT_THUMB_WIDTH));
+ mThumbMode = ta.getInt(R.styleable.HDLArcSeekBar_hdl_arc_thumb_mode, THUMB_MODE_STROKE);
+
+ mShadowRadius = ta.getDimensionPixelSize(R.styleable.HDLArcSeekBar_arc_shadow_radius, dp2px(DEFAULT_SHADOW_RADIUS));
+ mArcProgressBarColor = ta.getColor(R.styleable.HDLArcSeekBar_arc_progress_bar_color, DEFAULT_ARC_PROGRESS_BAR_COLOR);
+
+ mArcProgressBarColors = new int[]{mArcProgressBarColor,mArcProgressBarColor};
+
+ ta.recycle();
+ }
+
+ // 鑾峰彇 Arc 棰滆壊鏁扮粍
+ private int[] getArcColors(Context context, TypedArray ta) {
+ int[] ret;
+ int resId = ta.getResourceId(R.styleable.HDLArcSeekBar_arc_colors, 0);
+ if (0 == resId) {
+ resId = R.array.arc_colors_default;
+ }
+ ret = getColorsByArrayResId(context, resId);
+ return ret;
+ }
+
+ // 鏍规嵁 resId 鑾峰彇棰滆壊鏁扮粍
+ private int[] getColorsByArrayResId(Context context, int resId) {
+ int[] ret;
+ TypedArray colorArray = context.getResources().obtainTypedArray(resId);
+ ret = new int[colorArray.length()];
+ for (int i = 0; i < colorArray.length(); i++) {
+ ret[i] = colorArray.getColor(i, 0);
+ }
+ return ret;
+ }
+
+ // 鍒濆鍖栨暟鎹�
+ private void initData() {
+ mSeekPath = new Path();
+ mBorderPath = new Path();
+ mSeekPathMeasure = new PathMeasure();
+ mTempPos = new float[2];
+ mTempTan = new float[2];
+
+// mDetector = new GestureDetector(getContext(), new OnClickListener());
+ mInvertMatrix = new Matrix();
+ mArcRegion = new Region();
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ }
+
+ // 鍒濆鍖栫敾绗�
+ private void initPaint() {
+ initArcPaint();
+ initThumbPaint();
+ initTextPanit();
+ initProgressBarPaint();
+ initBorderPaint();
+ initShadowPaint();
+ }
+
+
+ // 鍒濆鍖栧渾寮х敾绗�
+ private void initArcPaint() {
+ mArcPaint = new Paint();
+ mArcPaint.setAntiAlias(true);
+ mArcPaint.setStrokeWidth(mArcWidth);
+ mArcPaint.setStyle(Paint.Style.STROKE);
+ mArcPaint.setStrokeCap(Paint.Cap.ROUND);
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽敾绗�
+ private void initThumbPaint() {
+ mThumbPaint = new Paint();
+ mThumbPaint.setAntiAlias(true);
+ mThumbPaint.setColor(mThumbColor);
+ mThumbPaint.setStrokeWidth(mThumbWidth);
+ mThumbPaint.setStrokeCap(Paint.Cap.ROUND);
+ if (mThumbMode == THUMB_MODE_FILL) {
+ mThumbPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ } else if (mThumbMode == THUMB_MODE_FILL_STROKE) {
+ mThumbPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ } else {
+ mThumbPaint.setStyle(Paint.Style.STROKE);
+ }
+ mThumbPaint.setTextSize(56);
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+ // 鍒濆鍖栬繘搴﹀渾寮х敾绗�
+ private void initProgressBarPaint() {
+ mArcProgressBarPaint = new Paint(); //鍒濆鍖栬繘搴﹀渾寮х敾绗�
+ mArcProgressBarPaint.setAntiAlias(true);
+ mArcProgressBarPaint.setStyle(Paint.Style.STROKE);
+ mArcProgressBarPaint.setStrokeCap(Paint.Cap.ROUND);
+ mArcProgressBarPaint.setStrokeWidth(mArcWidth - 1);
+// mArcProgressBarPaint.setColor(mArcProgressBarColor);
+
+
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(12));
+ mTextPaint.setColor(mThumbColor);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽敾绗�
+ private void initBorderPaint() {
+ mBorderPaint = new Paint();
+ mBorderPaint.setAntiAlias(true);
+ mBorderPaint.setColor(mBorderColor);
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+ mBorderPaint.setStyle(Paint.Style.STROKE);
+ }
+
+ // 鍒濆鍖栭槾褰辩敾绗�
+ private void initShadowPaint() {
+ mShadowPaint = new Paint();
+ mShadowPaint.setAntiAlias(true);
+ mShadowPaint.setStrokeWidth(mBorderWidth);
+ mShadowPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgressPresent);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgressPresent = bundle.getFloat(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, getProgress(), false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ float edgeLength, startX, startY;
+ float fix = mArcWidth / 2 + mBorderWidth + mShadowRadius * 2; // 淇璺濈,鐢荤瑪瀹藉害鐨勪慨姝�
+ if (safeW < safeH) {
+ // 瀹藉害灏忎簬楂樺害,浠ュ搴︿负鍑�
+ edgeLength = safeW - fix;
+ startX = getPaddingLeft();
+ startY = (safeH - safeW) / 2.0f + getPaddingTop();
+ } else {
+ // 瀹藉害澶т簬楂樺害,浠ラ珮搴︿负鍑�
+ edgeLength = safeH - fix;
+ startX = (safeW - safeH) / 2.0f + getPaddingLeft();
+ startY = getPaddingTop();
+ }
+
+ // 寰楀埌鏄剧ず鍖哄煙鍜屼腑蹇冪殑
+ content = new RectF(startX + fix + DEFAULT_PADDING, startY + fix + DEFAULT_PADDING, startX + edgeLength - DEFAULT_PADDING, startY + edgeLength - DEFAULT_PADDING);
+ mCenterX = content.centerX();
+ mCenterY = content.centerY();
+
+ // 寰楀埌璺緞
+ mSeekPath.reset();
+ mSeekPath.addArc(content, mOpenAngle / 2, CIRCLE_ANGLE - mOpenAngle);
+ mSeekPathMeasure.setPath(mSeekPath, false);
+ computeThumbPos(mProgressPresent);
+ mArcProgressBarRadius = getDistanceWithCenter(mThumbX, mThumbY);//璁$畻鍑哄渾寮х殑鍗婂緞
+ resetShaderColor();
+ mInvertMatrix.reset();
+ mInvertMatrix.preRotate(-mRotateAngle, mCenterX, mCenterY);
+
+ mArcPaint.getFillPath(mSeekPath, mBorderPath);
+ mBorderPath.close();
+ mArcRegion.setPath(mBorderPath, new Region(0, 0, w, h));
+ }
+
+
+
+ /**
+ * 閲嶇疆 mArcProgressBarColors 棰滆壊
+ * 2019-8-14
+ */
+ private void resetmArcProgressBarColor() {
+// // 璁$畻娓愬彉鏁扮粍
+// float startPos = (mOpenAngle / 2) / CIRCLE_ANGLE;
+// float stopPos = (CIRCLE_ANGLE - (mOpenAngle / 2)) / CIRCLE_ANGLE;
+// int len = mArcProgressBarColors.length - 1;
+// float distance = (stopPos - startPos) / len;
+// float pos[] = new float[mArcProgressBarColors.length];
+// for (int i = 0; i < mArcProgressBarColors.length; i++) {
+// pos[i] = startPos + (distance * i);
+// }
+// SweepGradient gradient = new SweepGradient(mCenterX, mCenterY, mArcProgressBarColors, pos);
+
+ SweepGradient gradient = new SweepGradient(mCenterX, mCenterY, mArcProgressBarColors, null);
+
+
+ mArcProgressBarPaint.setShader(gradient);
+ }
+
+ // 閲嶇疆 shader 棰滆壊
+ private void resetShaderColor() {
+ // 璁$畻娓愬彉鏁扮粍
+ float startPos = (mOpenAngle / 2) / CIRCLE_ANGLE;
+ float stopPos = (CIRCLE_ANGLE - (mOpenAngle / 2)) / CIRCLE_ANGLE;
+ int len = mArcColors.length - 1;
+ float distance = (stopPos - startPos) / len;
+ float pos[] = new float[mArcColors.length];
+ for (int i = 0; i < mArcColors.length; i++) {
+ pos[i] = startPos + (distance * i);
+ }
+ SweepGradient gradient = new SweepGradient(mCenterX, mCenterY, mArcColors, pos);
+ mArcPaint.setShader(gradient);
+ }
+
+ // 鍏蜂綋缁樺埗
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.save();
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mTextPoint.x, mTextPoint.y, mTextPaint);
+ canvas.rotate(mRotateAngle, mCenterX, mCenterY);
+// mShadowPaint.setShadowLayer(mShadowRadius * 2, 0, 0, getColor());
+ canvas.drawPath(mBorderPath, mShadowPaint);
+ canvas.drawPath(mSeekPath, mArcPaint);
+ //褰撳墠杩涘害
+ resetmArcProgressBarColor();//娓愬彉棰滆壊
+ canvas.drawArc(content, mOpenAngle / 2, mSweepAngle, false, mArcProgressBarPaint);
+ if (mBorderWidth > 0) {
+ canvas.drawPath(mBorderPath, mBorderPaint);
+ }
+ if (mThumbShadowRadius > 0) {
+ mThumbPaint.setShadowLayer(mThumbShadowRadius, 0, 0, mThumbShadowColor);
+ canvas.drawCircle(mThumbX, mThumbY, mThumbRadius, mThumbPaint);
+ mThumbPaint.clearShadowLayer();
+ }
+ canvas.drawCircle(mThumbX, mThumbY, mThumbRadius, mThumbPaint);
+ canvas.restore();
+ }
+
+ private boolean moved = false;
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if(!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ float tempProgressPresent = getCurrentProgress(event.getX(), event.getY());
+ if (!mAllowTouchSkip) {
+ // 涓嶅厑璁哥獊鍙�
+ if (Math.abs(tempProgressPresent - mProgressPresent) > 0.5f) {
+ break;
+ }
+ }
+ // 鍏佽绐佸彉 鎴栬�呴潪绐佸彉
+ mProgressPresent = tempProgressPresent;
+ computeThumbPos(mProgressPresent);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && getProgress() != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, getProgress(), true);
+ lastProgress = getProgress();
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if(!moved){
+ if (isInArcProgress(event.getX(), event.getY())) {
+ // 鐐瑰嚮鍏佽绐佸彉
+ mProgressPresent = getCurrentProgress(event.getX(), event.getY());
+ computeThumbPos(mProgressPresent);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+
+ break;
+ }
+// mDetector.onTouchEvent(event);
+ invalidate();
+ return true;
+ }
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ float[] pos = {event.getX(), event.getY()};
+ mInvertMatrix.mapPoints(pos);
+ if (getDistance(pos[0], pos[1]) <= mThumbRadius * DEFAULT_THUMB_DISTANCE_MULTIPLE) {
+ mCanDrag = true;
+ } else {
+ mCanDrag = false;
+ }
+ }
+
+
+ private class OnClickListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ // 鍒ゆ柇鏄惁鐐瑰嚮鍦ㄤ簡杩涘害鍖哄煙
+ if (!isInArcProgress(e.getX(), e.getY())) {
+ return false;
+ }
+ // 鐐瑰嚮鍏佽绐佸彉
+ mProgressPresent = getCurrentProgress(e.getX(), e.getY());
+ computeThumbPos(mProgressPresent);
+
+ Log.i("onSingleTapUp","onSingleTapUp");
+// // 浜嬩欢鍥炶皟
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(HDLArcSeekBar.this, getProgress(), true);
+//// mOnProgressChangeListener.onStopTrackingTouch(HDLArcSeekBar.this);
+// }
+ return true;
+ }
+ }
+
+// // 鍒ゆ柇璇ョ偣鏄惁鍦ㄨ繘搴︽潯涓婇潰
+// private boolean isInArcProgress(float px, float py) {
+// float[] pos = {px, py};
+// mInvertMatrix.mapPoints(pos);
+// return mArcRegion.contains((int) pos[0], (int) pos[1]);
+// }
+
+ /**
+ * 鍒ゆ柇璇ョ偣鏄惁鍦ㄨ繘搴︽潯闄勮繎 2019-07-17
+ * 瀵规瘮鍒ゆ柇璇ョ偣鏄惁鍦ㄨ繘搴︽潯涓婇潰锛屽澶у彲鐐瑰嚮鍖哄煙
+ *
+ * @param px 褰撳墠鍧愭爣x
+ * @param py 褰撳墠鍧愭爣y
+ * @return
+ */
+ private boolean isInArcProgress(float px, float py) {
+ float[] pos = {px, py};
+ mInvertMatrix.mapPoints(pos);
+ double mDistance = getDistanceWithCenter(pos[0], pos[1]);
+// Log.i("kkk" ,"KmArcProgressBarRadiusmDistance"+mDistance);
+ if ((mDistance >= (mArcProgressBarRadius * 2 / 3))
+ && (mDistance <= (mArcProgressBarRadius * 4 / 3))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // 鑾峰彇褰撳墠杩涘害鐞嗚杩涘害鏁板��
+ private float getCurrentProgress(float px, float py) {
+ float diffAngle = getDiffAngle(px, py);
+ float progress = diffAngle / (CIRCLE_ANGLE - mOpenAngle);
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ return progress;
+ }
+
+ // 鑾峰緱褰撳墠鐐瑰嚮浣嶇疆鎵�鎴愯搴︿笌寮�濮嬭搴︿箣闂寸殑鏁板�煎樊
+ private float getDiffAngle(float px, float py) {
+ float angle = getAngle(px, py);
+ float diffAngle;
+ diffAngle = angle - mRotateAngle;
+ if (diffAngle < 0) {
+ diffAngle = (diffAngle + CIRCLE_ANGLE) % CIRCLE_ANGLE;
+ }
+ diffAngle = diffAngle - mOpenAngle / 2;
+ return diffAngle;
+ }
+
+ // 璁$畻鎸囧畾浣嶇疆涓庡唴瀹瑰尯鍩熶腑蹇冪偣鐨勫す瑙�
+ private float getAngle(float px, float py) {
+ float angle = (float) ((Math.atan2(py - mCenterY, px - mCenterX)) * 180 / 3.14f);
+ if (angle < 0) {
+ angle += 360;
+ }
+ return angle;
+ }
+
+ // 璁$畻鎸囧畾浣嶇疆涓庝笂娆′綅缃殑璺濈
+ private float getDistance(float px, float py) {
+ return (float) Math.sqrt((px - mThumbX) * (px - mThumbX) + (py - mThumbY) * (py - mThumbY));
+ }
+
+ // 璁$畻鍧愭爣鍦嗙偣鐨勮窛绂�
+ private double getDistanceWithCenter(float px, float py) {
+ return Math.sqrt((px - mCenterX) * (px - mCenterX) + (py - mCenterY) * (py - mCenterY));
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ /**
+ * 鑾峰彇鐩稿悓璺濈涓嬶紝鍦嗗姬瀵瑰簲鐨勭涓夌偣鍧愭爣
+ *
+ * @param mPoint 鍦嗗姬鍧愭爣
+ * 绗笁鐐硅窛绂荤浜岀偣鐨勮窛绂�
+ * DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC 璺濈
+ */
+ private Point calcOutsidePoint(Point mPoint) {
+ double newX = (mPoint.x * (mArcProgressBarRadius + mTextDefaultDistance) - mCenterX * mTextDefaultDistance) / mArcProgressBarRadius;
+ double newY = (mPoint.y * (mArcProgressBarRadius + mTextDefaultDistance) - mCenterY * mTextDefaultDistance) / mArcProgressBarRadius;
+ return new Point((int) newX, (int) newY);
+ }
+
+
+ // 璁$畻鎷栧姩鍧楀簲璇ユ樉绀虹殑浣嶇疆
+ private void computeThumbPos(float present) {
+ if (present < 0) present = 0;
+ if (present > 1) present = 1;
+ if (null == mSeekPathMeasure) return;
+ float distance = mSeekPathMeasure.getLength() * present;
+ mSeekPathMeasure.getPosTan(distance, mTempPos, mTempTan);
+ mThumbX = mTempPos[0];
+ mThumbY = mTempPos[1];
+ Point mmTextPoint = calcNewPoint(new Point((int) mThumbX, (int) mThumbY), new Point((int) mCenterX, (int) mCenterY), mRotateAngle);
+ mSweepAngle = getDiffAngle(mmTextPoint.x, mmTextPoint.y);
+ if (mSweepAngle < 0) mSweepAngle = 0;
+// Log.i("mSweepAngle", "mSweepAngle锛�" + mSweepAngle);
+
+ mTextPoint = calcOutsidePoint(mmTextPoint);
+ }
+
+ //--- 绾挎�у彇鑹� ---------------------------------------------------------------------------------
+
+ /**
+ * 鑾峰彇褰撳墠杩涘害鐨勫叿浣撻鑹�
+ *
+ * @return 褰撳墠杩涘害鍦ㄦ笎鍙樹腑鐨勯鑹�
+ */
+ public int getColor() {
+ return getColor(mProgressPresent);
+ }
+
+ /**
+ * 鑾峰彇鏌愪釜鐧惧垎姣斾綅缃殑棰滆壊
+ *
+ * @param radio 鍙栧�糩0,1]
+ * @return 鏈�缁堥鑹�
+ */
+ private int getColor(float radio) {
+ float diatance = 1.0f / (mArcColors.length - 1);
+ int startColor;
+ int endColor;
+ if (radio >= 1) {
+ return mArcColors[mArcColors.length - 1];
+ }
+ for (int i = 0; i < mArcColors.length; i++) {
+ if (radio <= i * diatance) {
+ if (i == 0) {
+ return mArcColors[0];
+ }
+ startColor = mArcColors[i - 1];
+ endColor = mArcColors[i];
+ float areaRadio = getAreaRadio(radio, diatance * (i - 1), diatance * i);
+ return getColorFrom(startColor, endColor, areaRadio);
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 璁$畻褰撳墠姣斾緥鍦ㄥ瓙鍖洪棿鐨勬瘮渚�
+ *
+ * @param radio 鎬绘瘮渚�
+ * @param startPosition 瀛愬尯闂村紑濮嬩綅缃�
+ * @param endPosition 瀛愬尯闂寸粨鏉熶綅缃�
+ * @return 鑷尯闂存瘮渚媅0, 1]
+ */
+ private float getAreaRadio(float radio, float startPosition, float endPosition) {
+ return (radio - startPosition) / (endPosition - startPosition);
+ }
+
+ /**
+ * 鍙栦袱涓鑹查棿鐨勬笎鍙樺尯闂� 涓殑鏌愪竴鐐圭殑棰滆壊
+ *
+ * @param startColor 寮�濮嬬殑棰滆壊
+ * @param endColor 缁撴潫鐨勯鑹�
+ * @param radio 姣斾緥 [0, 1]
+ * @return 閫変腑鐐圭殑棰滆壊
+ */
+ private int getColorFrom(int startColor, int endColor, float radio) {
+ int redStart = Color.red(startColor);
+ int blueStart = Color.blue(startColor);
+ int greenStart = Color.green(startColor);
+ int redEnd = Color.red(endColor);
+ int blueEnd = Color.blue(endColor);
+ int greenEnd = Color.green(endColor);
+
+ int red = (int) (redStart + ((redEnd - redStart) * radio + 0.5));
+ int greed = (int) (greenStart + ((greenEnd - greenStart) * radio + 0.5));
+ int blue = (int) (blueStart + ((blueEnd - blueStart) * radio + 0.5));
+ return Color.argb(255, red, greed, blue);
+ }
+
+
+ /**
+ * 璁$畻鏌愮偣缁曚腑蹇冪偣鏃嬭浆涓�涓搴﹀悗鐨勫潗鏍�
+ *
+ * @param pCenter 涓績鍧愭爣
+ */
+ private static Point calcNewPoint(Point p, Point pCenter, float angle) {
+ // calc arc
+ float l = (float) ((angle * Math.PI) / 180);
+
+ //sin/cos value
+ float cosv = (float) Math.cos(l);
+ float sinv = (float) Math.sin(l);
+
+ // calc new point
+ float newX = (float) ((p.x - pCenter.x) * cosv - (p.y - pCenter.y) * sinv + pCenter.x);
+ float newY = (float) ((p.x - pCenter.x) * sinv + (p.y - pCenter.y) * cosv + pCenter.y);
+ return new Point((int) newX, (int) newY);
+ }
+
+// /**
+// * 姹傜涓夌偣鍧愭爣
+// *
+// * @param pCenter 涓績鍧愭爣
+// * @param distance 绗笁鐐硅窛绂荤浜岀偣鐨勮窛绂�
+// */
+// private static Point calcOutsidePoint(Point p, Point pCenter, double distance) {
+// //璁$畻2鐐逛箣闂寸殑璺濈
+// double ll = Math.sqrt((p.x - pCenter.x) * (p.x - pCenter.x) + (p.y - pCenter.y) * (p.y - pCenter.y));
+//
+// // calc new point
+// double newX = (p.x * (ll + distance) - pCenter.x * distance) / ll;
+// double newY = (p.y * (ll + distance) - pCenter.y * distance) / ll;
+// return new Point((int) newX, (int) newY);
+// }
+//
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ /**
+ * 璁剧疆杩涘害
+ *
+ * @param progress 杩涘害鍊�
+ */
+ public void setProgress(int progress) {
+ System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+ mProgressPresent = (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + mProgressPresent);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ computeThumbPos(mProgressPresent);
+ postInvalidate();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠杩涘害鏁板��
+ *
+ * @return 褰撳墠杩涘害鏁板��
+ */
+ public int getProgress() {
+ return (int) (mProgressPresent * (mMaxValue - mMinValue)) + mMinValue;
+ }
+
+ /**
+ * 璁剧疆棰滆壊
+ * 3涓鑹� 娓愬彉鏁堟灉
+ * @param colors 棰滆壊
+ */
+ public void setProgressBarColors(int[] colors) {
+ if(colors.length < 2) return;
+ mArcProgressBarColors = colors;
+ resetmArcProgressBarColor();
+ postInvalidate();
+ }
+
+ /**
+ * 璁剧疆棰滆壊 鍗曠棰滆壊
+ * 2019-8-15
+ * @param colors 棰滆壊
+ */
+ public void setProgressBarColor(int colors) {
+ int[] colorsArray = new int[]{colors, colors};
+ mArcProgressBarColors = colorsArray;
+ resetmArcProgressBarColor();
+ postInvalidate();
+ }
+
+ /**
+ * 璁剧疆棰滆壊 2涓鑹蹭互涓�
+ * 2019-8-15
+ * @param colors 棰滆壊
+ */
+ public void setArcColors(int[] colors) {
+ if(colors.length < 2) return;
+ mArcColors = colors;
+ resetShaderColor();
+ postInvalidate();
+ }
+
+ /**
+ * 璁剧疆棰滆壊
+ * 鍗曠棰滆壊
+ * @param colors 棰滆壊
+ */
+ public void setArcColor(int colors) {
+ int[] colorsArray = new int[]{colors, colors, colors};
+ mArcColors = colorsArray;
+ resetShaderColor();
+ postInvalidate();
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+// /**
+// * 璁剧疆杩涘害鏉¢鑹�
+// *
+// * @param arcProgressPainColor 杩涘害鏉¢鑹�
+// */
+// public void setProgressBarColor(int arcProgressPainColor) {
+// mArcProgressBarColor = arcProgressPainColor;
+// mArcProgressBarPaint.setColor(mArcProgressBarColor);
+// }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+// /**
+// * 璁剧疆棰滆壊
+// *
+// * @param colorArrayRes 棰滆壊璧勬簮 R.array.arc_color
+// */
+// public void setArcColors(int colorArrayRes) {
+// setArcColors(getColorsByArrayResId(getContext(), colorArrayRes));
+// }
+
+ /**
+ * 璁剧疆鍦嗗姬瀹藉害锛屽悓鏃跺悓姝ユ嫋鍒版寜閽搴�
+ * @param arcWidth
+ */
+ public void setArcWidthDefaultStyle(int arcWidth) {
+ mArcWidth = dp2px(arcWidth);
+ mThumbRadius = mArcWidth / 3;
+ mThumbWidth = mArcWidth * 2 / 9;
+
+ mArcPaint.setStrokeWidth(mArcWidth);
+ mArcProgressBarPaint.setStrokeWidth(mArcWidth - 1);
+ mThumbPaint.setStrokeWidth(mThumbWidth);
+ }
+
+ /**
+ * 寮�鍙h搴�
+ * @param openAngle
+ */
+ public void setOpenAngle(float openAngle) {
+ mOpenAngle = openAngle;
+ }
+
+ /**
+ *
+ * @param thumbMode
+ */
+ public void setThumbMode(int thumbMode) {
+ mThumbMode = thumbMode;
+ if (mThumbMode == THUMB_MODE_FILL) {
+ mThumbPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ } else if (mThumbMode == THUMB_MODE_FILL_STROKE) {
+ mThumbPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ } else {
+ mThumbMode = THUMB_MODE_STROKE;
+ mThumbPaint.setStyle(Paint.Style.STROKE);
+ }
+ }
+
+ /**
+ *
+ * @param arcWidth
+ */
+ public void setArcWidth(int arcWidth) {
+ mArcWidth = dp2px(arcWidth);
+ mArcPaint.setStrokeWidth(mArcWidth);
+ mArcProgressBarPaint.setStrokeWidth(mArcWidth - 1);
+ }
+
+ /**
+ * 鎷栧姩婊戝潡鍗婂緞
+ * @param thumbRadius
+ */
+ public void setThumbRadius(int thumbRadius) {
+ mThumbRadius = dp2px(thumbRadius);
+ mThumbWidth = mThumbRadius * 2 / 3;
+ mThumbPaint.setStrokeWidth(mThumbWidth);
+// initThumbPaint();
+ }
+
+ /**
+ * 鎷栧姩婊戝潡棰滆壊
+ * @param thumbColor
+ */
+ public void setThumbColor(int thumbColor) {
+ mThumbColor = thumbColor;
+ mThumbPaint.setColor(mThumbColor);
+ }
+
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize){
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor){
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 杩涘害鏂囧瓧涓庡渾寮ц窛绂�
+ * @param textDefaultDistance
+ */
+ public void setTextDefaultDistance(int textDefaultDistance) {
+ mTextDefaultDistance = dp2px(textDefaultDistance);
+ }
+
+// endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLArcSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLArcSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLArcSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLCurtainSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLCurtainSeekBar.java
new file mode 100644
index 0000000..395c1c1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLCurtainSeekBar.java
@@ -0,0 +1,610 @@
+//package com.hdl.widget;
+//
+//import android.annotation.SuppressLint;
+//import android.content.Context;
+//import android.content.res.TypedArray;
+//import android.graphics.Bitmap;
+//import android.graphics.BitmapFactory;
+//import android.graphics.Canvas;
+//import android.graphics.Color;
+//import android.graphics.Matrix;
+//import android.graphics.Paint;
+//import android.graphics.Path;
+//import android.graphics.PorterDuff;
+//import android.graphics.PorterDuffXfermode;
+//import android.graphics.RectF;
+//import android.os.Bundle;
+//import android.os.Parcelable;
+//import android.util.AttributeSet;
+//import android.util.TypedValue;
+//import android.view.MotionEvent;
+//import android.view.View;
+//
+//import com.hdl.widgetxm.R;
+//
+//import static android.view.MotionEvent.ACTION_CANCEL;
+//import static android.view.MotionEvent.ACTION_DOWN;
+//import static android.view.MotionEvent.ACTION_MOVE;
+//import static android.view.MotionEvent.ACTION_UP;
+//
+////import com.hdl.arcseekbar.R;
+////import com.hdl.widget.Utils.HDLUtils;
+//
+///**
+// * Created by JLChen on 2019/11/4
+// */
+//public class HDLCurtainSeekBar extends View {
+//
+// private static final int DEFAULT_WAVE_BORDER_COLOR = 0xFFCBCEE5;
+// private static final int DEFAULT_WAVE_COLOR = 0xFFCBCEE5;
+// private static final int DEFAULT_WAVE_BACKGROUND = 0xFFE5E5ED;
+//
+// private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+//// private Paint mBorderPaint;//杩涘害妗嗙敾绗�
+// private Paint circlePaint;//杩涘害妗嗙敾绗�
+// private Paint curtainPaint;//缁樺埗娉㈡氮鐢荤瑪
+// private Path curtainPath;//缁樺埗娉㈡氮Path
+// private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+// private Bitmap bitmap;//缂撳瓨bitmap
+// private Canvas bitmapCanvas;
+//
+// private float curtainWidth;//娉㈡氮瀹藉害
+// private float curtainHeight;//娉㈡氮楂樺害
+// private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+// private float mPercent;//杩涘害鏉″崰姣�
+// private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+//
+// private int curtainColor;//娉㈡氮棰滆壊
+// private int bgColor;//鑳屾櫙杩涘害棰滆壊
+//
+// private int mPadding = 10;
+//
+// private Boolean isClickable = true;
+// private float mSeekBarWidth;
+// private float mSeekBarHeight;
+//
+// private float mcurtainViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+// private float mcurtainViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+//
+// private int mMaxValue; // 鏈�澶ф暟鍊�
+// private int mMinValue; // 鏈�灏忔暟鍊�
+// private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+// private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+// private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+// private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+// private float mCurtainLeftAndTop,mCurtainRight,mCurtainBottom;
+//
+// private Boolean isProgressTextShow = true;
+//
+// private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+// private float nowY;
+// private float buttonWidth = 10;
+//
+// private int topCompensatePadding = 5; //椤堕儴鍥剧墖琛ュ伩鍊�
+// private Bitmap bgBitmapCurtain,bgBitmapButton;
+//
+//
+// public HDLCurtainSeekBar(Context context) {
+// this(context, null);
+// }
+//
+// public HDLCurtainSeekBar(Context context, AttributeSet attrs) {
+// this(context, attrs, 0);
+// }
+//
+// public HDLCurtainSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+// super(context, attrs, defStyleAttr);
+// setSaveEnabled(true);
+// setLayerType(LAYER_TYPE_SOFTWARE, null);
+// initAttrs(context, attrs);
+// initData();
+// initPaint();
+// }
+//
+// private void initData() {
+// defaultSize = dp2px(100);
+//
+// mPadding = dp2px(30);
+// topCompensatePadding = dp2px(5);
+//
+// buttonWidth = dp2px(10);
+// mPercent = 0.0f;
+// mProgress = 0;
+// mMaxValue = 100;
+// mMinValue = 0;
+//
+// mCornerRadius = dp2px(2);
+// mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+// isProgressTextShow = true;
+// }
+//
+// private void initPaint() {
+// curtainPath = new Path();
+//
+// curtainPaint = new Paint();
+// curtainPaint.setColor(curtainColor);
+// curtainPaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+// curtainPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+//
+// circlePaint = new Paint();
+// circlePaint.setColor(bgColor);
+// circlePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+//
+// initTextPanit();
+// }
+//
+// // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+// private void initTextPanit() {
+// mTextPaint = new Paint();
+// mTextPaint.setAntiAlias(true);
+// mTextPaint.setStrokeWidth(1);
+// mTextPaint.setTextSize(getTextSizeDip(20));
+// mTextPaint.setColor(Color.BLACK);
+// mTextPaint.setTextAlign(Paint.Align.CENTER);
+// }
+//
+//// public HDLcurtainSeekBar(Context context, @Nullable AttributeSet attrs) {
+//// super(context, attrs);
+//// init(context,attrs);
+//// }
+//
+// private void initAttrs(Context context,AttributeSet attrs){
+// TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLCurtainSeekBar);
+// curtainWidth = typedArray.getDimension(R.styleable.HDLCurtainSeekBar_curtain_bar_width, dp2px(80));
+// curtainHeight = typedArray.getDimension(R.styleable.HDLCurtainSeekBar_curtain_bar_height,dp2px(15));
+// curtainColor = typedArray.getColor(R.styleable.HDLCurtainSeekBar_curtain_bar_color, DEFAULT_WAVE_COLOR);
+//// secondWaveColor = typedArray.getColor(R.styleable.HDLWaveSeekBar_second_wave_color,getResources().getColor(R.color.light));
+// bgColor = typedArray.getColor(R.styleable.HDLCurtainSeekBar_curtain_bar_bg_color, DEFAULT_WAVE_BACKGROUND);
+//
+// typedArray.recycle();
+// }
+//
+// private int dp2px(int dp) {
+// return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+// }
+//
+// private float getTextSizeDip(float value) {
+// return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+// }
+//
+//
+// private void oncurtainSizeChange(){
+// mcurtainViewWidth = mSeekBarWidth - mPadding*2;
+// mcurtainViewHeight = mSeekBarHeight - mPadding*2;
+// mCurtainLeftAndTop = mPadding;
+// mCurtainRight = mSeekBarWidth - mPadding;
+// mCurtainBottom = mSeekBarHeight - mPadding;
+// buttonWidth = mcurtainViewWidth/4;
+// updateBitmapImage();
+// }
+//
+// private void updateBitmapImage(){
+//
+// bgBitmapCurtain= BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_bg_top);
+// bgBitmapCurtain = resizeImage(bgBitmapCurtain, (int)mSeekBarWidth-mPadding*2 + topCompensatePadding*2, (int)mPadding+2);
+//
+// bgBitmapButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_open);
+// bgBitmapButton = resizeImage(bgBitmapButton, (int) buttonWidth, (int) buttonWidth);
+//
+// }
+//
+// @Override
+// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+//
+// int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+// int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+// int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+// int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+//
+// if (wm == MeasureSpec.UNSPECIFIED) {
+// wm = MeasureSpec.EXACTLY;
+// ws = dp2px(DEFAULT_EDGE_LENGTH);
+// } else if (wm == MeasureSpec.AT_MOST) {
+// wm = MeasureSpec.EXACTLY;
+// ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+// }
+// if (hm == MeasureSpec.UNSPECIFIED) {
+// hm = MeasureSpec.EXACTLY;
+// hs = dp2px(DEFAULT_EDGE_LENGTH);
+// } else if (hm == MeasureSpec.AT_MOST) {
+// hm = MeasureSpec.EXACTLY;
+// hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+// }
+// setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+//
+// mSeekBarHeight = hs;
+// mSeekBarWidth = ws;
+// mCenterX = mSeekBarWidth/2;
+// mCenterY = mSeekBarHeight/2;
+// oncurtainSizeChange();
+// }
+//
+// private int measureSize(int defaultSize,int measureSpec) {
+// int result = defaultSize;
+// int specMode = MeasureSpec.getMode(measureSpec);
+// int specSize = MeasureSpec.getSize(measureSpec);
+//
+// if (specMode == MeasureSpec.EXACTLY) {
+// result = specSize;
+// } else if (specMode == MeasureSpec.AT_MOST) {
+// result = Math.min(result, specSize);
+// }
+// return result;
+// }
+//
+// @Override
+// protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+// super.onSizeChanged(w, h, oldw, oldh);
+// // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+// int safeW = w - getPaddingLeft() - getPaddingRight();
+// int safeH = h - getPaddingTop() - getPaddingBottom();
+// mSeekBarHeight = safeH;
+// mSeekBarWidth = safeW;
+// mCenterX = mSeekBarWidth/2;
+// mCenterY = mSeekBarHeight/2;
+// oncurtainSizeChange();
+// // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+// }
+//
+//
+//
+// @SuppressLint("DrawAllocation")
+// @Override
+// protected void onDraw(Canvas canvas) {
+// super.onDraw(canvas);
+//
+// canvas.save();
+//
+//// //鐢诲渾瑙掔煩褰�
+//// RectF rectF = new RectF(mBorderLeftAndTop, mBorderLeftAndTop, mSeekBarWidth - mBorderLeftAndTop, mSeekBarHeight-mBorderLeftAndTop);
+//// canvas.drawRoundRect(rectF, mCornerRadius, mCornerRadius, mBorderPaint);
+//
+// bitmap = Bitmap.createBitmap((int)mSeekBarWidth, (int)mSeekBarHeight, Bitmap.Config.ARGB_8888);
+// bitmapCanvas = new Canvas(bitmap);
+//
+// RectF rectF2 = new RectF(mCurtainLeftAndTop, mCurtainLeftAndTop, mCurtainRight, mCurtainBottom);
+// bitmapCanvas.drawRoundRect(rectF2, mCornerRadius, mCornerRadius, circlePaint);
+//
+//// bitmapCanvas.drawCircle(mcurtainViewWidth/2, mcurtainViewWidth/2, mcurtainViewWidth/2, circlePaint);
+// bitmapCanvas.drawPath(getCurtainPath(), curtainPaint);
+//// if(isDrawSecondcurtain){
+//// bitmapCanvas.drawPath(getSecondcurtainPath(),secondcurtainPaint);
+//// }
+//
+//
+// canvas.drawBitmap(bitmap, 0, 0, null);
+//
+// if(isProgressTextShow) {
+// canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, mCenterY, mTextPaint);
+//
+// }
+//
+//
+// canvas.drawBitmap(bgBitmapCurtain, mPadding- topCompensatePadding, 0, new Paint());
+//
+//
+// canvas.drawBitmap(bgBitmapButton, mSeekBarWidth/2 - bgBitmapButton.getWidth()/2.0F, nowY - bgBitmapButton.getHeight()/2.0F, new Paint());
+//
+// canvas.restore();
+//
+// }
+//
+//
+// public Bitmap getBitmap(int resId) {
+// BitmapFactory.Options options = new BitmapFactory.Options();
+// TypedValue value = new TypedValue();
+// getResources().openRawResource(resId, value);
+// options.inTargetDensity = value.density;
+// options.inScaled = false;//涓嶇缉鏀�
+// return BitmapFactory.decodeResource(getResources(), resId, options);
+// }
+//
+// public Bitmap resizeImage(Bitmap bitmap, int width, int height)
+// {
+// int bmpWidth = bitmap.getWidth();
+// int bmpHeight = bitmap.getHeight();
+//
+// float scaleWidth = ((float) width) / bmpWidth;
+// float scaleHeight = ((float) height) / bmpHeight;
+//
+// Matrix matrix = new Matrix();
+// matrix.postScale(scaleWidth, scaleHeight);
+//
+// return Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
+// }
+//
+// //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+//
+// //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+// private static final String KEY_PROGRESS_PRESENT = "PRESENTWAVE"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+// @Override
+// protected Parcelable onSaveInstanceState() {
+// Bundle bundle = new Bundle();
+// bundle.putParcelable("superState", super.onSaveInstanceState());
+// bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+// return bundle;
+// }
+//
+// @Override
+// protected void onRestoreInstanceState(Parcelable state) {
+// if (state instanceof Bundle) {
+// Bundle bundle = (Bundle) state;
+// this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+// state = bundle.getParcelable("superState");
+// }
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+// }
+// super.onRestoreInstanceState(state);
+// }
+//
+// //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+//
+// private Path getCurtainPath(){
+//
+// nowY = (mPercent)*mcurtainViewHeight + mCurtainLeftAndTop;
+//
+// curtainPath.reset();
+//
+// //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+// curtainPath.moveTo(mCurtainRight, mCurtainLeftAndTop);
+// //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+// curtainPath.lineTo(mCurtainRight, nowY);
+// //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+// curtainPath.lineTo(mCurtainLeftAndTop, nowY);
+// //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+// //curtainPath.lineTo(0, (1-mPercent)*mcurtainViewWidth);
+//// curtainPath.lineTo(-curtainMovingDistance, (1-mPercent)*mSeekBarHeight);
+//
+//// if(mPercent == 0 || mPercent ==1){
+//// curtainPath.lineTo(mCurtainLeftAndTop, nowY);
+//// }else {
+//// curtainPath.lineTo(-curtainMovingDistance, nowY);
+//// //浠巔3寮�濮嬪悜p0鏂瑰悜缁樺埗娉㈡氮鏇茬嚎
+//// for (int i = 0; i < curtainNum * 2; i++) {
+//// curtainPath.rQuadTo(curtainWidth / 2, changecurtainHeight, curtainWidth, 0);
+//// curtainPath.rQuadTo(curtainWidth / 2, -changecurtainHeight, curtainWidth, 0);
+//// }
+//// }
+//
+// curtainPath.lineTo(mCurtainLeftAndTop, mCurtainLeftAndTop);
+//
+// //灏唒ath灏侀棴璧锋潵
+// curtainPath.close();
+//
+//
+//
+// return curtainPath;
+// }
+//
+//
+// private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+// private boolean moved = false; // 鏄惁鍏佽
+// private int lastProgress = -1;
+//
+// @SuppressLint("ClickableViewAccessibility")
+// @Override
+// public boolean onTouchEvent(MotionEvent event) {
+// super.onTouchEvent(event);
+// if(!isClickable) return false;
+// int action = event.getActionMasked();
+// switch (action) {
+// case ACTION_DOWN:
+// moved = false;
+// judgeCanDrag(event);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onStartTrackingTouch(this);
+// }
+// break;
+// case ACTION_MOVE:
+// if (!mCanDrag) {
+// break;
+// }
+// setCurrentPercent(event);
+// // 浜嬩欢鍥炶皟
+// if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+// mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+// lastProgress = mProgress;
+// }
+// moved = true;
+// break;
+// case ACTION_UP:
+// case ACTION_CANCEL:
+// if(!moved){
+// if (isInArcProgress(event.getX(),event.getY())) {
+// setCurrentPercent(event);
+// }
+// }
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onStopTrackingTouch(this);
+// }
+// break;
+// }
+//
+// invalidate();
+// return true;
+// }
+//
+//
+// // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+// private void judgeCanDrag(MotionEvent event) {
+// if(isInArcProgress(event.getX(),event.getY())){
+// mCanDrag = true;
+// }else {
+// mCanDrag = false;
+// }
+// }
+//
+// private void setCurrentPercent(MotionEvent event) {
+//// Log.i("getCurrentProgress ","getCurrentProgress :Y " + event.getY() + " X:"+event.getX());
+// float progressY = event.getY() - mCurtainLeftAndTop;
+// float progress = progressY /mcurtainViewHeight;
+//// progress = 1 - progress;
+// if (progress < 0) progress = 0;
+// if (progress > 1) progress = 1;
+// mPercent = progress;
+// mProgress = (int) (mPercent * (mMaxValue - mMinValue)) + mMinValue;
+//
+// }
+//
+// private boolean isInArcProgress(float px ,float py) {
+//
+// if(px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight){
+// return false;
+// }else {
+// return true;
+// }
+// }
+//
+//
+//
+// // endregion -----------------------------------------------------------------------------------
+// // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+//
+// private HDLCurtainSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+//
+// public void setOnProgressChangeListener(HDLCurtainSeekBar.OnProgressChangeListener onProgressChangeListener) {
+// mOnProgressChangeListener = onProgressChangeListener;
+// }
+//
+// public interface OnProgressChangeListener {
+// /**
+// * 杩涘害鍙戠敓鍙樺寲
+// *
+// * @param seekBar 鎷栧姩鏉�
+// * @param progress 褰撳墠杩涘害鏁板��
+// * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+// */
+// void onProgressChanged(HDLCurtainSeekBar seekBar, int progress, boolean isUser);
+//
+// /**
+// * 鐢ㄦ埛寮�濮嬫嫋鍔�
+// *
+// * @param seekBar 鎷栧姩鏉�
+// */
+// void onStartTrackingTouch(HDLCurtainSeekBar seekBar);
+//
+// /**
+// * 鐢ㄦ埛缁撴潫鎷栧姩
+// *
+// * @param seekBar 鎷栧姩鏉�
+// */
+// void onStopTrackingTouch(HDLCurtainSeekBar seekBar);
+// }
+// // endregion -----------------------------------------------------------------------------------
+//
+//
+// //****************************瀵瑰鎺ュ彛****************************************************
+// /**
+// * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+// * @param isClickable
+// */
+// public void setIsClickable(Boolean isClickable) {
+// this.isClickable = isClickable;
+// }
+//
+// public int getProgress() {
+// return mProgress;
+// }
+//
+// public void setProgress(int progress) {
+// System.out.println("setProgress = " + progress);
+// if (progress > mMaxValue) progress = mMaxValue;
+// if (progress < mMinValue) progress = mMinValue;
+// mProgress = progress;
+// mPercent = (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+// postInvalidate();
+//
+// }
+//
+// /**
+// * 杩涘害鏂囧瓧澶у皬
+// * @param textSize
+// */
+// public void setProgressTextSize(int textSize){
+// mTextPaint.setTextSize(getTextSizeDip(textSize));
+// }
+//
+// /**
+// * 杩涘害鏂囧瓧棰滆壊
+// * @param textPaintColor
+// */
+// public void setProgressTextColor(int textPaintColor){
+// mTextPaint.setColor(textPaintColor);
+// }
+//
+// /**
+// * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+// *
+// * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+// */
+// public void setProgressBarUnitSring(String progressBarUnitSring) {
+// mProgressBarUnitSring = progressBarUnitSring;
+// }
+//
+// /**
+// * 璁剧疆鏈�澶ф暟鍊�
+// *
+// * @param max 鏈�澶ф暟鍊�
+// */
+// public void setMaxValue(int max) {
+// mMaxValue = max;
+// }
+//
+// /**
+// * 璁剧疆鏈�灏忔暟鍊�
+// *
+// * @param min 鏈�灏忔暟鍊�
+// */
+// public void setMinValue(int min) {
+// mMinValue = min;
+// }
+//
+//// public void setBorderWidth(int borderWidth) {
+//// mBorderWidth = dp2px(borderWidth);
+//// mBorderPaint.setStrokeWidth(mBorderWidth);
+//// oncurtainSizeChange();
+//// postInvalidate();
+//// }
+//
+//
+// public void setCurtainColor(int mCurtainColor){
+// curtainColor = mCurtainColor;
+// curtainPaint.setColor(curtainColor);
+//
+// }
+//
+//// public void setCurtainBorderColor(int mmBorderColor){
+//// mBorderColor = mmBorderColor;
+//// mBorderPaint.setColor(mBorderColor);
+//// }
+//
+// public void setCurtainBgColor(int mBgColor){
+// bgColor = mBgColor;
+// circlePaint.setColor(bgColor);
+// }
+//
+// public void setCurtainPadding(int mmPadding){
+// mPadding = dp2px(mmPadding);
+// oncurtainSizeChange();
+// }
+//
+// public void setCornerRadius(int mmCornerRadius){
+// mCornerRadius = dp2px(mmCornerRadius);
+//
+// }
+//
+// public void setProgressTextShow(Boolean progressTextShow) {
+// isProgressTextShow = progressTextShow;
+// }
+//
+// public void setTopCompensatePadding(int topCompensatePadding) {
+// this.topCompensatePadding = topCompensatePadding;
+// oncurtainSizeChange();
+// }
+//}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageSeekBar.java
new file mode 100644
index 0000000..51809dc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageSeekBar.java
@@ -0,0 +1,545 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+/**
+ * Created by JLChen on 2019/12/5
+ */
+public class HDLDiyImageSeekBar extends View {
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+ private Paint mImagePaint; //
+ private Paint mProgressPaint; //
+// private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+ private int mPadding = 10;
+ private boolean isClickable = true;
+ private float mSeekBarWidth;
+ private float mSeekBarHeight;
+
+ private float mDiySeekBarViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+ private int mDiySeekBarViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+ private boolean isProgressTextShow = true;
+ // private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+ private float nowX;
+ private float buttonWidth = 10;
+
+ private float mDiySeekBarPaddingTop = 5; //
+ private float mDiySeekBarPaddingBottom = 5; //
+
+ private Bitmap bgBitmapButton;
+ private boolean isOffline = false;
+ private Paint offlinePaint;
+ private int offlineRadius = 10;
+ private int mProgressBarColor = Color.YELLOW; //褰撳墠杩涘害棰滆壊
+ private int mBackgroundColor = HDLUtlisXM.DEFAULT_OFFLINE_COLOR; //褰撳墠鑳屾櫙棰滆壊
+
+ public HDLDiyImageSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLDiyImageSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLDiyImageSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+// initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ private void initData() {
+// defaultSize = dp2px(100);
+ mPadding = dp2px(10);
+ buttonWidth = dp2px(10);
+ offlineRadius = dp2px(5);
+ mPercent = 0.0f;
+ mProgress = 0;
+ mMaxValue = 100;
+ mMinValue = 0;
+ mDiySeekBarViewHeight = dp2px(10);
+ buttonWidth = mDiySeekBarViewHeight * 2;
+// mCornerRadius = dp2px(2);
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ isProgressTextShow = true;
+ bgBitmapButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_h_open);
+
+ }
+
+ private void initPaint() {
+ mImagePaint = new Paint();
+
+ offlinePaint = new Paint();
+ offlinePaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ offlinePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+
+ mProgressPaint = new Paint();
+ mProgressPaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ mProgressPaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ initTextPanit();
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(16));
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+
+// private void initAttrs(Context context, AttributeSet attrs) {
+// TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLDiySeekBarSeekBar);
+//
+// typedArray.recycle();
+// }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+
+ private void onDiySeekBarSizeChange() {
+ mDiySeekBarViewWidth = mSeekBarWidth - mPadding * 2;
+ mDiySeekBarPaddingTop = mSeekBarHeight/2 - mDiySeekBarViewHeight/2;
+ mDiySeekBarPaddingBottom = mSeekBarHeight/2 + mDiySeekBarViewHeight/2;
+
+ updateBitmapImage();
+ }
+
+ private void updateBitmapImage(){
+ try {
+
+ bgBitmapButton = resizeImage(bgBitmapButton, (int) buttonWidth, (int) buttonWidth);
+ } catch (Exception e) {
+ Log.e("updateBitmapImage 澶辫触", e.getMessage());
+ }
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+ mSeekBarHeight = hs;
+ mSeekBarWidth = ws;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ onDiySeekBarSizeChange();
+ }
+
+ private int measureSize(int defaultSize, int measureSpec) {
+ int result = defaultSize;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ onDiySeekBarSizeChange();
+ // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+ }
+
+
+ @SuppressLint("DrawAllocation")
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+
+ nowX = (mPercent) * mDiySeekBarViewWidth + mPadding;
+
+ int round = mDiySeekBarViewHeight / 2;
+ //璁剧疆progress鍐呴儴鏄伆鑹�
+ mProgressPaint.setColor(mBackgroundColor);
+ RectF rectBlackBg = new RectF(mPadding, mDiySeekBarPaddingTop , mSeekBarWidth - mPadding, mDiySeekBarPaddingBottom);
+ canvas.drawRoundRect(rectBlackBg, round, round, mProgressPaint);
+
+ //璁剧疆杩涘害鏉¤繘搴﹀強棰滆壊
+ RectF rectProgressBg = new RectF(mPadding, mDiySeekBarPaddingTop , nowX, mDiySeekBarPaddingBottom );
+ if (mPercent != 0.0f) {
+ mProgressPaint.setColor(mProgressBarColor);
+ } else {
+ mProgressPaint.setColor(Color.TRANSPARENT);
+ }
+ canvas.drawRoundRect(rectProgressBg, round, round, mProgressPaint);
+
+ canvas.drawBitmap(bgBitmapButton, nowX - bgBitmapButton.getWidth()/2.0F, mCenterY- bgBitmapButton.getHeight()/2.0F, mImagePaint);
+
+ if (isProgressTextShow) {
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, nowX, mDiySeekBarPaddingTop - 30, mTextPaint);
+ }
+
+ //缁樺埗绂荤嚎閬尅灞�
+ if(isOffline){
+ RectF rectF2 = new RectF(0, 0, mSeekBarWidth, mSeekBarHeight);
+ canvas.drawRoundRect(rectF2, offlineRadius, offlineRadius, offlinePaint);
+ }
+
+ canvas.restore();
+ }
+
+
+ public Bitmap getBitmap(int resId) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ TypedValue value = new TypedValue();
+ getResources().openRawResource(resId, value);
+ options.inTargetDensity = value.density;
+ options.inScaled = false;//涓嶇缉鏀�
+ return BitmapFactory.decodeResource(getResources(), resId, options);
+ }
+
+ public Bitmap resizeImage(Bitmap bitmap, int width, int height) {
+ int bmpWidth = bitmap.getWidth();
+ int bmpHeight = bitmap.getHeight();
+
+ float scaleWidth = ((float) width) / bmpWidth;
+ float scaleHeight = ((float) height) / bmpHeight;
+
+ Matrix matrix = new Matrix();
+ matrix.postScale(scaleWidth, scaleHeight);
+
+ return Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTHC"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ // private boolean bDownLeft = false; // 鏄惁宸︿晶
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if (!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if (!moved) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ mCanDrag = true;
+ } else {
+ mCanDrag = false;
+ }
+
+
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+ float progressX = event.getX() - mPadding;
+ float progress = progressX /mDiySeekBarViewWidth;
+
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ mPercent = progress;
+ mProgress = (int) ((mPercent) * (mMaxValue - mMinValue)) + mMinValue;
+
+ }
+
+ private boolean isInArcProgress(float px, float py) {
+
+ if (px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ // endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private HDLDiyImageSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLDiyImageSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLDiyImageSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLDiyImageSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLDiyImageSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ *
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(int progress) {
+// System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+
+ mProgress = progress;
+
+ mPercent = (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ *
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize) {
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ *
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor) {
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public void setDiySeekBarPadding(int mmPadding) {
+ mPadding = mmPadding;
+ onDiySeekBarSizeChange();
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+
+ public void setDiySeekBarViewHeight(int diySeekBarViewHeight) {
+ mDiySeekBarViewHeight = diySeekBarViewHeight;
+ onDiySeekBarSizeChange();
+ }
+
+ public void setBitmapButtonHeight(int mHeight) {
+ this.buttonWidth = mHeight;
+ updateBitmapImage();
+ }
+
+ public void setProgressBarColor(int progressBarColor) {
+ mProgressBarColor = progressBarColor;
+ }
+
+ public void setBarBackgroundColor(int backgroundColor) {
+ mBackgroundColor = backgroundColor;
+ }
+
+ public void setBgBitmapButton(Bitmap bgBitmapButton) {
+ this.bgBitmapButton = bgBitmapButton;
+ updateBitmapImage();
+ }
+
+ /**
+ * 璁剧疆绂荤嚎鐘舵��
+ * @param offline
+ */
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ isClickable = !isOffline;
+ postInvalidate();
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageVerticalSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageVerticalSeekBar.java
new file mode 100644
index 0000000..eb866e8
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLDiyImageVerticalSeekBar.java
@@ -0,0 +1,549 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+/**
+ * Created by jlchen on 2020-03-14.
+ */
+public class HDLDiyImageVerticalSeekBar extends View {
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+ private Paint mImagePaint; //
+ private Paint mProgressPaint; //
+ // private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+ private int mPadding = 10;
+ private boolean isClickable = true;
+ private float mSeekBarWidth;
+ private float mSeekBarHeight;
+
+ private float mDiySeekBarViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+ private int mDiySeekBarViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+ private boolean isProgressTextShow = true;
+ // private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+// private float nowX;
+ private float nowY;
+ private float buttonWidth = 10;
+
+ private float mDiySeekBarPaddingLeft = 5; //
+ private float mDiySeekBarPaddingRight = 5; //
+ private float mDiySeekBarPaddingTop = 5; //
+ private float mDiySeekBarPaddingBottom = 5; //
+
+ private Bitmap bgBitmapButton;
+ private boolean isOffline = false;
+ private Paint offlinePaint;
+ private int offlineRadius = 10;
+ private int mProgressBarColor = Color.YELLOW; //褰撳墠杩涘害棰滆壊
+ private int mBackgroundColor = HDLUtlisXM.DEFAULT_OFFLINE_COLOR; //褰撳墠鑳屾櫙棰滆壊
+
+ public HDLDiyImageVerticalSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLDiyImageVerticalSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLDiyImageVerticalSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+// initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ private void initData() {
+// defaultSize = dp2px(100);
+ mPadding = dp2px(10);
+ buttonWidth = dp2px(10);
+ offlineRadius = dp2px(5);
+ mPercent = 1.0f;
+ mProgress = 0;
+ mMaxValue = 100;
+ mMinValue = 0;
+ mDiySeekBarViewHeight = dp2px(10);
+ buttonWidth = mDiySeekBarViewHeight * 2;
+// mCornerRadius = dp2px(2);
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ isProgressTextShow = true;
+ bgBitmapButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_h_open);
+
+ }
+
+ private void initPaint() {
+ mImagePaint = new Paint();
+
+ offlinePaint = new Paint();
+ offlinePaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ offlinePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+
+ mProgressPaint = new Paint();
+ mProgressPaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ mProgressPaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ initTextPanit();
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(12));
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+
+// private void initAttrs(Context context, AttributeSet attrs) {
+// TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLDiySeekBarSeekBar);
+//
+// typedArray.recycle();
+// }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+
+ private void onDiySeekBarSizeChange() {
+ mDiySeekBarViewWidth = mSeekBarHeight - mPadding * 2;
+ mDiySeekBarPaddingTop = mPadding;
+ mDiySeekBarPaddingBottom = mSeekBarHeight-mPadding;
+ mDiySeekBarPaddingLeft = mSeekBarWidth/2 - mDiySeekBarViewHeight/2;
+ mDiySeekBarPaddingRight = mSeekBarWidth/2 + mDiySeekBarViewHeight/2;
+ updateBitmapImage();
+ }
+
+ private void updateBitmapImage(){
+ try {
+
+ bgBitmapButton = resizeImage(bgBitmapButton, (int) buttonWidth, (int) buttonWidth);
+ } catch (Exception e) {
+ Log.e("updateBitmapImage 澶辫触", e.getMessage());
+ }
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+ mSeekBarHeight = hs;
+ mSeekBarWidth = ws;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ onDiySeekBarSizeChange();
+ }
+
+ private int measureSize(int defaultSize, int measureSpec) {
+ int result = defaultSize;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ onDiySeekBarSizeChange();
+ // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+ }
+
+
+ @SuppressLint("DrawAllocation")
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+
+ nowY = (mPercent) * mDiySeekBarViewWidth + mPadding;
+
+ int round = mDiySeekBarViewHeight / 2;
+ //璁剧疆progress鍐呴儴鏄伆鑹�
+ mProgressPaint.setColor(mBackgroundColor);
+ RectF rectBlackBg = new RectF(mDiySeekBarPaddingLeft, mDiySeekBarPaddingTop , mDiySeekBarPaddingRight, mDiySeekBarPaddingBottom);
+ canvas.drawRoundRect(rectBlackBg, round, round, mProgressPaint);
+
+ //璁剧疆杩涘害鏉¤繘搴﹀強棰滆壊
+ RectF rectProgressBg = new RectF(mDiySeekBarPaddingLeft, nowY , mDiySeekBarPaddingRight, mSeekBarHeight - mPadding );
+ if (mPercent != 1.0f) {
+ mProgressPaint.setColor(mProgressBarColor);
+ } else {
+ mProgressPaint.setColor(Color.TRANSPARENT);
+ }
+ canvas.drawRoundRect(rectProgressBg, round, round, mProgressPaint);
+
+ canvas.drawBitmap(bgBitmapButton, mCenterX- bgBitmapButton.getHeight()/2.0F , nowY - bgBitmapButton.getWidth()/2.0F, mImagePaint);
+
+ if (isProgressTextShow) {
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX + bgBitmapButton.getHeight()/2.0F + dp2px(10), nowY, mTextPaint);
+ }
+
+ //缁樺埗绂荤嚎閬尅灞�
+ if(isOffline){
+ RectF rectF2 = new RectF(0, 0, mSeekBarWidth, mSeekBarHeight);
+ canvas.drawRoundRect(rectF2, offlineRadius, offlineRadius, offlinePaint);
+ }
+
+ canvas.restore();
+ }
+
+
+ public Bitmap getBitmap(int resId) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ TypedValue value = new TypedValue();
+ getResources().openRawResource(resId, value);
+ options.inTargetDensity = value.density;
+ options.inScaled = false;//涓嶇缉鏀�
+ return BitmapFactory.decodeResource(getResources(), resId, options);
+ }
+
+ public Bitmap resizeImage(Bitmap bitmap, int width, int height) {
+ int bmpWidth = bitmap.getWidth();
+ int bmpHeight = bitmap.getHeight();
+
+ float scaleWidth = ((float) width) / bmpWidth;
+ float scaleHeight = ((float) height) / bmpHeight;
+
+ Matrix matrix = new Matrix();
+ matrix.postScale(scaleWidth, scaleHeight);
+
+ return Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTHC"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ // private boolean bDownLeft = false; // 鏄惁宸︿晶
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if (!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if (!moved) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ mCanDrag = true;
+ } else {
+ mCanDrag = false;
+ }
+
+
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+ float progressY = event.getY() - mPadding;
+ float progress = progressY /mDiySeekBarViewWidth;
+
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ mPercent = progress;
+ mProgress = (int) ((1 - mPercent) * (mMaxValue - mMinValue)) + mMinValue;
+
+ }
+
+ private boolean isInArcProgress(float px, float py) {
+
+ if (px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ // endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private HDLDiyImageVerticalSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLDiyImageVerticalSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLDiyImageVerticalSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLDiyImageVerticalSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLDiyImageVerticalSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ *
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(int progress) {
+// System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+
+ mProgress = progress;
+
+ mPercent = 1 - (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ *
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize) {
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ *
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor) {
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public void setDiySeekBarPadding(int mmPadding) {
+ mPadding = mmPadding;
+ onDiySeekBarSizeChange();
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+
+ public void setDiySeekBarViewHeight(int diySeekBarViewHeight) {
+ mDiySeekBarViewHeight = diySeekBarViewHeight;
+ onDiySeekBarSizeChange();
+ }
+
+ public void setBitmapButtonHeight(int mHeight) {
+ this.buttonWidth = mHeight;
+ updateBitmapImage();
+ }
+
+ public void setProgressBarColor(int progressBarColor) {
+ mProgressBarColor = progressBarColor;
+ }
+
+ public void setBarBackgroundColor(int backgroundColor) {
+ mBackgroundColor = backgroundColor;
+ }
+
+ public void setBgBitmapButton(Bitmap bgBitmapButton) {
+ this.bgBitmapButton = bgBitmapButton;
+ updateBitmapImage();
+ }
+
+ /**
+ * 璁剧疆绂荤嚎鐘舵��
+ * @param offline
+ */
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ isClickable = !isOffline;
+ postInvalidate();
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLOACCurtainSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLOACCurtainSeekBar.java
new file mode 100644
index 0000000..c388829
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLOACCurtainSeekBar.java
@@ -0,0 +1,597 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+
+/**
+ * Created by JLChen on 2019/11/5
+ */
+public class HDLOACCurtainSeekBar extends View {
+
+// private static final int DEFAULT_OFFLINE_COLOR = 0xC8E9E9EC;
+
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+ private Paint mImagePaint; //
+ private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+ private int mPadding = 10;
+ private boolean isClickable = true;
+ private float mSeekBarWidth;
+ private float mSeekBarWidthHalf;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫涓�鍗�
+ private int mSeekBarHeight;
+
+ private int mTopImageHeight;
+ private float mCurtainViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+ private float mCurtainViewWidthHalf;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫涓�鍗�
+
+ private float mCurtainViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+// private float mCurtainPaddingTop;
+
+ private boolean isProgressTextShow = true;
+
+// private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+ private float nowX;
+ private float buttonWidth = 10;
+
+ private int mCurtainPaddingTop = 5; //椤堕儴鍥剧墖琛ュ伩鍊�
+
+ private Bitmap bitmap;//缂撳瓨bitmap
+ private Canvas bitmapCanvas;
+ private Bitmap bgBitmapCurtain,bgBitmapButton;
+ private Bitmap bgBitmapTop;
+
+ private boolean isOffline = false;
+ private Paint offlinePaint;
+ private int offlineRadius = 10;
+
+ public HDLOACCurtainSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLOACCurtainSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLOACCurtainSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+// initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ private void initData() {
+ defaultSize = dp2px(100);
+ mPadding = dp2px(15);
+ mCurtainPaddingTop = dp2px(5);
+ buttonWidth = dp2px(10);
+ offlineRadius = dp2px(5);
+ mPercent = 0.0f;
+ mProgress = 0;
+ mMaxValue = 100;
+ mMinValue = 0;
+// mCornerRadius = dp2px(2);
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ isProgressTextShow = true;
+ setBackgroundResource(R.drawable.ic_wd_curtain_h_bg);
+ }
+
+ private void initPaint() {
+ mImagePaint = new Paint();
+ offlinePaint = new Paint();
+ offlinePaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ offlinePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ initTextPanit();
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(16));
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+
+// private void initAttrs(Context context, AttributeSet attrs) {
+// TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLCurtainSeekBar);
+//
+// typedArray.recycle();
+// }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+
+ private void oncurtainSizeChange() {
+ mSeekBarWidthHalf = mSeekBarWidth / 2;
+ mCurtainViewWidth = mSeekBarWidth - mPadding * 2;
+ mCurtainViewWidthHalf = mCurtainViewWidth / 2;
+
+// mCurtainPaddingTop = mPadding - mCurtainPaddingTop;
+ mCurtainViewHeight = mSeekBarHeight - mCurtainPaddingTop;
+ buttonWidth = mCurtainViewWidth / 6;
+ mTopImageHeight = (int) mSeekBarWidth*18/396;
+ updateBitmapImage();
+ }
+
+ private void updateBitmapImage(){
+
+ try {
+ bgBitmapCurtain = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_h_progress);
+ bgBitmapCurtain = resizeImage(bgBitmapCurtain, (int) mCurtainViewWidth, (int) mCurtainViewHeight);
+
+ bgBitmapButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_h_open);
+ bgBitmapButton = resizeImage(bgBitmapButton, (int) buttonWidth, (int) buttonWidth);
+
+ bgBitmapTop = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_h_top);
+ bgBitmapTop = resizeImage(bgBitmapTop, (int) mSeekBarWidth, mTopImageHeight);
+
+ } catch (Exception e) {
+ Log.e("updateBitmapImage 澶辫触", e.getMessage());
+ }
+
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+ mSeekBarHeight = hs;
+ mSeekBarWidth = ws;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ oncurtainSizeChange();
+ }
+
+ private int measureSize(int defaultSize, int measureSpec) {
+ int result = defaultSize;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ oncurtainSizeChange();
+ // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+ }
+
+
+ @SuppressLint("DrawAllocation")
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+ bitmap = Bitmap.createBitmap((int) mCurtainViewWidth, (int) mSeekBarHeight, Bitmap.Config.ARGB_8888);
+ bitmapCanvas = new Canvas(bitmap);
+ nowX = (mPercent) * mCurtainViewWidthHalf;
+ if(mPercent==1){
+ bitmapCanvas.drawBitmap(bgBitmapCurtain, 0 , mCurtainPaddingTop, mImagePaint);
+ }else {
+ bitmapCanvas.drawBitmap(bgBitmapCurtain, nowX - mCurtainViewWidth, mCurtainPaddingTop,mImagePaint);
+ bitmapCanvas.drawBitmap(bgBitmapCurtain, mCurtainViewWidth - nowX, mCurtainPaddingTop, mImagePaint);
+ }
+ canvas.drawBitmap(bitmap, mPadding , 0, null);
+
+ if (isProgressTextShow) {
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, mCenterY - buttonWidth, mTextPaint);
+ }
+ canvas.drawBitmap(bgBitmapButton, nowX + mPadding - bgBitmapButton.getWidth() / 2.0F, mSeekBarHeight / 2 - bgBitmapButton.getHeight() / 2.0F, mImagePaint);
+
+ canvas.drawBitmap(bgBitmapTop,0,0,mImagePaint);
+
+ //缁樺埗绂荤嚎閬尅灞�
+ if(isOffline){
+ RectF rectF2 = new RectF(0, 0, mSeekBarWidth, mSeekBarHeight);
+ canvas.drawRoundRect(rectF2, offlineRadius, offlineRadius, offlinePaint);
+ }
+
+ canvas.restore();
+ }
+
+
+
+
+ public Bitmap getBitmap(int resId) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ TypedValue value = new TypedValue();
+ getResources().openRawResource(resId, value);
+ options.inTargetDensity = value.density;
+ options.inScaled = false;//涓嶇缉鏀�
+ return BitmapFactory.decodeResource(getResources(), resId, options);
+ }
+
+ public Bitmap resizeImage(Bitmap bitmap, int width, int height) {
+ int bmpWidth = bitmap.getWidth();
+ int bmpHeight = bitmap.getHeight();
+
+ float scaleWidth = ((float) width) / bmpWidth;
+ float scaleHeight = ((float) height) / bmpHeight;
+
+ Matrix matrix = new Matrix();
+ matrix.postScale(scaleWidth, scaleHeight);
+
+ return Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTHC"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+//
+// private Path getCurtainPath() {
+//// float changeWaveHeight = (1 - mPercent) * curtainHeight;
+// float changeWaveHeight = curtainHeight;
+// nowX = (mPercent) * mcurtainViewWidthHalf + mPadding;
+//
+// curtainPath.reset();
+//
+// //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+// curtainPath.moveTo(mCurtainLeftAndTop, mCurtainLeftAndTop);
+// //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+// curtainPath.lineTo(mCurtainLeftAndTop, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+// curtainPath.lineTo(nowX, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+// curtainPath.lineTo(nowX, mCurtainLeftAndTop);
+//
+// //灏唒ath灏侀棴璧锋潵
+// curtainPath.close();
+//
+//
+// return curtainPath;
+// }
+//
+// private Path getCurtainPathRight() {
+// curtainPathRight.reset();
+// //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+// curtainPathRight.moveTo(mCurtainRight, mCurtainLeftAndTop);
+// //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+// curtainPathRight.lineTo(mCurtainRight, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+// curtainPathRight.lineTo(mSeekBarWidth-nowX, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+// curtainPathRight.lineTo(mSeekBarWidth-nowX, mCurtainLeftAndTop);
+// //灏唒ath灏侀棴璧锋潵
+// curtainPathRight.close();
+// return curtainPathRight;
+// }
+//
+
+
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ private boolean bDownLeft = false; // 鏄惁宸︿晶
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if (!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if (!moved) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ mCanDrag = true;
+ } else {
+ mCanDrag = false;
+ }
+ bDownLeft = (event.getX() - mSeekBarWidthHalf) < 0;
+
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+// Log.i("getCurrentProgress ","getCurrentProgress :Y " + event.getY() + " X:"+event.getX());
+// boolean isLeft = (event.getX() - mSeekBarWidthHalf) < 0;
+ float progress = 0;
+ if (bDownLeft) {
+ float progressX = event.getX() - mPadding;
+ progress = progressX / mCurtainViewWidthHalf;
+ } else {
+ float progressX = event.getX() - mSeekBarWidthHalf;
+ progress = 1 - progressX / mCurtainViewWidthHalf;
+ }
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ mPercent = progress;
+ mProgress = (int) ((1 - mPercent) * (mMaxValue - mMinValue)) + mMinValue;
+
+ }
+
+ private boolean isInArcProgress(float px, float py) {
+
+ if (px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ // endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private HDLOACCurtainSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLOACCurtainSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLOACCurtainSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLOACCurtainSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLOACCurtainSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ *
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(int progress) {
+// System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+ mProgress = progress;
+ mPercent = 1 - (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ *
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize) {
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ *
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor) {
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public void setCurtainPadding(int mmPadding) {
+// mPadding = dp2px(mmPadding);
+
+ mPadding = mmPadding;
+ oncurtainSizeChange();
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+ public void setCurtainPaddingTop(int curtainPaddingTop) {
+// mCurtainPaddingTop = dp2px(curtainPaddingTop);
+ mCurtainPaddingTop = curtainPaddingTop;
+ oncurtainSizeChange();
+ }
+
+
+ /**
+ * 璁剧疆绂荤嚎鐘舵��
+ * @param offline
+ */
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ isClickable = !isOffline;
+ postInvalidate();
+ }
+
+
+ /**
+ *褰撳墠 杩涘害X鍧愭爣
+ */
+ public float getProgressX() {
+ return nowX;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLRollCurtainSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLRollCurtainSeekBar.java
new file mode 100644
index 0000000..59c1326
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLRollCurtainSeekBar.java
@@ -0,0 +1,584 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+
+/**
+ * Created by JLChen on 2019/11/5
+ */
+public class HDLRollCurtainSeekBar extends View {
+// private static final int DEFAULT_OFFLINE_COLOR = 0xC8E9E9EC;
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+ private Paint mImagePaint; //
+ private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+ private int mPadding = 10;
+ private boolean isClickable = true;
+ private float mSeekBarWidth;
+ private float mSeekBarHeight;
+
+ private float mCurtainViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+ private float mCurtainViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+// private float mCurtainPaddingTop;
+
+ private boolean isProgressTextShow = true;
+
+// private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+ private float nowY;
+ private float buttonWidth = 10;
+
+ private int mCurtainPaddingTop = 5; //椤堕儴鍥剧墖琛ュ伩鍊�
+ private int mCurtainPaddingHeight = 5; //
+
+
+ private Bitmap bitmap;//缂撳瓨bitmap
+ private Canvas bitmapCanvas;
+ private Bitmap bgBitmapCurtain,bgBitmapButton;
+
+ private boolean isOffline = false;
+ private Paint offlinePaint;
+ private int offlineRadius = 10;
+
+
+
+ public HDLRollCurtainSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLRollCurtainSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLRollCurtainSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+// initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ private void initData() {
+ defaultSize = dp2px(100);
+ mPadding = dp2px(4);
+ mCurtainPaddingTop = dp2px(55);
+ buttonWidth = dp2px(10);
+ mCurtainPaddingHeight= dp2px(10);
+ offlineRadius = dp2px(5);
+ mPercent = 0.0f;
+ mProgress = 0;
+ mMaxValue = 100;
+ mMinValue = 0;
+// mCornerRadius = dp2px(2);
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ isProgressTextShow = true;
+ setBackgroundResource(R.drawable.ic_wd_curtain_roll_bg);
+ }
+
+ private void initPaint() {
+ mImagePaint = new Paint();
+
+ offlinePaint = new Paint();
+ offlinePaint.setColor(HDLUtlisXM.DEFAULT_OFFLINE_COLOR);
+ offlinePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+
+ initTextPanit();
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(16));
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+
+// private void initAttrs(Context context, AttributeSet attrs) {
+// TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLCurtainSeekBar);
+//
+// typedArray.recycle();
+// }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+
+ private void oncurtainSizeChange() {
+ mCurtainViewWidth = mSeekBarWidth - mPadding * 2;
+ mCurtainViewHeight = mSeekBarHeight - mCurtainPaddingTop;
+ buttonWidth = mCurtainViewWidth / 5;
+ updateBitmapImage();
+ }
+
+ private void updateBitmapImage(){
+ try {
+ bgBitmapCurtain = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_roll_progress);
+ bgBitmapCurtain = resizeImage(bgBitmapCurtain, (int) mCurtainViewWidth, (int) mCurtainViewHeight + mCurtainPaddingHeight);
+
+ bgBitmapButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_wd_curtain_open);
+ bgBitmapButton = resizeImage(bgBitmapButton, (int) buttonWidth, (int) buttonWidth);
+ } catch (Exception e) {
+ Log.e("updateBitmapImage 澶辫触", e.getMessage());
+ }
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+ mSeekBarHeight = hs;
+ mSeekBarWidth = ws;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ oncurtainSizeChange();
+ }
+
+ private int measureSize(int defaultSize, int measureSpec) {
+ int result = defaultSize;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+ mCenterX = mSeekBarWidth / 2;
+ mCenterY = mSeekBarHeight / 2;
+ oncurtainSizeChange();
+ // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+ }
+
+
+ @SuppressLint("DrawAllocation")
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+
+ bitmap = Bitmap.createBitmap((int) mSeekBarWidth, (int) mCurtainViewHeight, Bitmap.Config.ARGB_8888);
+ bitmapCanvas = new Canvas(bitmap);
+ nowY = (mPercent) * mCurtainViewHeight + mCurtainPaddingTop;
+
+ bitmapCanvas.drawBitmap(bgBitmapCurtain, mPadding, nowY - mCurtainViewHeight - mCurtainPaddingTop - mCurtainPaddingHeight ,mImagePaint);
+
+
+ canvas.drawBitmap(bitmap, 0 , mCurtainPaddingTop, null);
+
+ if (isProgressTextShow) {
+ if(mPercent > 0.3) {//灏忎簬 70% 鐨勬椂鍊欐枃瀛楁樉绀哄湪涓婃柟
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, nowY - bgBitmapButton.getHeight(), mTextPaint);
+ }else {
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, nowY + bgBitmapButton.getHeight(), mTextPaint);
+ }
+ }
+
+ canvas.drawBitmap(bgBitmapButton, mSeekBarWidth/2 - bgBitmapButton.getWidth()/2.0F, nowY - bgBitmapButton.getHeight()/2.0F, mImagePaint);
+
+ //缁樺埗绂荤嚎閬尅灞�
+ if(isOffline){
+ RectF rectF2 = new RectF(0, 0, mSeekBarWidth, mSeekBarHeight);
+ canvas.drawRoundRect(rectF2, offlineRadius, offlineRadius, offlinePaint);
+ }
+
+ canvas.restore();
+ }
+
+
+ public Bitmap getBitmap(int resId) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ TypedValue value = new TypedValue();
+ getResources().openRawResource(resId, value);
+ options.inTargetDensity = value.density;
+ options.inScaled = false;//涓嶇缉鏀�
+ return BitmapFactory.decodeResource(getResources(), resId, options);
+ }
+
+ public Bitmap resizeImage(Bitmap bitmap, int width, int height) {
+ int bmpWidth = bitmap.getWidth();
+ int bmpHeight = bitmap.getHeight();
+
+ float scaleWidth = ((float) width) / bmpWidth;
+ float scaleHeight = ((float) height) / bmpHeight;
+
+ Matrix matrix = new Matrix();
+ matrix.postScale(scaleWidth, scaleHeight);
+
+ return Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTHC"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+//
+// private Path getCurtainPath() {
+//// float changeWaveHeight = (1 - mPercent) * curtainHeight;
+// float changeWaveHeight = curtainHeight;
+// nowY = (mPercent) * mcurtainViewWidthHalf + mPadding;
+//
+// curtainPath.reset();
+//
+// //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+// curtainPath.moveTo(mCurtainLeftAndTop, mCurtainLeftAndTop);
+// //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+// curtainPath.lineTo(mCurtainLeftAndTop, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+// curtainPath.lineTo(nowY, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+// curtainPath.lineTo(nowY, mCurtainLeftAndTop);
+//
+// //灏唒ath灏侀棴璧锋潵
+// curtainPath.close();
+//
+//
+// return curtainPath;
+// }
+//
+// private Path getCurtainPathRight() {
+// curtainPathRight.reset();
+// //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+// curtainPathRight.moveTo(mCurtainRight, mCurtainLeftAndTop);
+// //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+// curtainPathRight.lineTo(mCurtainRight, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+// curtainPathRight.lineTo(mSeekBarWidth-nowY, mSeekBarHeight-mPadding);
+// //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+// curtainPathRight.lineTo(mSeekBarWidth-nowY, mCurtainLeftAndTop);
+// //灏唒ath灏侀棴璧锋潵
+// curtainPathRight.close();
+// return curtainPathRight;
+// }
+//
+
+
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+// private boolean bDownLeft = false; // 鏄惁宸︿晶
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if (!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if (!moved) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if (isInArcProgress(event.getX(), event.getY())) {
+ mCanDrag = true;
+ } else {
+ mCanDrag = false;
+ }
+
+
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+// Log.i("getCurrentProgress ","getCurrentProgress :Y " + event.getY() + " X:"+event.getX());
+// boolean isLeft = (event.getX() - mSeekBarWidthHalf) < 0;
+
+ float progressY = event.getY() - mCurtainPaddingTop;
+ float progress = progressY /mCurtainViewHeight;
+
+
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ mPercent = progress;
+ mProgress = (int) ((1 - mPercent) * (mMaxValue - mMinValue)) + mMinValue;
+
+ }
+
+ private boolean isInArcProgress(float px, float py) {
+
+ if (px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ // endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private HDLRollCurtainSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLRollCurtainSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLRollCurtainSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLRollCurtainSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLRollCurtainSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ *
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(int progress) {
+// System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+
+ mProgress = progress;
+
+ mPercent = 1 - (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ *
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize) {
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ *
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor) {
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public void setCurtainPadding(int mmPadding) {
+// mPadding = dp2px(mmPadding);
+ mPadding = mmPadding;
+ oncurtainSizeChange();
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+ public void setCurtainPaddingTop(int curtainPaddingTop) {
+// mCurtainPaddingTop = dp2px(curtainPaddingTop);
+ mCurtainPaddingTop = curtainPaddingTop;
+ oncurtainSizeChange();
+ }
+
+ /**
+ * 璁剧疆绂荤嚎鐘舵��
+ * @param offline
+ */
+ public void setOffline(boolean offline) {
+ isOffline = offline;
+ isClickable = !isOffline;
+ postInvalidate();
+ }
+
+ /**
+ *褰撳墠 杩涘害Y鍧愭爣
+ */
+ public float getProgressY() {
+ return nowY;
+ }
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLUtlisXM.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLUtlisXM.java
new file mode 100644
index 0000000..e8fb1b3
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLUtlisXM.java
@@ -0,0 +1,228 @@
+package com.hdl.widget;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.annotation.NonNull;
+import android.util.Log;
+import java.util.List;
+
+/**
+ * Created by JLChen on 2019/9/23
+ */
+public final class HDLUtlisXM {
+ public static final int DEFAULT_OFFLINE_COLOR = 0xC8E9E9EC;
+ public static String MAuthority_NAME = "com.hdl.widgetxm.fileprovider";
+ public static final String CROP_TYPE_KEY = "Type";
+ public static final String CROP_NAME_KEY = "FileName";
+ public static final String CROP_RATIO_X_KEY = "ImageRatioX";
+ public static final String CROP_RATIO_Y_KEY = "ImageRatioY";
+ public static final String CROP_OUTPUT_Y_KEY = "ImageUotputY";
+
+
+ private HDLUtlisXM() {
+ throw new UnsupportedOperationException("u can't instantiate me...");
+ }
+
+
+ /**
+ * dp杞琾x
+ *
+ * @param dpValue dp鍊�
+ * @return px鍊�
+ */
+ public static int dp2px(Context context, final float dpValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ /**
+ * px杞琩p
+ *
+ * @param pxValue px鍊�
+ * @return dp鍊�
+ */
+ public static int px2dp(Context context, final float pxValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (pxValue / scale + 0.5f);
+ }
+
+ /**
+ * Relaunch the application.
+ */
+ public static void relaunchApp(Context mContext) {
+ relaunchApp(mContext, false);
+ }
+
+ /**
+ * Relaunch the application.
+ *
+ * @param isKillProcess True to kill the process, false otherwise.
+ */
+ public static void relaunchApp(Context mContext, final boolean isKillProcess) {
+ Intent intent = getLaunchAppIntent(mContext, mContext.getPackageName(), true);
+ if (intent == null) {
+ Log.e("AppUtils", "Didn't exist launcher activity.");
+ return;
+ }
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ );
+ mContext.startActivity(intent);
+ if (!isKillProcess) return;
+ android.os.Process.killProcess(android.os.Process.myPid());
+ System.exit(0);
+ }
+
+ private static Intent getLaunchAppIntent(Context mContext, final String packageName) {
+ return getLaunchAppIntent(mContext, packageName, false);
+ }
+
+ private static Intent getLaunchAppIntent(Context mContext, final String packageName, final boolean isNewTask) {
+ String launcherActivity = getLauncherActivity(mContext, packageName);
+ if (!launcherActivity.isEmpty()) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ ComponentName cn = new ComponentName(packageName, launcherActivity);
+ intent.setComponent(cn);
+ return isNewTask ? intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) : intent;
+ }
+ return null;
+ }
+
+ private static String getLauncherActivity(Context mContext, @NonNull final String pkg) {
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setPackage(pkg);
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> info = pm.queryIntentActivities(intent, 0);
+ int size = info.size();
+ if (size == 0) return "";
+ for (int i = 0; i < size; i++) {
+ ResolveInfo ri = info.get(i);
+ if (ri.activityInfo.processName.equals(pkg)) {
+ return ri.activityInfo.name;
+ }
+ }
+ return info.get(0).activityInfo.name;
+ }
+
+
+// /**
+// * 鐢熸垚浜岀淮鐮侊紝榛樿澶у皬涓�500*500
+// *
+// * @param url 闇�瑕佺敓鎴愪簩缁寸爜鐨勭綉鍧�锛屼篃鍙互鏄枃瀛�
+// * @return bitmap
+// */
+// public static Bitmap createQRCode(String url) {
+// return createQRCode(url, 500);
+// }
+//
+// /**
+// * 鐢熸垚浜岀淮鐮侊紝榛樿澶у皬涓�500*500
+// *
+// * @param url 闇�瑕佺敓鎴愪簩缁寸爜鐨勭綉鍧�锛屼篃鍙互鏄枃瀛�
+// * @param size 闇�瑕佺敓鎴愪簩缁寸爜鐨勫ぇ灏忥紙锛�
+// * @return bitmap
+// */
+// public static Bitmap createQRCode(String url, int size) {
+// try {
+// Hashtable<EncodeHintType, String> hints = new Hashtable<>();
+// hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+// BitMatrix bitMatrix = new QRCodeWriter().encode(url,
+// BarcodeFormat.QR_CODE, size, size, hints);
+// int[] pixels = new int[size * size];
+// for (int y = 0; y < size; y++) {
+// for (int x = 0; x < size; x++) {
+// if (bitMatrix.get(x, y)) {
+// pixels[y * size + x] = 0xff000000;
+// } else {
+// pixels[y * size + x] = 0xffffffff;
+// }
+//
+// }
+// }
+// Bitmap bitmap = Bitmap.createBitmap(size, size,
+// Bitmap.Config.ARGB_8888);
+// bitmap.setPixels(pixels, 0, size, 0, 0, size, size);
+// return bitmap;
+// } catch (WriterException e) {
+// e.printStackTrace();
+// return null;
+// }
+// }
+//
+// /**
+// * @param url 闇�瑕佺敓鎴愪簩缁寸爜鐨勬枃瀛椼�佺綉鍧�绛�
+// * @param size 闇�瑕佺敓鎴愪簩缁寸爜鐨勫ぇ灏忥紙锛�
+// * @param mBitmap logo鏂囦欢
+// * @return bitmap
+// */
+// private static int IMAGE_HALFWIDTH = 50;//瀹藉害鍊硷紝褰卞搷涓棿鍥剧墖澶у皬
+//
+// public static Bitmap createQRCodeWithLogo(String url, Bitmap mBitmap) {
+// return createQRCodeWithLogo(url, 500, mBitmap);
+// }
+//
+// public static Bitmap createQRCodeWithLogo(String url, int size, Bitmap mBitmap) {
+// try {
+// IMAGE_HALFWIDTH = size / 10;
+// Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
+// hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+// /*
+// * 璁剧疆瀹归敊绾у埆锛岄粯璁や负ErrorCorrectionLevel.L
+// * 鍥犱负涓棿鍔犲叆logo鎵�浠ュ缓璁綘鎶婂閿欑骇鍒皟鑷矵,鍚﹀垯鍙兘浼氬嚭鐜拌瘑鍒笉浜�
+// */
+// hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+// BitMatrix bitMatrix = new QRCodeWriter().encode(url,
+// BarcodeFormat.QR_CODE, size, size, hints);
+//
+// int width = bitMatrix.getWidth();//鐭╅樀楂樺害
+// int height = bitMatrix.getHeight();//鐭╅樀瀹藉害
+// int halfW = width / 2;
+// int halfH = height / 2;
+//
+// Matrix m = new Matrix();
+// float sx = (float) 2 * IMAGE_HALFWIDTH / mBitmap.getWidth();
+// float sy = (float) 2 * IMAGE_HALFWIDTH
+// / mBitmap.getHeight();
+// m.setScale(sx, sy);
+// //璁剧疆缂╂斁淇℃伅
+// //灏唋ogo鍥剧墖鎸塵artix璁剧疆鐨勪俊鎭缉鏀�
+// mBitmap = Bitmap.createBitmap(mBitmap, 0, 0,
+// mBitmap.getWidth(), mBitmap.getHeight(), m, false);
+//
+// int[] pixels = new int[size * size];
+// for (int y = 0; y < size; y++) {
+// for (int x = 0; x < size; x++) {
+// if (x > halfW - IMAGE_HALFWIDTH && x < halfW + IMAGE_HALFWIDTH
+// && y > halfH - IMAGE_HALFWIDTH
+// && y < halfH + IMAGE_HALFWIDTH) {
+// //璇ヤ綅缃敤浜庡瓨鏀惧浘鐗囦俊鎭�
+// //璁板綍鍥剧墖姣忎釜鍍忕礌淇℃伅
+// pixels[y * width + x] = mBitmap.getPixel(x - halfW
+// + IMAGE_HALFWIDTH, y - halfH + IMAGE_HALFWIDTH);
+// } else {
+// if (bitMatrix.get(x, y)) {
+// pixels[y * size + x] = 0xff000000;
+// } else {
+// pixels[y * size + x] = 0xffffffff;
+// }
+// }
+// }
+// }
+// Bitmap bitmap = Bitmap.createBitmap(size, size,
+// Bitmap.Config.ARGB_8888);
+// bitmap.setPixels(pixels, 0, size, 0, 0, size, size);
+// return bitmap;
+// } catch (WriterException e) {
+// e.printStackTrace();
+// return null;
+// }
+// }
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLWaveSeekBar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLWaveSeekBar.java
new file mode 100644
index 0000000..7fd3b31
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/HDLWaveSeekBar.java
@@ -0,0 +1,630 @@
+package com.hdl.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+/**
+ * Created by JLChen on 2019/9/3
+ */
+public class HDLWaveSeekBar extends View {
+
+ private static final int DEFAULT_WAVE_BORDER_COLOR = 0xFF495780;
+// private static final int DEFAULT_WAVE_COLOR = 0xFFFC5733;
+ private static final int DEFAULT_WAVE_COLOR = 0xFFFD692E;
+ private static final int DEFAULT_WAVE_END_COLOR = 0xFFFB3140;
+
+
+
+ private static final int DEFAULT_EDGE_LENGTH = 200; // 榛樿瀹介珮
+ private Paint mBorderPaint;//鍦嗗舰杩涘害妗嗙敾绗�
+ private Paint circlePaint;//鍦嗗舰杩涘害妗嗙敾绗�
+ private Paint wavePaint;//缁樺埗娉㈡氮鐢荤瑪
+ private Path wavePath;//缁樺埗娉㈡氮Path
+ private Paint mTextPaint; //杩涘害鏂囧瓧鏄剧ず鍐呭
+// private Paint secondWavePaint;//缁樺埗绗簩涓尝娴殑鐢荤瑪
+ private Bitmap bitmap;//缂撳瓨bitmap
+ private Canvas bitmapCanvas;
+
+ private float waveWidth;//娉㈡氮瀹藉害
+ private float waveHeight;//娉㈡氮楂樺害
+ private int waveNum;//娉㈡氮缁勭殑鏁伴噺锛堜竴娆¤捣浼忎负涓�缁勶級
+ private float waveMovingDistance;//娉㈡氮骞崇Щ鐨勮窛绂�
+
+ private float defaultSize;//鑷畾涔塚iew榛樿鐨勫楂�
+ private float mPercent;//杩涘害鏉″崰姣�
+ private int mProgress;//鍙互鏇存柊鐨勮繘搴︽潯鏁板��
+
+// private int waveColor;//娉㈡氮棰滆壊
+// private int secondWaveColor;//绗簩灞傛尝娴鑹�
+ private int bgColor;//鑳屾櫙杩涘害棰滆壊
+
+ private int mBorderColor; //鑳屾櫙杈规妗嗛鑹�
+ private float mBorderWidth; //鑳屾櫙杈规妗嗗搴�
+ private int mPadding = 10;
+
+ private boolean isClickable = true;
+
+ private float mSeekBarWidth;
+ private float mSeekBarHeight;
+
+ private float mWaveViewWidth;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勫
+ private float mWaveViewHeight;//閲嶆柊娴嬮噺鍚嶸iew瀹為檯鐨勯珮
+
+ private int mMaxValue; // 鏈�澶ф暟鍊�
+ private int mMinValue; // 鏈�灏忔暟鍊�
+ private float mCenterX; // 鍦嗗姬 SeekBar 涓績鐐� X
+ private float mCenterY; // 鍦嗗姬 SeekBar 涓績鐐� Y
+ private String mProgressBarUnitSring; //杩涘害鍗曚綅绗﹀彿
+ private static final String DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING = "%"; // 榛樿鏄剧ず鍗曚綅
+ private float mWaveLeftAndTop,mWaveRight,mWaveBottom;
+ private float mBorderLeftAndTop;
+ private boolean isProgressTextShow = true;
+
+ private int mCornerRadius; //鍦嗚鍗婂緞澶у皬
+
+ private boolean isDrawSecondWave;
+ private float nowY;
+ private int[] mArcProgressBarColors; // 褰撳墠杩涘害娓愬彉棰滆壊鏁扮粍
+
+
+ public HDLWaveSeekBar(Context context) {
+ this(context, null);
+ }
+
+ public HDLWaveSeekBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public HDLWaveSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setSaveEnabled(true);
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+ initAttrs(context, attrs);
+ initData();
+ initPaint();
+ }
+
+ private void initData() {
+ defaultSize = dp2px(100);
+ mBorderWidth = dp2px(2);
+ mPadding = dp2px(10);
+ waveNum =(int) Math.ceil(Double.parseDouble(String.valueOf(defaultSize / waveWidth / 2)));
+ waveMovingDistance = 0;
+ mPercent = 0.0f;
+ mProgress = 0;
+ isDrawSecondWave = false;
+ mMaxValue = 100;
+ mMinValue = 0;
+ mCornerRadius = dp2px(10);
+ mProgressBarUnitSring = DEFAULT_ARC_PROGRESS_BAR_UNIT_STRING;
+ isProgressTextShow = true;
+ mArcProgressBarColors = new int[]{DEFAULT_WAVE_COLOR,DEFAULT_WAVE_END_COLOR};
+ }
+
+ private void initPaint() {
+ wavePath = new Path();
+ wavePaint = new Paint();
+ wavePaint.setColor(DEFAULT_WAVE_COLOR);
+ wavePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ wavePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+// secondWavePaint = new Paint();
+// secondWavePaint.setColor(secondWaveColor);
+// secondWavePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+// secondWavePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));//鍥犱负瑕佽鐩栧湪绗竴灞傛尝娴笂锛屼笖瑕佽鍗婇�忔槑鐢熸晥锛屾墍浠ラ�夋妯″紡
+
+ circlePaint = new Paint();
+ circlePaint.setColor(bgColor);
+ circlePaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+
+ mBorderPaint = new Paint();
+ mBorderPaint.setStyle(Paint.Style.STROKE);
+ mBorderPaint.setColor(mBorderColor);
+ mBorderPaint.setAntiAlias(true);//璁剧疆鎶楅敮榻�
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+ initTextPanit();
+ }
+
+ // 鍒濆鍖栨嫋鍔ㄦ寜閽《閮ㄦ枃瀛楃敾绗斿拰杩涘害鍦嗗姬鐢荤瑪
+ private void initTextPanit() {
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setStrokeWidth(1);
+ mTextPaint.setTextSize(getTextSizeDip(20));
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+// public HDLWaveSeekBar(Context context, @Nullable AttributeSet attrs) {
+// super(context, attrs);
+// init(context,attrs);
+// }
+
+ private void initAttrs(Context context,AttributeSet attrs){
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HDLWaveSeekBar);
+ waveWidth = typedArray.getDimension(R.styleable.HDLWaveSeekBar_wave_width, dp2px(80));
+ waveHeight = typedArray.getDimension(R.styleable.HDLWaveSeekBar_wave_height,dp2px(15));
+// waveColor = typedArray.getColor(R.styleable.HDLWaveSeekBar_wave_color, DEFAULT_WAVE_COLOR);
+// secondWaveColor = typedArray.getColor(R.styleable.HDLWaveSeekBar_second_wave_color,getResources().getColor(R.color.light));
+ bgColor = typedArray.getColor(R.styleable.HDLWaveSeekBar_wave_bg_color,Color.WHITE);
+ mBorderColor = typedArray.getColor(R.styleable.HDLWaveSeekBar_wave_border_color, DEFAULT_WAVE_BORDER_COLOR);
+
+ typedArray.recycle();
+ }
+
+ private int dp2px(int dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
+ }
+
+ private float getTextSizeDip(float value) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
+ }
+
+
+ private void onWaveSizeChange(){
+ mWaveViewWidth = mSeekBarWidth - mPadding*4 - mBorderWidth*2;
+ mWaveViewHeight = mSeekBarHeight - mPadding*4 - mBorderWidth*2;
+ mWaveLeftAndTop = mPadding*2 + mBorderWidth;
+
+ mWaveRight = mSeekBarWidth - mPadding*2 - mBorderWidth;
+ mWaveBottom = mSeekBarHeight - mPadding*2 - mBorderWidth;
+
+ mBorderLeftAndTop = mPadding + mBorderWidth/2;
+ waveNum = (int) Math.ceil(Double.parseDouble(String.valueOf(mWaveViewWidth / waveWidth / 2)));
+
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int ws = MeasureSpec.getSize(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勭‘鍒囨暟鍊�
+ int wm = MeasureSpec.getMode(widthMeasureSpec); //鍙栧嚭瀹藉害鐨勬祴閲忔ā寮�
+ int hs = MeasureSpec.getSize(heightMeasureSpec); //鍙栧嚭楂樺害鐨勭‘鍒囨暟鍊�
+ int hm = MeasureSpec.getMode(heightMeasureSpec); //鍙栧嚭楂樺害鐨勬祴閲忔ā
+
+ if (wm == MeasureSpec.UNSPECIFIED) {
+ wm = MeasureSpec.EXACTLY;
+ ws = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (wm == MeasureSpec.AT_MOST) {
+ wm = MeasureSpec.EXACTLY;
+ ws = Math.min(dp2px(DEFAULT_EDGE_LENGTH), ws);
+ }
+ if (hm == MeasureSpec.UNSPECIFIED) {
+ hm = MeasureSpec.EXACTLY;
+ hs = dp2px(DEFAULT_EDGE_LENGTH);
+ } else if (hm == MeasureSpec.AT_MOST) {
+ hm = MeasureSpec.EXACTLY;
+ hs = Math.min(dp2px(DEFAULT_EDGE_LENGTH), hs);
+ }
+ setMeasuredDimension(MeasureSpec.makeMeasureSpec(ws, wm), MeasureSpec.makeMeasureSpec(hs, hm));
+
+ mSeekBarHeight = hs;
+ mSeekBarWidth = ws;
+ mCenterX = mSeekBarWidth/2;
+ mCenterY = mSeekBarHeight/2;
+ onWaveSizeChange();
+ }
+
+ private int measureSize(int defaultSize,int measureSpec) {
+ int result = defaultSize;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ if (specMode == MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // 璁$畻鍦ㄥ綋鍓嶅ぇ灏忎笅,鍐呭搴旇鏄剧ず鐨勫ぇ灏忓拰璧峰浣嶇疆
+ int safeW = w - getPaddingLeft() - getPaddingRight();
+ int safeH = h - getPaddingTop() - getPaddingBottom();
+ mSeekBarHeight = safeH;
+ mSeekBarWidth = safeW;
+ mCenterX = mSeekBarWidth/2;
+ mCenterY = mSeekBarHeight/2;
+ onWaveSizeChange();
+ // Log.i("getCurrentProgress ","mSeekBarHeight :Y " + mSeekBarHeight + " mSeekBarWidth:"+mSeekBarWidth);
+ }
+
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.save();
+
+ //鐢诲渾瑙掔煩褰�
+ RectF rectF = new RectF(mBorderLeftAndTop, mBorderLeftAndTop, mSeekBarWidth - mBorderLeftAndTop, mSeekBarHeight-mBorderLeftAndTop);
+ canvas.drawRoundRect(rectF, mCornerRadius, mCornerRadius, mBorderPaint);
+
+// //鐢诲渾瑙掔煩褰�
+// RectF rectF2 = new RectF(10, 10, mWaveViewWidth-20, mWaveViewWidth-20);
+// canvas.drawRoundRect(rectF2, 80, 80, circlePaint);
+// canvas.drawPath(getWavePath(),wavePaint);
+// canvas.restore();
+
+ bitmap = Bitmap.createBitmap((int)mSeekBarWidth, (int)mSeekBarHeight, Bitmap.Config.ARGB_8888);
+ bitmapCanvas = new Canvas(bitmap);
+
+ RectF rectF2 = new RectF(mWaveLeftAndTop, mWaveLeftAndTop, mWaveRight, mWaveBottom);
+ bitmapCanvas.drawRoundRect(rectF2, mCornerRadius, mCornerRadius, circlePaint);
+ resetmArcProgressBarColor();//瀹炵幇娓愬彉鏁堟灉
+// bitmapCanvas.drawCircle(mWaveViewWidth/2, mWaveViewWidth/2, mWaveViewWidth/2, circlePaint);
+ bitmapCanvas.drawPath(getWavePath(), wavePaint);
+// if(isDrawSecondWave){
+// bitmapCanvas.drawPath(getSecondWavePath(),secondWavePaint);
+// }
+
+
+ canvas.drawBitmap(bitmap, 0, 0, null);
+
+ if(isProgressTextShow) {
+ if(mPercent>0.6){
+ mTextPaint.setColor(Color.WHITE);
+ }else {
+ mTextPaint.setColor(Color.BLACK);
+ }
+ canvas.drawText(String.valueOf(getProgress()) + mProgressBarUnitSring, mCenterX, mCenterY, mTextPaint);
+ }
+
+ canvas.restore();
+
+ }
+
+ /**
+ * 閲嶇疆 mArcProgressBarColors 棰滆壊
+ */
+ private void resetmArcProgressBarColor() {
+ LinearGradient gradient = new LinearGradient(mBorderLeftAndTop, mBorderLeftAndTop, mSeekBarWidth - mBorderLeftAndTop, mSeekBarHeight-mBorderLeftAndTop, mArcProgressBarColors, null, Shader.TileMode.MIRROR);
+ wavePaint.setShader(gradient);
+ }
+
+ //--- 鍒濆鍖栫粨鏉� -------------------------------------------------------------------------------
+
+ //--- 鐘舵�佸瓨鍌� ---------------------------------------------------------------------------------
+ private static final String KEY_PROGRESS_PRESENT = "PRESENTWAVE"; // 鐢ㄤ簬瀛樺偍鍜岃幏鍙栧綋鍓嶇櫨鍒嗘瘮
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("superState", super.onSaveInstanceState());
+ bundle.putFloat(KEY_PROGRESS_PRESENT, mProgress);
+ return bundle;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof Bundle) {
+ Bundle bundle = (Bundle) state;
+ this.mProgress = bundle.getInt(KEY_PROGRESS_PRESENT);
+ state = bundle.getParcelable("superState");
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onProgressChanged(this, this.mProgress, false);
+ }
+ super.onRestoreInstanceState(state);
+ }
+
+ //--- 鐘舵�佸瓨鍌ㄧ粨鏉� -----------------------------------------------------------------------------
+
+ private Path getWavePath(){
+// float changeWaveHeight = (1 - mPercent) * waveHeight;
+ float changeWaveHeight = waveHeight;
+ nowY = (1-mPercent)*mWaveViewHeight + mWaveLeftAndTop;
+
+ wavePath.reset();
+
+ //绉诲姩鍒板彸涓婃柟锛屼篃灏辨槸p0鐐�
+ wavePath.moveTo(mWaveRight, nowY);
+ //绉诲姩鍒板彸涓嬫柟锛屼篃灏辨槸p1鐐�
+ wavePath.lineTo(mWaveRight, mWaveBottom);
+ //绉诲姩鍒板乏涓嬭竟锛屼篃灏辨槸p2鐐�
+ wavePath.lineTo(mWaveLeftAndTop, mWaveBottom);
+ //绉诲姩鍒板乏涓婃柟锛屼篃灏辨槸p3鐐�
+ //wavePath.lineTo(0, (1-mPercent)*mWaveViewWidth);
+// wavePath.lineTo(-waveMovingDistance, (1-mPercent)*mSeekBarHeight);
+
+ if(mPercent == 0 || mPercent ==1){
+ wavePath.lineTo(mWaveLeftAndTop, nowY);
+ }else {
+ wavePath.lineTo(-waveMovingDistance, nowY);
+ //浠巔3寮�濮嬪悜p0鏂瑰悜缁樺埗娉㈡氮鏇茬嚎
+ for (int i = 0; i < waveNum * 2; i++) {
+ wavePath.rQuadTo(waveWidth / 2, changeWaveHeight, waveWidth, 0);
+ wavePath.rQuadTo(waveWidth / 2, -changeWaveHeight, waveWidth, 0);
+ }
+ }
+
+ //灏唒ath灏侀棴璧锋潵
+ wavePath.close();
+ return wavePath;
+ }
+
+
+ private boolean mCanDrag = false; // 鏄惁鍏佽鎷栧姩
+ private boolean moved = false; // 鏄惁鍏佽
+ private int lastProgress = -1;
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ if(!isClickable) return false;
+ int action = event.getActionMasked();
+ switch (action) {
+ case ACTION_DOWN:
+ moved = false;
+ judgeCanDrag(event);
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStartTrackingTouch(this);
+ }
+ break;
+ case ACTION_MOVE:
+ if (!mCanDrag) {
+ break;
+ }
+ setCurrentPercent(event);
+ // 浜嬩欢鍥炶皟
+ if (null != mOnProgressChangeListener && mProgress != lastProgress) {
+ mOnProgressChangeListener.onProgressChanged(this, mProgress, true);
+ lastProgress = mProgress;
+ }
+ moved = true;
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ if(!moved){
+ if (isInArcProgress(event.getX(),event.getY())) {
+ setCurrentPercent(event);
+ }
+ }
+ if (null != mOnProgressChangeListener) {
+ mOnProgressChangeListener.onStopTrackingTouch(this);
+ }
+ break;
+ }
+
+ invalidate();
+ return true;
+ }
+
+
+ // 鍒ゆ柇鏄惁鍏佽鎷栧姩
+ private void judgeCanDrag(MotionEvent event) {
+ if(isInArcProgress(event.getX(),event.getY())){
+ mCanDrag = true;
+ }else {
+ mCanDrag = false;
+ }
+ }
+
+ private void setCurrentPercent(MotionEvent event) {
+// Log.i("getCurrentProgress ","getCurrentProgress :Y " + event.getY() + " X:"+event.getX());
+ float progressY = event.getY() - mWaveLeftAndTop;
+ float progress = progressY /mWaveViewHeight;
+ progress = 1 - progress;
+ if (progress < 0) progress = 0;
+ if (progress > 1) progress = 1;
+ mPercent = progress;
+ mProgress = (int) (mPercent * (mMaxValue - mMinValue)) + mMinValue;
+ waveMovingDistance = mPercent * 500;
+// Log.i("getCurrentProgress ","getCurrentProgress :mProgress " + mProgress);
+ }
+
+ private boolean isInArcProgress(float px ,float py) {
+
+ if(px < 0 || px > mSeekBarWidth || py < 0 || py > mSeekBarHeight){
+ return false;
+ }else {
+ return true;
+ }
+ }
+
+
+
+ // endregion -----------------------------------------------------------------------------------
+ // region 鐘舵�佸洖璋� ------------------------------------------------------------------------------
+
+ private HDLWaveSeekBar.OnProgressChangeListener mOnProgressChangeListener;
+
+ public void setOnProgressChangeListener(HDLWaveSeekBar.OnProgressChangeListener onProgressChangeListener) {
+ mOnProgressChangeListener = onProgressChangeListener;
+ }
+
+ public interface OnProgressChangeListener {
+ /**
+ * 杩涘害鍙戠敓鍙樺寲
+ *
+ * @param seekBar 鎷栧姩鏉�
+ * @param progress 褰撳墠杩涘害鏁板��
+ * @param isUser 鏄惁鏄敤鎴锋搷浣�, true 琛ㄧず鐢ㄦ埛鎷栧姩, false 琛ㄧず閫氳繃浠g爜璁剧疆
+ */
+ void onProgressChanged(HDLWaveSeekBar seekBar, int progress, boolean isUser);
+
+ /**
+ * 鐢ㄦ埛寮�濮嬫嫋鍔�
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStartTrackingTouch(HDLWaveSeekBar seekBar);
+
+ /**
+ * 鐢ㄦ埛缁撴潫鎷栧姩
+ *
+ * @param seekBar 鎷栧姩鏉�
+ */
+ void onStopTrackingTouch(HDLWaveSeekBar seekBar);
+ }
+ // endregion -----------------------------------------------------------------------------------
+
+
+ //****************************瀵瑰鎺ュ彛****************************************************
+ /**
+ * 璁剧疆鎺т欢鏄惁鍙敤鐐瑰嚮
+ * @param isClickable
+ */
+ public void setIsClickable(boolean isClickable) {
+ this.isClickable = isClickable;
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(int progress) {
+ System.out.println("setProgress = " + progress);
+ if (progress > mMaxValue) progress = mMaxValue;
+ if (progress < mMinValue) progress = mMinValue;
+ mProgress = progress;
+ mPercent = (progress - mMinValue) * 1.0f / (mMaxValue - mMinValue);
+// System.out.println("setProgress present = " + progress);
+// if (null != mOnProgressChangeListener) {
+// mOnProgressChangeListener.onProgressChanged(this, progress, false);
+// }
+ postInvalidate();
+
+ }
+
+ /**
+ * 杩涘害鏂囧瓧澶у皬
+ * @param textSize
+ */
+ public void setProgressTextSize(int textSize){
+ mTextPaint.setTextSize(getTextSizeDip(textSize));
+ }
+
+ /**
+ * 杩涘害鏂囧瓧棰滆壊
+ * @param textPaintColor
+ */
+ public void setProgressTextColor(int textPaintColor){
+ mTextPaint.setColor(textPaintColor);
+ }
+
+ /**
+ * 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+ *
+ * @param progressBarUnitSring 杩涘害鏄剧ず鍊煎崟浣�
+ */
+ public void setProgressBarUnitSring(String progressBarUnitSring) {
+ mProgressBarUnitSring = progressBarUnitSring;
+ }
+
+ /**
+ * 璁剧疆鏈�澶ф暟鍊�
+ *
+ * @param max 鏈�澶ф暟鍊�
+ */
+ public void setMaxValue(int max) {
+ mMaxValue = max;
+ }
+
+ /**
+ * 璁剧疆鏈�灏忔暟鍊�
+ *
+ * @param min 鏈�灏忔暟鍊�
+ */
+ public void setMinValue(int min) {
+ mMinValue = min;
+ }
+
+ public void setBorderWidth(int borderWidth) {
+// mBorderWidth = dp2px(borderWidth);
+ mBorderWidth = borderWidth;
+ mBorderPaint.setStrokeWidth(mBorderWidth);
+ onWaveSizeChange();
+ postInvalidate();
+ }
+
+//
+// public void setWaveColor(int mWaveColor){
+// waveColor = mWaveColor;
+// wavePaint.setColor(waveColor);
+//
+// }
+
+ /**
+ * 璁剧疆棰滆壊
+ * 3涓鑹� 娓愬彉鏁堟灉
+ * @param colors 棰滆壊
+ */
+ public void setProgressBarColors(int[] colors) {
+ if(colors.length < 2) return;
+ mArcProgressBarColors = colors;
+ resetmArcProgressBarColor();
+ postInvalidate();
+ }
+
+ /**
+ * 璁剧疆棰滆壊 鍗曠棰滆壊
+ * @param colors 棰滆壊
+ */
+ public void setProgressBarColor(int colors) {
+ int[] colorsArray = new int[]{colors, colors};
+ mArcProgressBarColors = colorsArray;
+ resetmArcProgressBarColor();
+ postInvalidate();
+ }
+
+ public void setWaveBorderColor(int mmBorderColor){
+ mBorderColor = mmBorderColor;
+ mBorderPaint.setColor(mBorderColor);
+ }
+
+ public void setWaveBgColor(int mBgColor){
+ bgColor = mBgColor;
+ circlePaint.setColor(bgColor);
+ }
+
+ public void setWavePadding(int mmPadding){
+// mPadding = dp2px(mmPadding);
+ mPadding = mmPadding;
+ onWaveSizeChange();
+ }
+
+ public void setCornerRadius(int mmCornerRadius){
+// mCornerRadius = dp2px(mmCornerRadius);
+ mCornerRadius = mmCornerRadius;
+ }
+
+ public void setProgressTextShow(boolean progressTextShow) {
+ isProgressTextShow = progressTextShow;
+ }
+
+ /**
+ *褰撳墠 杩涘害Y鍧愭爣
+ */
+ public float getProgressY() {
+ return nowY;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CheckPermissionsCropImageActivity.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CheckPermissionsCropImageActivity.java
new file mode 100644
index 0000000..d821ca4
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CheckPermissionsCropImageActivity.java
@@ -0,0 +1,199 @@
+package com.hdl.widget.cropimage;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import android.os.Bundle;
+import android.view.KeyEvent;
+
+import com.hdl.widgetxm.R;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class CheckPermissionsCropImageActivity extends Activity {
+
+
+ /**
+ * 闇�瑕佽繘琛屾娴嬬殑鏉冮檺鏁扮粍
+ */
+
+ protected String[] needPermissions = {
+ Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE
+ };
+
+ private static final int PERMISSON_REQUESTCODE = 66;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if(Build.VERSION.SDK_INT > 28
+ && getApplicationContext().getApplicationInfo().targetSdkVersion > 28) {
+// needPermissions = new String[] {
+// Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE
+// };
+ }
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁闇�瑕佹娴嬶紝闃叉涓嶅仠鐨勫脊妗�
+ */
+ private boolean isNeedCheck = true;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (Build.VERSION.SDK_INT >= 23
+ && getApplicationInfo().targetSdkVersion >= 23) {
+ if (isNeedCheck) {
+ checkPermissions(needPermissions);
+ }
+ }
+ }
+
+ /**
+ *
+ * @param permissions
+ * @since 2.5.0
+ *
+ */
+ private void checkPermissions(String... permissions) {
+ try {
+ if (Build.VERSION.SDK_INT >= 23
+ && getApplicationInfo().targetSdkVersion >= 23) {
+ List<String> needRequestPermissonList = findDeniedPermissions(permissions);
+ if (null != needRequestPermissonList
+ && needRequestPermissonList.size() > 0) {
+ String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
+ Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class,
+ int.class});
+
+ method.invoke(this, array, PERMISSON_REQUESTCODE);
+ }
+ }
+ } catch (Throwable e) {
+ }
+ }
+
+ /**
+ * 鑾峰彇鏉冮檺闆嗕腑闇�瑕佺敵璇锋潈闄愮殑鍒楄〃
+ *
+ * @param permissions
+ * @return
+ * @since 2.5.0
+ *
+ */
+ private List<String> findDeniedPermissions(String[] permissions) {
+ List<String> needRequestPermissonList = new ArrayList<String>();
+ if (Build.VERSION.SDK_INT >= 23
+ && getApplicationInfo().targetSdkVersion >= 23){
+ try {
+ for (String perm : permissions) {
+ Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
+ Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
+ String.class);
+ if ((Integer)checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
+ || (Boolean)shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {
+
+ needRequestPermissonList.add(perm);
+ }
+ }
+ } catch (Throwable e) {
+
+ }
+ }
+ return needRequestPermissonList;
+ }
+
+ /**
+ * 妫�娴嬫槸鍚︽墍鏈夌殑鏉冮檺閮藉凡缁忔巿鏉�
+ * @param grantResults
+ * @return
+ * @since 2.5.0
+ *
+ */
+ private boolean verifyPermissions(int[] grantResults) {
+ for (int result : grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @TargetApi(23)
+ public void onRequestPermissionsResult(int requestCode,
+ String[] permissions, int[] paramArrayOfInt) {
+ if (requestCode == PERMISSON_REQUESTCODE) {
+ if (!verifyPermissions(paramArrayOfInt)) {
+ showMissingPermissionDialog();
+ isNeedCheck = false;
+ }
+ }
+ }
+
+ /**
+ * 鏄剧ず鎻愮ず淇℃伅
+ *
+ * @since 2.5.0
+ *
+ */
+ private void showMissingPermissionDialog() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.gd_notifyTitle);
+ builder.setMessage(R.string.gd_notifyMsg);
+
+ // 鎷掔粷, 閫�鍑哄簲鐢�
+ builder.setNegativeButton(R.string.gd_cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+
+ builder.setPositiveButton(R.string.gd_setting,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ startAppSettings();
+ }
+ });
+
+ builder.setCancelable(false);
+
+ builder.show();
+ }
+
+ /**
+ * 鍚姩搴旂敤鐨勮缃�
+ *
+ * @since 2.5.0
+ *
+ */
+ private void startAppSettings() {
+ Intent intent = new Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.parse("package:" + getPackageName()));
+ startActivity(intent);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if(keyCode == KeyEvent.KEYCODE_BACK){
+ this.finish();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CropImageBean.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CropImageBean.java
new file mode 100644
index 0000000..f781309
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/CropImageBean.java
@@ -0,0 +1,55 @@
+package com.hdl.widget.cropimage;
+
+import java.io.Serializable;
+
+/**
+ * Created by JLChen on 2019/10/31
+ */
+public class CropImageBean implements Serializable {
+
+ private int mTypeID = 101;
+ private String mPictureName = "hdl_headPicture";
+ private int mRATIO_X = 1;
+ private int mRATIO_Y = 1;
+ private int mOutputY = 300;
+
+ public int getTypeID() {
+ return mTypeID;
+ }
+
+ public void setTypeID(int typeID) {
+ mTypeID = typeID;
+ }
+
+ public String getPictureName() {
+ return mPictureName;
+ }
+
+ public void setPictureName(String pictureName) {
+ mPictureName = pictureName;
+ }
+
+ public int getRATIO_X() {
+ return mRATIO_X;
+ }
+
+ public void setRATIO_X(int RATIO_X) {
+ mRATIO_X = RATIO_X;
+ }
+
+ public int getRATIO_Y() {
+ return mRATIO_Y;
+ }
+
+ public void setRATIO_Y(int RATIO_Y) {
+ mRATIO_Y = RATIO_Y;
+ }
+
+ public int getOutputY() {
+ return mOutputY;
+ }
+
+ public void setOutputY(int outputY) {
+ mOutputY = outputY;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/HDLCropImageActivity.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/HDLCropImageActivity.java
new file mode 100644
index 0000000..954572d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/cropimage/HDLCropImageActivity.java
@@ -0,0 +1,377 @@
+package com.hdl.widget.cropimage;
+
+
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.support.v4.content.FileProvider;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.view.Window;
+import android.view.WindowManager;
+import com.hdl.widget.HDLUtlisXM;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Locale;
+
+
+
+
+public class HDLCropImageActivity extends CheckPermissionsCropImageActivity {
+
+
+ private static final int ACTION_TYPE_PHOTO = 0;
+ private final int CAMERA = 101;
+ private final int ALBUM = 102;
+ private final int CUPREQUEST = 103;
+
+ private String mPicturePath = "hdl_headPicture";
+ private File mOutImage;
+ private Uri mImageUri;
+ private Uri mUritempFile;
+// private Bitmap imageBitmap;
+ private String mCropPicturePath;
+ private String mPictureName = "hdl_headPicture";
+ private int mRATIO_X = 1;
+ private int mRATIO_Y = 1;
+ private int mOutputY = 200;
+
+
+ public interface OnCropImageeCallback {
+ void OnSaveCallback(String picturePath);
+ }
+ /**
+ * 2.鎺ュ彛瀹炵幇鍥炶皟
+ */
+ public static OnCropImageeCallback mOnCropImageeCallback;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+// setContentView(R.layout.hdl_widget_activity_crop_image);
+
+// Bundle mExtras = getIntent().getExtras();
+// if(mExtras != null) {
+// CropImageBean mCropImageBean = (CropImageBean) getIntent().getSerializableExtra("CropImageBean");
+// if(mCropImageBean != null){
+// type = mCropImageBean.getTypeID();
+// String mmPictureName = mCropImageBean.getPictureName();
+// if(!TextUtils.isEmpty(mmPictureName)){
+// mPictureName = mmPictureName;
+// }
+// mRATIO_X = mCropImageBean.getRATIO_X();
+// mRATIO_Y = mCropImageBean.getRATIO_Y();
+// mOutputY = mCropImageBean.getOutputY();
+// if(mRATIO_X <= 0){
+// mRATIO_X = 1;
+// }
+// if(mRATIO_Y <= 0){
+// mRATIO_Y = 1;
+// }
+// if(mOutputY <= 0 || mOutputY > 400){
+// mRATIO_Y = 300;
+// }
+//
+// }
+// }
+
+
+
+ Bundle extras = getIntent().getExtras();
+ int type = 0;
+ if(extras != null){
+ type = extras.getInt(HDLUtlisXM.CROP_TYPE_KEY);
+ String mmPictureName = extras.getString(HDLUtlisXM.CROP_NAME_KEY);
+ if(!TextUtils.isEmpty(mmPictureName)){
+ mPictureName = mmPictureName;
+ }
+ mRATIO_X = extras.getInt(HDLUtlisXM.CROP_RATIO_X_KEY);
+ mRATIO_Y = extras.getInt(HDLUtlisXM.CROP_RATIO_Y_KEY);
+ mOutputY = extras.getInt(HDLUtlisXM.CROP_OUTPUT_Y_KEY);
+ if(mRATIO_X <= 0){
+ mRATIO_X = 1;
+ }
+ if(mRATIO_Y <= 0){
+ mRATIO_Y = 1;
+ }
+ if(mOutputY <= 0 || mOutputY > 200){
+ mOutputY = 200;
+ }
+
+ }
+
+
+
+
+ if(type == CAMERA){
+ setMobilePhones();
+ }else {
+ setLocalPhoto();
+ }
+
+
+
+ }
+
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (null != mOnCropImageeCallback) {
+ mOnCropImageeCallback = null;
+ }
+ }
+
+ /**
+ * 鐩稿唽
+ */
+ private void setLocalPhoto() {
+ Intent albumIntent = new Intent(Intent.ACTION_PICK, null);
+ albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
+ startActivityForResult(albumIntent, ALBUM);
+ }
+
+ /**
+ * 鎷嶇収
+ */
+ private void setMobilePhones() {
+ //鑾峰緱椤圭洰缂撳瓨璺緞
+ String sdPath = getExternalCacheDir().getPath();
+ //鏍规嵁鏃堕棿闅忔満鐢熸垚鍥剧墖鍚�
+ String photoName = new DateFormat().format("yyyyMMddhhmmss",
+ Calendar.getInstance(Locale.CHINA)) + ".jpg";
+ mPicturePath = sdPath + "/" + photoName;
+ mOutImage = new File(mPicturePath);
+ //濡傛灉鏄�7.0浠ヤ笂 閭d箞灏辨妸uir鍖呰
+ if (Build.VERSION.SDK_INT >= 24) {
+ mImageUri = FileProvider.getUriForFile(this, HDLUtlisXM.MAuthority_NAME , mOutImage);
+ } else {
+ //鍚﹀垯灏辩敤鑰佺郴缁熺殑榛樿妯″紡
+ mImageUri = Uri.fromFile(mOutImage);
+ }
+ //鍚姩鐩告満
+ Intent intent = new Intent();
+ intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
+ startActivityForResult(intent, CAMERA);
+ }
+
+
+ /**
+ * 閫夋嫨鍥剧墖鍚庣殑鍥炶皟
+ *
+ * @param requestCode
+ * @param resultCode
+ * @param data
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ finishActivity();
+ return;
+ }
+ switch (requestCode) {
+
+ // 瑁佸壀鐩告満鐓х墖
+ case CAMERA:
+ setCropPhoto();
+ break;
+ //瑁佸壀鏈湴鐩稿唽
+ case ALBUM:
+ Uri data1 = data.getData();
+ if (data1 != null) {
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
+ mPicturePath = data1.toString();
+ } else {
+ mPicturePath = data1.getPath();
+ }
+ // Uri --> Path
+ if (mPicturePath.contains("content://")) {
+ mPicturePath = getFilePathFromContentUri(data1, getContentResolver());
+ }
+ mOutImage = new File(mPicturePath);
+ setCropPhoto();
+ }else {
+ finishActivity();
+ }
+ break;
+
+ //瑁佸壀瀹屾垚
+ case CUPREQUEST:
+ if (data == null) {
+ finishActivity();
+ return;
+ }
+ Bundle extras = data.getExtras();
+
+ if (Build.MANUFACTURER.contains("Xiaomi")) {
+ if (mUritempFile != null) {
+ mCropPicturePath = mUritempFile.getPath();
+ } else {
+ mCropPicturePath = "";
+ }
+ } else {
+ if (extras != null) {
+ Bitmap photo = extras.getParcelable("data");
+ mCropPicturePath = saveImage(mPictureName ,photo);
+ } else {
+ mCropPicturePath = "";
+ }
+ }
+
+ finishActivity();
+// if (!TextUtils.isEmpty(mCropPicturePath)) {
+// imageBitmap = BitmapFactory.decodeFile(s);
+// }
+ break;
+ default:
+ finishActivity();
+ break;
+ }
+ }
+
+ private void setCropPhoto() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ //濡傛灉鏄�7.0鍓鍥剧墖 鍚岀悊 闇�瑕佹妸uri鍖呰
+ //閫氳繃FileProvider鍒涘缓涓�涓猚ontent绫诲瀷鐨刄ri
+ Uri inputUri = FileProvider.getUriForFile(this,
+ HDLUtlisXM.MAuthority_NAME , mOutImage);
+
+ startPhotoZoom(inputUri);//璁剧疆杈撳叆绫诲瀷
+ } else {
+ Uri inputUri = Uri.fromFile(mOutImage);
+ startPhotoZoom(inputUri);
+ }
+ }
+
+ //瑁佸壀
+ private void startPhotoZoom(Uri uri) {
+ Intent intent = new Intent("com.android.camera.action.CROP");
+ intent.setDataAndType(uri, "image/*");
+ //sdk>=24
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ //鍘婚櫎榛樿鐨勪汉鑴歌瘑鍒紝鍚﹀垯鍜屽壀瑁佸尅閲嶅彔
+ intent.putExtra("noFaceDetection", false);
+
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ }
+ // 璁剧疆瑁佸壀
+ intent.putExtra("crop", "true");
+ // aspectX aspectY 瀹介珮鐨勬瘮渚�
+ //鍗庝负鐗规畩澶勭悊 涓嶇劧浼氭樉绀哄渾
+ if (Build.MANUFACTURER.contains("HUAWEI")) {
+ if(mRATIO_X == mRATIO_Y) {
+ intent.putExtra("aspectX", 9998);
+ intent.putExtra("aspectY", 9999);
+ }else {
+ intent.putExtra("aspectX", mRATIO_X);
+ intent.putExtra("aspectY", mRATIO_Y);
+ }
+ } else {
+ intent.putExtra("aspectX", mRATIO_X);
+ intent.putExtra("aspectY", mRATIO_Y);
+ }
+ // outputX outputY 鏄鍓浘鐗囧楂�
+ float mRATIO = ((float)mRATIO_X) /((float)mRATIO_Y);
+ int outputX = (int)((float)mOutputY * mRATIO);
+ intent.putExtra("outputX",outputX);
+ intent.putExtra("outputY", mOutputY);
+ //miui绯荤粺 鐗规畩澶勭悊 return-data鐨勬柟寮忓彧閫傜敤浜庡皬鍥俱��
+ if (Build.MANUFACTURER.contains("Xiaomi")) { //瑁佸壀鍚庣殑鍥剧墖Uri璺緞锛宮UritempFile涓篣ri绫诲彉閲�
+ mUritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + mPictureName + ".jpg");
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, mUritempFile);
+ } else {
+ intent.putExtra("return-data", true);
+ }
+ intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
+ startActivityForResult(intent, CUPREQUEST);
+
+
+//
+// Intent intent = new Intent("com.android.camera.action.CROP");
+// intent.setDataAndType(uri, "image/*");
+// intent.putExtra("crop", "true");
+// intent.putExtra("aspectX", 1);
+// intent.putExtra("aspectY", 1);
+// intent.putExtra("outputX", 300);
+// intent.putExtra("outputY", 300);
+// intent.putExtra("scale", true);
+// // intent.putExtra("return-data", false);
+// intent.putExtra("return-data", true);
+// intent.putExtra(MediaStore.EXTRA_OUTPUT, mUritempFile);
+// intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
+// intent.putExtra("noFaceDetection", true); // no face detection
+// startActivityForResult(intent, CROP_REQUEST_CODE);
+ }
+
+ /**
+ * Gets the corresponding path to a file from the given content:// URI
+ * @param selectedVideoUri The content:// URI to find the file path from
+ * @param contentResolver The content resolver to use to perform the query.
+ * @return the file path as a string
+ */
+ public static String getFilePathFromContentUri(Uri selectedVideoUri,
+ ContentResolver contentResolver) {
+ String filePath;
+ String[] filePathColumn = {MediaStore.MediaColumns.DATA};
+
+ Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
+// 涔熷彲鐢ㄤ笅闈㈢殑鏂规硶鎷垮埌cursor
+// Cursor cursor = this.context.managedQuery(selectedVideoUri, filePathColumn, null, null, null);
+
+ cursor.moveToFirst();
+
+ int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
+ filePath = cursor.getString(columnIndex);
+ cursor.close();
+ return filePath;
+ }
+
+
+ public String saveImage(String name, Bitmap bmp) {
+ File appDir = new File(Environment.getExternalStorageDirectory().getPath());
+ if (!appDir.exists()) {
+ appDir.mkdir();
+ }
+ String fileName = name + ".png";
+ File file = new File(appDir, fileName);
+// uploadHeadPic(file);
+
+ try {
+ FileOutputStream fos = new FileOutputStream(file);
+ bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+ fos.flush();
+ fos.close();
+
+// uploadHeadPic(file);
+ return file.getAbsolutePath();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+
+ private void finishActivity(){
+ if (null != mOnCropImageeCallback) {
+ mOnCropImageeCallback.OnSaveCallback(mCropPicturePath);
+ }
+ finish();
+ }
+
+}
+
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/GestureLockView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/GestureLockView.java
new file mode 100644
index 0000000..79a66b2
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/GestureLockView.java
@@ -0,0 +1,799 @@
+package com.hdl.widget.gesturelock;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import com.hdl.widget.HDLUtlisXM;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by JLChen on 2019/10/30
+ */
+public class GestureLockView extends RelativeLayout {
+
+ private static final String TAG = "GestureLockView";
+ public static int DEFAULT_SELECT_COLOR = 0xFFFC744B; //閫変腑棰滆壊
+ public static int DEFAULT_BORDER_COLOR = 0xFF818181; //杈规
+// public static int DEFAULT_BACK_TRUE_COLOR = 0x20FC744B; //鎶捣姝g‘鑳屾櫙棰滆壊
+// public static int DEFAULT_BACK_FALSE_COLOR = 0xFFEDACA7; //鎶捣閿欒鑳屾櫙棰滆壊
+ public static int DEFAULT_SELECT_FALSE_COLOR = 0xFFFF0000; //閿欒绾㈤鑹�
+
+ //妯″紡閫夋嫨锛岄噸缃瘑鐮侊紝璁剧疆瀵嗙爜妯″紡
+ public static final int RESET_MODE = 0;
+ //楠岃瘉瀵嗙爜妯″紡
+ public static final int VERIFY_MODE = 1;
+
+ // 鍏充簬LockView鐨勮竟闀匡紙n*n锛夛細 n * mLockViewWidth + ( n + 1 ) * mLockViewMargin = mWidth
+ private int mLockViewWidth = 0;
+ //mLockViewWidth * 0.25
+ private int mLockViewMargin = 0;
+ //LockView鏁扮粍
+ private ArrayList<ILockView> mILockViews = new ArrayList<>(1);
+
+ private LockViewFactory mLockViewFactory = null;
+
+ //x*x鐨勬墜鍔胯В閿�
+ private int mDotCount = 3;
+
+ //鐢荤瑪
+ private Paint mPaint;
+ //璺緞
+ private Path mPath;
+ //杩炴帴绾跨殑瀹藉害
+ private float mStrokeWidth = 2;
+ //鎵嬫寚瑙︽懜鏄紝path棰滆壊
+ private int mFingerTouchColor = DEFAULT_SELECT_COLOR;
+ //鎵嬫寚鎶捣鏃�,瀵嗙爜鍖归厤path棰滆壊
+ private int mFingerUpMatchedColor = DEFAULT_SELECT_COLOR;
+ //鎵嬫寚鎶捣鏃�,瀵嗙爜涓嶅尮閰峱ath棰滆壊
+ private int mFingerUpUnmatchedColor = DEFAULT_SELECT_FALSE_COLOR;
+
+ //path涓婁竴娆oveTo鍒扮殑鐐瑰潗鏍�
+ private float mLastPathX = 0;
+ private float mLastPathY = 0;
+
+ //鎸囧紩绾跨殑缁堢偣鍧愭爣
+ private float mLineX = 0;
+ private float mLineY = 0;
+
+ //淇濆瓨閫変腑鐨凩ockView id
+ private ArrayList<Integer> mChooseList = new ArrayList<>(1);
+ //绛旀list
+ private ArrayList<Integer> mAnswerList = new ArrayList<>(1);
+
+ //鏄惁鍙互瑙︽懜
+ private boolean mTouchable = true;
+
+// //鍏佽鐨勫皾璇曟鏁�
+// private int mTryTimes = 5;
+// //淇濆瓨鐨勫皾璇曟鏁帮紝鍥犱负妯″紡鍒囨崲鐨勬椂鍊橳ryTimes鍙兘涓嶇瓑浜庡垵濮嬭缃殑鍊�
+// private int mSavedTryTimes = 5;
+
+ private OnLockVerifyListener mOnLockVerifyListener;
+ private OnLockResetListener mOnLockResetListener;
+
+ //褰撳墠妯″紡
+ private int mCurrentMode = VERIFY_MODE;
+ //RESET_MODE涓嬫渶灏戣繛鎺ユ暟
+ private int mMinCount = 3;
+
+ private int resetDelayMillis = 300;
+
+ public GestureLockView(Context context) {
+ this(context, null);
+ }
+
+ public GestureLockView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ private void init(final Context context) {
+ if (mLockViewFactory == null) {
+ setLockView(new LockViewFactory() {
+ @Override
+ public ILockView newLockView() {
+ return new QQLockView(context);
+ }
+ });
+ }
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(context, mStrokeWidth));
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setStrokeJoin(Paint.Join.ROUND);
+
+ mPath = new Path();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ width = width > height ? height : width;
+
+ mLockViewWidth = (int) (4 * width * 1.0f / (5 * mDotCount + 1));
+ //璁$畻LockView鐨勯棿璺�
+ mLockViewMargin = (int) (mLockViewWidth * 0.25);
+
+ if (mLockViewFactory != null) {
+ setLockViewParams(mLockViewFactory);
+ }
+ }
+
+ /**
+ * 璁剧疆LockView鐨勫弬鏁板苟娣诲姞鍒板竷灞�涓�
+ *
+ * @param lockViewFactory
+ */
+ private void setLockViewParams(LockViewFactory lockViewFactory) {
+ if (mILockViews.size() > 0) {
+ return;
+ }
+ for (int i = 0; i < mDotCount * mDotCount; i++) {
+ ILockView iLockView = lockViewFactory.newLockView();
+ iLockView.getView().setId(i + 1);
+ mILockViews.add(iLockView);
+ RelativeLayout.LayoutParams lockerParams = new LayoutParams(mLockViewWidth, mLockViewWidth);
+
+ //涓嶆槸姣忚鐨勭涓�涓紝鍒欒缃綅缃负鍓嶄竴涓殑鍙宠竟
+ if (i % mDotCount != 0) {
+ lockerParams.addRule(RelativeLayout.RIGHT_OF, mILockViews.get(i - 1).getView().getId());
+ }
+ //浠庣浜岃寮�濮嬶紝璁剧疆涓轰笂涓�琛屽悓涓�浣嶇疆View鐨勪笅闈�
+ if (i > mDotCount - 1) {
+ lockerParams.addRule(RelativeLayout.BELOW, mILockViews.get(i - mDotCount).getView().getId());
+ }
+
+ //璁剧疆鍙充笅宸︿笂鐨勮竟璺�
+ int rightMargin = mLockViewMargin;
+ int bottomMargin = mLockViewMargin;
+ int leftMargin = 0;
+ int topMargin = 0;
+
+ //姣忎釜View閮芥湁鍙冲杈硅窛鍜屽簳澶栬竟璺� 绗竴琛岀殑鏈変笂澶栬竟璺� 绗竴鍒楃殑鏈夊乏澶栬竟璺�
+ if (i >= 0 && i < mDotCount) {//绗竴琛�
+ topMargin = mLockViewMargin;
+ }
+
+ if (i % mDotCount == 0) {//绗竴鍒�
+ leftMargin = mLockViewMargin;
+ }
+
+ lockerParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
+ mILockViews.get(i).onNoFinger();
+ mILockViews.get(i).getView().setLayoutParams(lockerParams);
+ addView(mILockViews.get(i).getView());
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ }
+
+ /**
+ * 淇濆瓨鐘舵��
+ *
+ * @return
+ */
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ SavedState ss = new SavedState(superState);
+// ss.tryTimes = mTryTimes;
+ return ss;
+ }
+
+ /**
+ * 鎭㈠鐘舵��
+ *
+ * @param state
+ */
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ SavedState savedState = (SavedState) state;
+ super.onRestoreInstanceState(savedState.getSuperState());
+// mTryTimes = savedState.tryTimes;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mTouchable) {
+ int action = event.getAction();
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ handleDownEvent(x, y);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ handleMoveEvent(x, y);
+ break;
+ case MotionEvent.ACTION_UP:
+ handleUpEvent();
+ break;
+ }
+ invalidate();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 澶勭悊鎸変笅浜嬩欢
+ *
+ * @param x
+ * @param y
+ */
+ private void handleDownEvent(int x, int y) {
+ reset();
+ handleMoveEvent(x, y);
+ }
+
+ /**
+ * 澶勭悊绉诲姩浜嬩欢
+ *
+ * @param x
+ * @param y
+ */
+ private void handleMoveEvent(int x, int y) {
+ mPaint.setColor(mFingerTouchColor);
+ ILockView lockView = getLockViewByPoint(x, y);
+ if (lockView != null) {
+ int childId = lockView.getView().getId();
+ if (!mChooseList.contains(childId)) {
+ mChooseList.add(childId);
+ lockView.onFingerTouch();
+
+ //鎵嬪娍瑙i攣鐩戝惉
+ if (mOnLockVerifyListener != null) {
+ mOnLockVerifyListener.onGestureSelected(childId);
+ }
+
+ mLastPathX = lockView.getView().getLeft() / 2 + lockView.getView().getRight() / 2;
+ mLastPathY = lockView.getView().getTop() / 2 + lockView.getView().getBottom() / 2;
+
+ if (mChooseList.size() == 1) {
+ mPath.moveTo(mLastPathX, mLastPathY);
+ } else {
+ mPath.lineTo(mLastPathX, mLastPathY);
+ }
+ }
+ }
+ //鎸囧紩绾跨粓鐐瑰潗鏍�
+ mLineX = x;
+ mLineY = y;
+ }
+
+ /**
+ * 澶勭悊鎶捣浜嬩欢
+ */
+ private void handleUpEvent() {
+ if (mCurrentMode == RESET_MODE) {
+ handleResetMode();
+ } else {
+ handleVerifyMode();
+ }
+ //灏嗘寚寮曠嚎鐨勭粓鐐瑰潗鏍囪缃负鏈�鍚庝竴涓狿ath鐨勫師鐐癸紝鍗冲彇娑堟寚寮曠嚎
+ mLineX = mLastPathX;
+ mLineY = mLastPathY;
+ }
+
+ /**
+ * 澶勭悊淇敼瀵嗙爜妯″紡
+ */
+ private void handleResetMode() {
+ if (mAnswerList.size() <= 0) {
+ //濡傛灉AnswerList.size()==0鍒欎负绗竴娆¤缃紝楠岃瘉杩炴帴鏁�
+ if (mChooseList.size() < mMinCount) {
+ //杩炴帴鏁颁笉绗�
+ if (mOnLockResetListener != null) {
+ mOnLockResetListener.onConnectCountUnmatched(mChooseList.size(), mMinCount);
+ }
+ toggleLockViewMatchedState(false);
+ return;
+ } else {
+ //杩炴帴鏁扮鍚堬紝灏嗛�夋嫨鐨勭瓟妗堣祴鍊肩粰mAnswerList
+ for (Integer integer : mChooseList) {
+ //鍥犱负mAnswerList鏄粠0寮�濮嬶紝chooseList淇濆瓨鐨勬槸id浠�1寮�濮嬶紝鎵�浠�-1
+ mAnswerList.add(integer - 1);
+ }
+ if (mOnLockResetListener != null) {
+ mOnLockResetListener.onFirstPasswordFinished(mAnswerList);
+ }
+ toggleLockViewMatchedState(true);
+ }
+ } else {
+ //mAnswerList宸叉湁绛旀锛屽垯楠岃瘉瀵嗙爜锛屼袱娆″瘑鐮佸尮閰嶄繚瀛樺瘑鐮�
+ boolean isAnswerRight = checkAnswer();
+ if (isAnswerRight) {
+ //涓ゆ瀵嗙爜姝g‘锛屽洖璋�
+ toggleLockViewMatchedState(true);
+ if (mOnLockResetListener != null) {
+ mOnLockResetListener.onSetPasswordFinished(true, mAnswerList);
+ }
+ } else {
+ //涓ゆ娌″瘑鐮佷笉姝g‘
+ toggleLockViewMatchedState(false);
+ if (mOnLockResetListener != null) {
+ mOnLockResetListener.onSetPasswordFinished(false, new ArrayList<Integer>(1));
+ }
+ }
+ }
+ }
+
+// /**
+// * 澶勭悊楠岃瘉瀵嗙爜妯″紡
+// */
+// private void handleVerifyMode() {
+// mTryTimes--;
+// boolean isAnswerRight = checkAnswer();
+// //鎵嬪娍瑙i攣鐩戝惉
+// if (mOnLockVerifyListener != null) {
+// mOnLockVerifyListener.onGestureFinished(isAnswerRight);
+// if (mTryTimes <= 0) {
+// mOnLockVerifyListener.onGestureTryTimesBoundary();
+// }
+// }
+// if (!isAnswerRight) {
+// toggleLockViewMatchedState(false);
+// } else {
+// toggleLockViewMatchedState(true);
+// }
+//
+//// resetGestureTimer();
+// }
+
+ /**
+ * 澶勭悊楠岃瘉瀵嗙爜妯″紡
+ */
+ private void handleVerifyMode() {
+ //鎵嬪娍瑙i攣鐩戝惉
+ if (mOnLockVerifyListener != null) {
+ mOnLockVerifyListener.onGestureFinished(getAnswer(), mChooseList.size());
+ }
+
+ }
+
+
+ private void resetGestureTimer(){
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ resetGesture();
+ }
+ }, resetDelayMillis);
+ }
+
+ /**
+ * 妫�鏌,y鐐规槸鍚﹀湪LockView涓�
+ *
+ * @param childView
+ * @param x
+ * @param y
+ * @return
+ */
+ private boolean checkPointInChild(View childView, int x, int y) {
+ //璁剧疆浜嗗唴杈硅窛锛屽嵆x,y蹇呴』钀藉叆涓婫estureLockView鐨勫唴閮ㄤ腑闂寸殑灏忓尯鍩熶腑锛屽彲浠ラ�氳繃璋冩暣padding浣垮緱x,y钀藉叆鑼冨洿涓嶅彉澶э紝鎴栬�呬笉璁剧疆padding
+ int padding = (int) (mLockViewWidth * 0.1);
+ if (x >= childView.getLeft() + padding && x <= childView.getRight() - padding
+ && y >= childView.getTop() + padding
+ && y <= childView.getBottom() - padding) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 鍚岃繃x锛寉鐐硅幏鍙朙ockView瀵硅薄
+ *
+ * @param x
+ * @param y
+ * @return
+ */
+ private ILockView getLockViewByPoint(int x, int y) {
+ for (ILockView lockView : mILockViews) {
+ if (checkPointInChild(lockView.getView(), x, y)) {
+ return lockView;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * 閲嶇疆鎵嬪娍瑙i攣
+ */
+ private void reset() {
+ if (mChooseList == null || mPath == null || mILockViews == null) {
+ return;
+ }
+ mChooseList.clear();
+ mPath.reset();
+ for (ILockView iLockView : mILockViews) {
+ iLockView.onNoFinger();
+ }
+ }
+
+ /**
+ * 閲嶇疆鎵嬪娍
+ */
+ public void resetGesture() {
+ reset();
+ invalidate();
+ }
+
+
+ /**
+ * 妫�鏌ョ瓟妗堟槸鍚︽纭�
+ *
+ * @return
+ */
+ private boolean checkAnswer() {
+ if (mAnswerList.size() != mChooseList.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < mAnswerList.size(); i++) {
+ if (mAnswerList.get(i) != mChooseList.get(i) - 1) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * 妫�鏌ョ瓟妗堟槸鍚︽纭�
+ *
+ * @return
+ */
+ private String getAnswer() {
+ String pas = "";
+ if(mChooseList != null) {
+ for (int mChooseId : mChooseList) {
+ pas += mChooseId;
+ }
+ }
+
+ return pas;
+ }
+
+ /**
+ * 鍒囨崲LockView鏄惁鍖归厤鐘舵��
+ *
+ * @param isMatched
+ */
+ private void toggleLockViewMatchedState(boolean isMatched) {
+ if (isMatched) {
+ mPaint.setColor(mFingerUpMatchedColor);
+ } else {
+ mPaint.setColor(mFingerUpUnmatchedColor);
+ }
+ for (ILockView iLockView : mILockViews) {
+ if (mChooseList.contains(iLockView.getView().getId())) {
+ if (!isMatched) {
+ iLockView.onFingerUpUnmatched();
+ } else {
+ iLockView.onFingerUpMatched();
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ //鐢籔ath
+ canvas.drawPath(mPath, mPaint);
+ //鐢绘寚寮曠嚎
+ if (mChooseList.size() > 0) {
+ canvas.drawLine(mLastPathX, mLastPathY, mLineX, mLineY, mPaint);
+ }
+ }
+
+ /**
+ * 璁剧疆LockView
+ *
+ * @param lockViewFactory
+ */
+ public void setLockView(LockViewFactory lockViewFactory) {
+ if (lockViewFactory != null) {
+ removeAllViewsInLayout();
+ mILockViews.clear();
+ mLockViewFactory = lockViewFactory;
+ if (mLockViewWidth > 0) {
+ setLockViewParams(mLockViewFactory);
+ reset();
+ }
+ }
+ }
+
+ /**
+ * 璁剧疆绛旀
+ *
+ * @param answer
+ */
+ public void setAnswer(int... answer) {
+ mAnswerList.clear();
+ for (int i = 0; i < answer.length; i++) {
+ mAnswerList.add(answer[i]);
+ }
+ }
+
+ /**
+ * 灏哠tring绫诲瀷鐨凙nswer璁剧疆鍒發ist
+ * 蹇呴』鏃禠ist鐨則oString褰㈠紡[x,x,x]
+ *
+ * @param answer
+ */
+ public void setAnswer(String answer) {
+ if (answer.startsWith("[") && answer.endsWith("]")) {
+ answer = answer.substring(1, answer.length() - 1);
+ String[] answers = answer.split(",");
+ mAnswerList.clear();
+ for (int i = 0; i < answers.length; i++) {
+ mAnswerList.add(Integer.parseInt(answers[i].trim()));
+ }
+ }
+ }
+
+ /**
+ * 璁剧疆鏄惁鍙互瑙︽懜
+ *
+ * @param touchable
+ */
+ public void setTouchable(boolean touchable) {
+ this.mTouchable = touchable;
+ reset();
+ invalidate();
+ }
+
+ /**
+ * 璁剧疆鎵嬪娍瑙i攣鐩戝惉鍣�
+ *
+ * @param listener
+ */
+ public void setOnLockVerifyListener(OnLockVerifyListener listener) {
+ this.mOnLockVerifyListener = listener;
+ }
+
+ public void setOnLockResetListener(OnLockResetListener listener) {
+ this.mOnLockResetListener = listener;
+ }
+
+ /**
+ * 璁剧疆璺緞瀹藉害
+ *
+ * @param dp
+ */
+ public void setPathWidth(float dp) {
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(getContext(), dp));
+ }
+
+ /**
+ * 璁剧疆姣忚鐐圭殑涓暟
+ *
+ * @param count
+ */
+ public void setDotCount(int count) {
+ this.mDotCount = count;
+ }
+
+ /**
+ * 璁剧疆鎵嬫寚鎸変笅鏃禤ath棰滆壊
+ *
+ * @param color
+ */
+ public void setTouchedPathColor(int color) {
+ this.mFingerTouchColor = color;
+ DEFAULT_SELECT_COLOR = color;
+
+ }
+
+ /**
+ * 璁剧疆姝g‘鏃剁殑棰滆壊
+ *
+ * @param color
+ */
+ public void setTruePathColor(int color) {
+ this.mFingerTouchColor = color;
+ this.mFingerUpMatchedColor = color;
+ DEFAULT_SELECT_COLOR = color;
+ }
+
+ /**
+ * 璁剧疆鎵嬫寚鎶捣鏃讹紝瀵嗙爜鍖归厤棰滆壊
+ *
+ * @param color
+ */
+ public void setMatchedPathColor(int color) {
+ this.mFingerUpMatchedColor = color;
+ DEFAULT_SELECT_COLOR = color;
+ }
+
+ /**
+ * 璁剧疆鎵嬫寚鎶捣鏃讹紝瀵嗙爜涓嶅尮閰嶇殑棰滆壊
+ *
+ * @param color
+ */
+ public void setUnmatchedPathColor(int color) {
+ this.mFingerUpUnmatchedColor = color;
+ DEFAULT_SELECT_FALSE_COLOR = color;
+ }
+
+ /**
+ * 鍒囨崲LockView鏄惁鍖归厤鐘舵��
+ *
+ * @param isMatched
+ */
+ public void setLockViewMatchedState(Boolean isMatched){
+ toggleLockViewMatchedState(isMatched);
+ resetGestureTimer();
+ }
+
+ /**
+ * 璁剧疆閲嶇疆寤舵椂鏃堕棿
+ *
+ * @param resetDelayMillis
+ */
+ public void setResetDelayMillis(int resetDelayMillis) {
+ this.resetDelayMillis = resetDelayMillis;
+ }
+
+ // /**
+// * 璁剧疆鏈�澶у皾璇曟鏁�
+// *
+// * @param tryTimes
+// */
+// public void setTryTimes(int tryTimes) {
+// this.mTryTimes = tryTimes;
+// this.mSavedTryTimes = tryTimes;
+// }
+
+// /**
+// * 鑾峰彇鏈�澶у皾璇曟鏁�
+// *
+// * @return
+// */
+// public int getTryTimes() {
+// return mTryTimes;
+// }
+
+// /**
+// * 璁剧疆瀵嗙爜妯″紡涓嬶紝鏈�灏忚繛鎺ユ暟
+// *
+// * @param minCount
+// */
+// public void setMinCount(int minCount) {
+// this.mMinCount = minCount;
+// }
+
+// public void setMode(int mode) {
+// this.mCurrentMode = mode;
+// reset();
+// //鍒囨崲鍒伴獙璇佹ā寮忕殑鏃跺�欙紝杩樺師鏈�澶у皾璇曟鏁�
+// if (mCurrentMode == VERIFY_MODE) {
+//// mTryTimes = mSavedTryTimes;
+// } else if (mCurrentMode == RESET_MODE) {
+// //娓呴櫎宸叉湁瀵嗙爜鏁版嵁
+// mAnswerList.clear();
+// }
+// }
+
+ public interface OnLockVerifyListener {
+
+ /**
+ * 绉诲姩杩囩▼涓�変腑鐨刬d
+ *
+ * @param id
+ */
+ void onGestureSelected(int id);
+
+// /**
+// * 鎵嬪娍鍔ㄤ綔瀹屾垚
+// *
+// * @param isMatched 鏄惁鍜屽瘑鐮佸尮閰�
+// */
+// void onGestureFinished(boolean isMatched);
+
+
+ /**
+ * 鎵嬪娍鍔ㄤ綔瀹屾垚
+ *
+ * @param selectPassword 閫夋嫨鐨勫瘑鐮�
+ */
+ void onGestureFinished(String selectPassword, int selectCount);
+
+// /**
+// * 瓒呰繃灏濊瘯娆℃暟涓婇檺
+// */
+// void onGestureTryTimesBoundary();
+ }
+
+ public interface OnLockResetListener {
+
+ /**
+ * 杩炴帴鏁颁笉绗�
+ *
+ * @param connectCount
+ * @param minCount
+ */
+ void onConnectCountUnmatched(int connectCount, int minCount);
+
+ /**
+ * 杩炴帴鏁扮鍚堬紝绗竴娆″瘑鐮佽缃垚鍔�
+ *
+ * @param answerList
+ */
+ void onFirstPasswordFinished(List<Integer> answerList);
+
+ /**
+ * 璁剧疆瀵嗙爜鎴愬姛
+ *
+ * @param isMatched 涓ゆ瀵嗙爜鏄惁鍖归厤
+ * @param answerList 瀵嗙爜list
+ */
+ void onSetPasswordFinished(boolean isMatched, List<Integer> answerList);
+ }
+
+ /**
+ * 淇濆瓨鐘舵�乥ean
+ */
+ static class SavedState extends BaseSavedState {
+
+ int tryTimes;
+
+ public SavedState(Parcelable source) {
+ super(source);
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ tryTimes = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeValue(tryTimes);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/ILockView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/ILockView.java
new file mode 100644
index 0000000..4b303b4
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/ILockView.java
@@ -0,0 +1,44 @@
+package com.hdl.widget.gesturelock;
+
+import android.view.View;
+
+/**
+ * Created by zyyoona7 on 2017/7/7.
+ * 鎺ュ彛锛岃嚜瀹氫箟鎵嬪娍瑙i攣鏍峰紡闇�瀹炵幇
+ */
+
+public interface ILockView {
+
+ //鎵嬪娍鐘舵��
+ int NO_FINGER = 0;
+ int FINGER_TOUCH = 1;
+ int FINGER_UP_MATCHED = 2;
+ int FINGER_UP_UN_MATCHED = 3;
+
+ /**
+ * 鑾峰彇View
+ *
+ * @return
+ */
+ View getView();
+
+ /**
+ * 鎵嬫寚娌¤Е鎽镐箣鍓嶏紝鍒濆鐘舵��
+ */
+ void onNoFinger();
+
+ /**
+ * 鎵嬫寚瑙︽懜锛屾寜涓嬬姸鎬�
+ */
+ void onFingerTouch();
+
+ /**
+ * 鎵嬫寚鎶捣锛屾墜鍔垮瘑鐮佸尮閰嶇姸鎬�
+ */
+ void onFingerUpMatched();
+
+ /**
+ * 鎵嬫寚鎶捣锛屾墜鍔垮瘑鐮佷笉鍖归厤鐘舵��
+ */
+ void onFingerUpUnmatched();
+}
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/LockViewFactory.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/LockViewFactory.java
new file mode 100644
index 0000000..6c238cc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/LockViewFactory.java
@@ -0,0 +1,13 @@
+package com.hdl.widget.gesturelock;
+
+/**
+ * LockViewFactory 鍚彂鑷� ThreadPoolExecutor 涓殑 ThreadFactory
+ */
+public interface LockViewFactory {
+
+ /**
+ * 鍒涘缓 LockView,蹇呴』鏄� newInstance 涓嶈兘澶嶇敤涓�涓璞�
+ * @return
+ */
+ ILockView newLockView();
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/QQLockView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/QQLockView.java
new file mode 100644
index 0000000..624d64f
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/gesturelock/QQLockView.java
@@ -0,0 +1,169 @@
+package com.hdl.widget.gesturelock;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.hdl.widget.HDLUtlisXM;
+
+
+/**
+ * Created by JLChen on 2019/10/30
+ * QQ鎵嬪娍瑙i攣鏍峰紡
+ */
+public class QQLockView extends View implements ILockView {
+ private static int DEFAULT_BACK_COLOR = 0x00000000;
+ private Paint mPaint;
+ private int mCurrentState = NO_FINGER;
+ private float mOuterRadius;
+ private float mInnerRadius;
+
+ public QQLockView(Context context) {
+ this(context, null);
+ }
+
+ public QQLockView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ width = width > height ? height : width;
+ setMeasuredDimension(width, width);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ float space = 10;
+ float x = getWidth() / 2;
+ float y = getHeight() / 2;
+ canvas.translate(x, y);
+ mOuterRadius = x - space;
+ mInnerRadius = (x - space) / 3;
+ switch (mCurrentState) {
+ case NO_FINGER:
+ drawNoFinger(canvas);
+ break;
+ case FINGER_TOUCH:
+ drawFingerTouch(canvas);
+ break;
+ case FINGER_UP_MATCHED:
+ drawFingerUpMatched(canvas);
+ break;
+ case FINGER_UP_UN_MATCHED:
+ drawFingerUpUnmatched(canvas);
+ break;
+ }
+ }
+
+ /**
+ * 鐢绘棤鎵嬫寚瑙︽懜鐘舵��
+ *
+ * @param canvas
+ */
+ private void drawNoFinger(Canvas canvas) {
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(GestureLockView.DEFAULT_BORDER_COLOR);
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(getContext(),1));
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ }
+
+ /**
+ * 鐢绘墜鎸囪Е鎽哥姸鎬�
+ *
+ * @param canvas
+ */
+ private void drawFingerTouch(Canvas canvas) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(DEFAULT_BACK_COLOR);
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_COLOR);
+ canvas.drawCircle(0, 0, mInnerRadius, mPaint);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_COLOR);
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(getContext(),1));
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ }
+
+ /**
+ * 鐢绘墜鎸囨姮璧凤紝鍖归厤鐘舵��
+ *
+ * @param canvas
+ */
+ private void drawFingerUpMatched(Canvas canvas) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(DEFAULT_BACK_COLOR);
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_COLOR);
+ canvas.drawCircle(0, 0, mInnerRadius, mPaint);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_COLOR);
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(getContext(),2));
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ }
+
+ /**
+ * 鐢绘墜鎸囨姮璧凤紝涓嶅尮閰嶇姸鎬�
+ *
+ * @param canvas
+ */
+ private void drawFingerUpUnmatched(Canvas canvas) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(DEFAULT_BACK_COLOR);
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_FALSE_COLOR);
+ canvas.drawCircle(0, 0, mInnerRadius, mPaint);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(GestureLockView.DEFAULT_SELECT_FALSE_COLOR);
+ mPaint.setStrokeWidth(HDLUtlisXM.dp2px(getContext(),1));
+ canvas.drawCircle(0, 0, mOuterRadius, mPaint);
+ }
+
+ @Override
+ public View getView() {
+ return this;
+ }
+
+ @Override
+ public void onNoFinger() {
+ mCurrentState = NO_FINGER;
+ postInvalidate();
+ }
+
+ @Override
+ public void onFingerTouch() {
+ mCurrentState = FINGER_TOUCH;
+ postInvalidate();
+ }
+
+ @Override
+ public void onFingerUpMatched() {
+ mCurrentState = FINGER_UP_MATCHED;
+ postInvalidate();
+ }
+
+ @Override
+ public void onFingerUpUnmatched() {
+ mCurrentState = FINGER_UP_UN_MATCHED;
+ postInvalidate();
+ }
+
+ public void setCurrentState(int state) {
+ this.mCurrentState = state;
+ postInvalidate();
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/ArrayWheelAdapter.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/ArrayWheelAdapter.java
new file mode 100644
index 0000000..773fde8
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/ArrayWheelAdapter.java
@@ -0,0 +1,46 @@
+package com.hdl.widget.pickerview.adapter;
+
+import com.hdl.widget.pickerview.contrarywind.adapter.WheelAdapter;
+
+import java.util.List;
+
+
+
+/**
+ * The simple Array wheel adapter
+ * @param <T> the element type
+ */
+public class ArrayWheelAdapter<T> implements WheelAdapter {
+
+
+ // items
+ private List<T> items;
+
+ /**
+ * Constructor
+ * @param items the items
+ */
+ public ArrayWheelAdapter(List<T> items) {
+ this.items = items;
+
+ }
+
+ @Override
+ public Object getItem(int index) {
+ if (index >= 0 && index < items.size()) {
+ return items.get(index);
+ }
+ return "";
+ }
+
+ @Override
+ public int getItemsCount() {
+ return items.size();
+ }
+
+ @Override
+ public int indexOf(Object o){
+ return items.indexOf(o);
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/NumericWheelAdapter.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/NumericWheelAdapter.java
new file mode 100644
index 0000000..f676864
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/adapter/NumericWheelAdapter.java
@@ -0,0 +1,47 @@
+package com.hdl.widget.pickerview.adapter;
+
+
+import com.hdl.widget.pickerview.contrarywind.adapter.WheelAdapter;
+
+/**
+ * Numeric Wheel adapter.
+ */
+public class NumericWheelAdapter implements WheelAdapter {
+
+ private int minValue;
+ private int maxValue;
+
+ /**
+ * Constructor
+ * @param minValue the wheel min value
+ * @param maxValue the wheel max value
+ */
+ public NumericWheelAdapter(int minValue, int maxValue) {
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ }
+
+ @Override
+ public Object getItem(int index) {
+ if (index >= 0 && index < getItemsCount()) {
+ int value = minValue + index;
+ return value;
+ }
+ return 0;
+ }
+
+ @Override
+ public int getItemsCount() {
+ return maxValue - minValue + 1;
+ }
+
+ @Override
+ public int indexOf(Object o){
+ try {
+ return (int)o - minValue;
+ } catch (Exception e) {
+ return -1;
+ }
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/OptionsPickerBuilder.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/OptionsPickerBuilder.java
new file mode 100644
index 0000000..66911ab
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/OptionsPickerBuilder.java
@@ -0,0 +1,278 @@
+package com.hdl.widget.pickerview.builder;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.support.annotation.ColorInt;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.hdl.widget.pickerview.configure.PickerOptions;
+import com.hdl.widget.pickerview.listener.CustomListener;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectListener;
+import com.hdl.widget.pickerview.view.OptionsPickerView;
+
+import com.hdl.widget.pickerview.configure.PickerOptions;
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+//import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * Created by xiaosongzeem on 2018/3/20.
+ */
+
+public class OptionsPickerBuilder {
+
+ //閰嶇疆绫�
+ private PickerOptions mPickerOptions;
+
+
+ //Required
+ public OptionsPickerBuilder(Context context, OnOptionsSelectListener listener) {
+ mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_OPTIONS);
+ mPickerOptions.context = context;
+ mPickerOptions.optionsSelectListener = listener;
+ }
+
+ //Option
+ public OptionsPickerBuilder setSubmitText(String textContentConfirm) {
+ mPickerOptions.textContentConfirm = textContentConfirm;
+ return this;
+ }
+
+ public OptionsPickerBuilder setCancelText(String textContentCancel) {
+ mPickerOptions.textContentCancel = textContentCancel;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTitleText(String textContentTitle) {
+ mPickerOptions.textContentTitle = textContentTitle;
+ return this;
+ }
+
+ public OptionsPickerBuilder isDialog(boolean isDialog) {
+ mPickerOptions.isDialog = isDialog;
+ return this;
+ }
+
+ public OptionsPickerBuilder addOnCancelClickListener(View.OnClickListener cancelListener) {
+ mPickerOptions.cancelListener = cancelListener;
+ return this;
+ }
+
+
+ public OptionsPickerBuilder setSubmitColor(int textColorConfirm) {
+ mPickerOptions.textColorConfirm = textColorConfirm;
+ return this;
+ }
+
+ public OptionsPickerBuilder setCancelColor(int textColorCancel) {
+ mPickerOptions.textColorCancel = textColorCancel;
+ return this;
+ }
+
+
+ /**
+ * {@link #setOutSideColor} instead.
+ *
+ * @param backgroundId color resId.
+ */
+ @Deprecated
+ public OptionsPickerBuilder setBackgroundId(int backgroundId) {
+ mPickerOptions.outSideColor = backgroundId;
+ return this;
+ }
+
+ /**
+ * 鏄剧ず鏃剁殑澶栭儴鑳屾櫙鑹查鑹�,榛樿鏄伆鑹�
+ *
+ * @param outSideColor color resId.
+ * @return
+ */
+ public OptionsPickerBuilder setOutSideColor(int outSideColor) {
+ mPickerOptions.outSideColor = outSideColor;
+ return this;
+ }
+
+ /**
+ * ViewGroup 绫诲瀷
+ * 璁剧疆PickerView鐨勬樉绀哄鍣�
+ *
+ * @param decorView Parent View.
+ * @return
+ */
+ public OptionsPickerBuilder setDecorView(ViewGroup decorView) {
+ mPickerOptions.decorView = decorView;
+ return this;
+ }
+
+ public OptionsPickerBuilder setLayoutRes(int res, CustomListener listener) {
+ mPickerOptions.layoutRes = res;
+ mPickerOptions.customListener = listener;
+ return this;
+ }
+
+ public OptionsPickerBuilder setBgColor(int bgColorWheel) {
+ mPickerOptions.bgColorWheel = bgColorWheel;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTitleBgColor(int bgColorTitle) {
+ mPickerOptions.bgColorTitle = bgColorTitle;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTitleColor(int textColorTitle) {
+ mPickerOptions.textColorTitle = textColorTitle;
+ return this;
+ }
+
+ public OptionsPickerBuilder setSubCalSize(int textSizeSubmitCancel) {
+ mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTitleSize(int textSizeTitle) {
+ mPickerOptions.textSizeTitle = textSizeTitle;
+ return this;
+ }
+
+ public OptionsPickerBuilder setContentTextSize(int textSizeContent) {
+ mPickerOptions.textSizeContent = textSizeContent;
+ return this;
+ }
+
+ public OptionsPickerBuilder setOutSideCancelable(boolean cancelable) {
+ mPickerOptions.cancelable = cancelable;
+ return this;
+ }
+
+
+ public OptionsPickerBuilder setLabels(String label1, String label2, String label3) {
+ mPickerOptions.label1 = label1;
+ mPickerOptions.label2 = label2;
+ mPickerOptions.label3 = label3;
+ return this;
+ }
+
+ /**
+ * 璁剧疆Item 鐨勯棿璺濆�嶆暟锛岀敤浜庢帶鍒� Item 楂樺害闂撮殧
+ *
+ * @param lineSpacingMultiplier 娴偣鍨嬶紝1.0-4.0f 涔嬮棿鏈夋晥,瓒呰繃鍒欏彇鏋佸�笺��
+ */
+ public OptionsPickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier;
+ return this;
+ }
+
+ /**
+ * Set item divider line type color.
+ *
+ * @param dividerColor color resId.
+ */
+ public OptionsPickerBuilder setDividerColor(@ColorInt int dividerColor) {
+ mPickerOptions.dividerColor = dividerColor;
+ return this;
+ }
+
+ /**
+ * Set item divider line type.
+ *
+ * @param dividerType enum Type {@link WheelView.DividerType}
+ */
+ public OptionsPickerBuilder setDividerType(WheelView.DividerType dividerType) {
+ mPickerOptions.dividerType = dividerType;
+ return this;
+ }
+
+ /**
+ * Set the textColor of selected item.
+ *
+ * @param textColorCenter color res.
+ */
+ public OptionsPickerBuilder setTextColorCenter(int textColorCenter) {
+ mPickerOptions.textColorCenter = textColorCenter;
+ return this;
+ }
+
+ /**
+ * Set the textColor of outside item.
+ *
+ * @param textColorOut color resId.
+ */
+ public OptionsPickerBuilder setTextColorOut(@ColorInt int textColorOut) {
+ mPickerOptions.textColorOut = textColorOut;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTypeface(Typeface font) {
+ mPickerOptions.font = font;
+ return this;
+ }
+
+ public OptionsPickerBuilder setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
+ mPickerOptions.cyclic1 = cyclic1;
+ mPickerOptions.cyclic2 = cyclic2;
+ mPickerOptions.cyclic3 = cyclic3;
+ return this;
+ }
+
+ public OptionsPickerBuilder setSelectOptions(int option1) {
+ mPickerOptions.option1 = option1;
+ return this;
+ }
+
+ public OptionsPickerBuilder setSelectOptions(int option1, int option2) {
+ mPickerOptions.option1 = option1;
+ mPickerOptions.option2 = option2;
+ return this;
+ }
+
+ public OptionsPickerBuilder setSelectOptions(int option1, int option2, int option3) {
+ mPickerOptions.option1 = option1;
+ mPickerOptions.option2 = option2;
+ mPickerOptions.option3 = option3;
+ return this;
+ }
+
+ public OptionsPickerBuilder setTextXOffset(int xoffset_one, int xoffset_two, int xoffset_three) {
+ mPickerOptions.x_offset_one = xoffset_one;
+ mPickerOptions.x_offset_two = xoffset_two;
+ mPickerOptions.x_offset_three = xoffset_three;
+ return this;
+ }
+
+ public OptionsPickerBuilder isCenterLabel(boolean isCenterLabel) {
+ mPickerOptions.isCenterLabel = isCenterLabel;
+ return this;
+ }
+
+ /**
+ * 鍒囨崲閫夐」鏃讹紝鏄惁杩樺師绗竴椤�
+ *
+ * @param isRestoreItem true锛氳繕鍘燂紱 false: 淇濇寔涓婁竴涓�夐」
+ * @return TimePickerBuilder
+ */
+ public OptionsPickerBuilder isRestoreItem(boolean isRestoreItem) {
+ mPickerOptions.isRestoreItem = isRestoreItem;
+ return this;
+ }
+
+ /**
+ * @param listener 鍒囨崲item椤规粴鍔ㄥ仠姝㈡椂锛屽疄鏃跺洖璋冪洃鍚��
+ * @return
+ */
+ public OptionsPickerBuilder setOptionsSelectChangeListener(OnOptionsSelectChangeListener listener) {
+ mPickerOptions.optionsSelectChangeListener = listener;
+ return this;
+ }
+
+
+// public <T> OptionsPickerView<T> build() {
+// return new OptionsPickerView<>(mPickerOptions);
+// }
+
+ public OptionsPickerView build() {
+ return new OptionsPickerView(mPickerOptions);
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/TimePickerBuilder.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/TimePickerBuilder.java
new file mode 100644
index 0000000..84a3b9d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/builder/TimePickerBuilder.java
@@ -0,0 +1,295 @@
+package com.hdl.widget.pickerview.builder;
+
+import android.content.Context;
+import android.support.annotation.ColorInt;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.hdl.widget.pickerview.configure.PickerOptions;
+import com.hdl.widget.pickerview.listener.CustomListener;
+import com.hdl.widget.pickerview.listener.OnTimeSelectChangeListener;
+import com.hdl.widget.pickerview.listener.OnTimeSelectListener;
+import com.hdl.widget.pickerview.view.TimePickerView;
+
+import java.util.Calendar;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * Created by xiaosongzeem on 2018/3/20.
+ */
+
+public class TimePickerBuilder {
+
+ private PickerOptions mPickerOptions;
+
+ //Required
+ public TimePickerBuilder(Context context, OnTimeSelectListener listener) {
+ mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_TIME);
+ mPickerOptions.context = context;
+ mPickerOptions.timeSelectListener = listener;
+ }
+
+ //Option
+ public TimePickerBuilder setGravity(int gravity) {
+ mPickerOptions.textGravity = gravity;
+ return this;
+ }
+
+ public TimePickerBuilder addOnCancelClickListener(View.OnClickListener cancelListener) {
+ mPickerOptions.cancelListener = cancelListener;
+ return this;
+ }
+
+ /**
+ * new boolean[]{true, true, true, false, false, false}
+ * control the "year","month","day","hours","minutes","seconds " display or hide.
+ * 鍒嗗埆鎺у埗鈥滃勾鈥濃�滄湀鈥濃�滄棩鈥濃�滄椂鈥濃�滃垎鈥濃�滅鈥濈殑鏄剧ず鎴栭殣钘忋��
+ *
+ * @param type 甯冨皵鍨嬫暟缁勶紝闀垮害闇�瑕佽缃负6銆�
+ * @return TimePickerBuilder
+ */
+ public TimePickerBuilder setType(boolean[] type) {
+ mPickerOptions.type = type;
+ return this;
+ }
+
+ public TimePickerBuilder setSubmitText(String textContentConfirm) {
+ mPickerOptions.textContentConfirm = textContentConfirm;
+ return this;
+ }
+
+ public TimePickerBuilder isDialog(boolean isDialog) {
+ mPickerOptions.isDialog = isDialog;
+ return this;
+ }
+
+ public TimePickerBuilder setCancelText(String textContentCancel) {
+ mPickerOptions.textContentCancel = textContentCancel;
+ return this;
+ }
+
+ public TimePickerBuilder setTitleText(String textContentTitle) {
+ mPickerOptions.textContentTitle = textContentTitle;
+ return this;
+ }
+
+ public TimePickerBuilder setSubmitColor(int textColorConfirm) {
+ mPickerOptions.textColorConfirm = textColorConfirm;
+ return this;
+ }
+
+ public TimePickerBuilder setCancelColor(int textColorCancel) {
+ mPickerOptions.textColorCancel = textColorCancel;
+ return this;
+ }
+
+ /**
+ * ViewGroup 绫诲瀷鐨勫鍣�
+ *
+ * @param decorView 閫夋嫨鍣ㄤ細琚坊鍔犲埌姝ゅ鍣ㄤ腑
+ * @return TimePickerBuilder
+ */
+ public TimePickerBuilder setDecorView(ViewGroup decorView) {
+ mPickerOptions.decorView = decorView;
+ return this;
+ }
+
+ public TimePickerBuilder setBgColor(int bgColorWheel) {
+ mPickerOptions.bgColorWheel = bgColorWheel;
+ return this;
+ }
+
+ public TimePickerBuilder setTitleBgColor(int bgColorTitle) {
+ mPickerOptions.bgColorTitle = bgColorTitle;
+ return this;
+ }
+
+ public TimePickerBuilder setTitleColor(int textColorTitle) {
+ mPickerOptions.textColorTitle = textColorTitle;
+ return this;
+ }
+
+ public TimePickerBuilder setSubCalSize(int textSizeSubmitCancel) {
+ mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel;
+ return this;
+ }
+
+ public TimePickerBuilder setTitleSize(int textSizeTitle) {
+ mPickerOptions.textSizeTitle = textSizeTitle;
+ return this;
+ }
+
+ public TimePickerBuilder setContentTextSize(int textSizeContent) {
+ mPickerOptions.textSizeContent = textSizeContent;
+ return this;
+ }
+
+ /**
+ * 鍥犱负绯荤粺Calendar鐨勬湀浠芥槸浠�0-11鐨�,鎵�浠ュ鏋滄槸璋冪敤Calendar鐨剆et鏂规硶鏉ヨ缃椂闂�,鏈堜唤鐨勮寖鍥翠篃瑕佹槸浠�0-11
+ *
+ * @param date
+ * @return TimePickerBuilder
+ */
+ public TimePickerBuilder setDate(Calendar date) {
+ mPickerOptions.date = date;
+ return this;
+ }
+
+ public TimePickerBuilder setLayoutRes(int res, CustomListener customListener) {
+ mPickerOptions.layoutRes = res;
+ mPickerOptions.customListener = customListener;
+ return this;
+ }
+
+
+ /**
+ * 璁剧疆璧峰鏃堕棿
+ * 鍥犱负绯荤粺Calendar鐨勬湀浠芥槸浠�0-11鐨�,鎵�浠ュ鏋滄槸璋冪敤Calendar鐨剆et鏂规硶鏉ヨ缃椂闂�,鏈堜唤鐨勮寖鍥翠篃瑕佹槸浠�0-11
+ */
+
+ public TimePickerBuilder setRangDate(Calendar startDate, Calendar endDate) {
+ mPickerOptions.startDate = startDate;
+ mPickerOptions.endDate = endDate;
+ return this;
+ }
+
+
+ /**
+ * 璁剧疆闂磋窛鍊嶆暟,浣嗘槸鍙兘鍦�1.0-4.0f涔嬮棿
+ *
+ * @param lineSpacingMultiplier
+ */
+ public TimePickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier;
+ return this;
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑棰滆壊
+ *
+ * @param dividerColor
+ */
+
+ public TimePickerBuilder setDividerColor(@ColorInt int dividerColor) {
+ mPickerOptions.dividerColor = dividerColor;
+ return this;
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑绫诲瀷
+ *
+ * @param dividerType
+ */
+ public TimePickerBuilder setDividerType(WheelView.DividerType dividerType) {
+ mPickerOptions.dividerType = dividerType;
+ return this;
+ }
+
+ /**
+ * {@link #setOutSideColor} instead.
+ *
+ * @param backgroundId color resId.
+ */
+ @Deprecated
+ public TimePickerBuilder setBackgroundId(int backgroundId) {
+ mPickerOptions.outSideColor = backgroundId;
+ return this;
+ }
+
+ /**
+ * 鏄剧ず鏃剁殑澶栭儴鑳屾櫙鑹查鑹�,榛樿鏄伆鑹�
+ *
+ * @param outSideColor
+ */
+ public TimePickerBuilder setOutSideColor(@ColorInt int outSideColor) {
+ mPickerOptions.outSideColor = outSideColor;
+ return this;
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public TimePickerBuilder setTextColorCenter(@ColorInt int textColorCenter) {
+ mPickerOptions.textColorCenter = textColorCenter;
+ return this;
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸互澶栨枃瀛楃殑棰滆壊
+ *
+ * @param textColorOut
+ */
+ public TimePickerBuilder setTextColorOut(@ColorInt int textColorOut) {
+ mPickerOptions.textColorOut = textColorOut;
+ return this;
+ }
+
+ public TimePickerBuilder isCyclic(boolean cyclic) {
+ mPickerOptions.cyclic = cyclic;
+ return this;
+ }
+
+ public TimePickerBuilder setOutSideCancelable(boolean cancelable) {
+ mPickerOptions.cancelable = cancelable;
+ return this;
+ }
+
+ public TimePickerBuilder setLunarCalendar(boolean lunarCalendar) {
+ mPickerOptions.isLunarCalendar = lunarCalendar;
+ return this;
+ }
+
+
+ public TimePickerBuilder setLabel(String label_year, String label_month, String label_day, String label_hours, String label_mins, String label_seconds) {
+ mPickerOptions.label_year = label_year;
+ mPickerOptions.label_month = label_month;
+ mPickerOptions.label_day = label_day;
+ mPickerOptions.label_hours = label_hours;
+ mPickerOptions.label_minutes = label_mins;
+ mPickerOptions.label_seconds = label_seconds;
+ return this;
+ }
+
+ /**
+ * 璁剧疆X杞村�炬枩瑙掑害[ -90 , 90掳]
+ *
+ * @param x_offset_year 骞�
+ * @param x_offset_month 鏈�
+ * @param x_offset_day 鏃�
+ * @param x_offset_hours 鏃�
+ * @param x_offset_minutes 鍒�
+ * @param x_offset_seconds 绉�
+ * @return
+ */
+ public TimePickerBuilder setTextXOffset(int x_offset_year, int x_offset_month, int x_offset_day,
+ int x_offset_hours, int x_offset_minutes, int x_offset_seconds) {
+ mPickerOptions.x_offset_year = x_offset_year;
+ mPickerOptions.x_offset_month = x_offset_month;
+ mPickerOptions.x_offset_day = x_offset_day;
+ mPickerOptions.x_offset_hours = x_offset_hours;
+ mPickerOptions.x_offset_minutes = x_offset_minutes;
+ mPickerOptions.x_offset_seconds = x_offset_seconds;
+ return this;
+ }
+
+ public TimePickerBuilder isCenterLabel(boolean isCenterLabel) {
+ mPickerOptions.isCenterLabel = isCenterLabel;
+ return this;
+ }
+
+ /**
+ * @param listener 鍒囨崲item椤规粴鍔ㄥ仠姝㈡椂锛屽疄鏃跺洖璋冪洃鍚��
+ * @return
+ */
+ public TimePickerBuilder setTimeSelectChangeListener(OnTimeSelectChangeListener listener) {
+ mPickerOptions.timeSelectChangeListener = listener;
+ return this;
+ }
+
+ public TimePickerView build() {
+ return new TimePickerView(mPickerOptions);
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/configure/PickerOptions.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/configure/PickerOptions.java
new file mode 100644
index 0000000..48ae31d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/configure/PickerOptions.java
@@ -0,0 +1,116 @@
+package com.hdl.widget.pickerview.configure;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.listener.CustomListener;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectListener;
+import com.hdl.widget.pickerview.listener.OnTimeSelectChangeListener;
+import com.hdl.widget.pickerview.listener.OnTimeSelectListener;
+
+import java.util.Calendar;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * Build Options
+ * Created by xiaosongzeem on 2018/3/8.
+ */
+
+public class PickerOptions {
+
+ //constant
+ private static final int PICKER_VIEW_BTN_COLOR_NORMAL = 0xFFFF5722;
+ private static final int PICKER_VIEW_BTN_COLOR_NORMAL_GARY = 0xFF808080;
+ private static final int PICKER_VIEW_BG_COLOR_TITLE = 0xFFf5f5f5;
+ private static final int PICKER_VIEW_COLOR_TITLE = 0xFF000000;
+ private static final int PICKER_VIEW_BG_COLOR_DEFAULT = 0xFFFFFFFF;
+
+ public static final int TYPE_PICKER_OPTIONS = 1;
+ public static final int TYPE_PICKER_TIME = 2;
+
+ public OnOptionsSelectListener optionsSelectListener;
+ public OnTimeSelectListener timeSelectListener;
+ public View.OnClickListener cancelListener;
+
+ public OnTimeSelectChangeListener timeSelectChangeListener;
+ public OnOptionsSelectChangeListener optionsSelectChangeListener;
+ public CustomListener customListener;
+
+
+ //options picker
+ public String label1, label2, label3;//鍗曚綅瀛楃
+ public int option1, option2, option3;//榛樿閫変腑椤�
+ public int x_offset_one, x_offset_two, x_offset_three;//x杞村亸绉婚噺
+
+ public boolean cyclic1 = false;//鏄惁寰幆锛岄粯璁ゅ惁
+ public boolean cyclic2 = false;
+ public boolean cyclic3 = false;
+
+ public boolean isRestoreItem = false; //鍒囨崲鏃讹紝杩樺師绗竴椤�
+
+
+ //time picker
+ public boolean[] type = new boolean[]{true, true, true, false, false, false};//鏄剧ず绫诲瀷锛岄粯璁ゆ樉绀猴細 骞存湀鏃�
+
+ public Calendar date;//褰撳墠閫変腑鏃堕棿
+ public Calendar startDate;//寮�濮嬫椂闂�
+ public Calendar endDate;//缁堟鏃堕棿
+ public int startYear;//寮�濮嬪勾浠�
+ public int endYear;//缁撳熬骞翠唤
+
+ public boolean cyclic = false;//鏄惁寰幆
+ public boolean isLunarCalendar = false;//鏄惁鏄剧ず鍐滃巻
+
+ public String label_year, label_month, label_day, label_hours, label_minutes, label_seconds;//鍗曚綅
+ public int x_offset_year, x_offset_month, x_offset_day, x_offset_hours, x_offset_minutes, x_offset_seconds;//鍗曚綅
+
+
+ public PickerOptions(int buildType) {
+ if (buildType == TYPE_PICKER_OPTIONS) {
+ layoutRes = R.layout.hdl_widget_pickerview_options;
+ } else {
+ layoutRes = R.layout.hdl_widget_pickerview_time;
+ }
+ }
+
+ //******* general field ******//
+ public int layoutRes;
+ public ViewGroup decorView;
+ public int textGravity = Gravity.CENTER;
+ public Context context;
+
+ public String textContentConfirm;//纭畾鎸夐挳鏂囧瓧
+ public String textContentCancel;//鍙栨秷鎸夐挳鏂囧瓧
+ public String textContentTitle;//鏍囬鏂囧瓧
+
+ public int textColorConfirm = PICKER_VIEW_BTN_COLOR_NORMAL;//纭畾鎸夐挳棰滆壊
+ public int textColorCancel = PICKER_VIEW_BTN_COLOR_NORMAL_GARY;//鍙栨秷鎸夐挳棰滆壊
+ public int textColorTitle = PICKER_VIEW_COLOR_TITLE;//鏍囬棰滆壊
+
+ public int bgColorWheel = PICKER_VIEW_BG_COLOR_DEFAULT;//婊氳疆鑳屾櫙棰滆壊
+ public int bgColorTitle = PICKER_VIEW_BG_COLOR_TITLE;//鏍囬鑳屾櫙棰滆壊
+
+ public int textSizeSubmitCancel = 17;//纭畾鍙栨秷鎸夐挳澶у皬
+ public int textSizeTitle = 18;//鏍囬鏂囧瓧澶у皬
+ public int textSizeContent = 18;//鍐呭鏂囧瓧澶у皬
+
+ public int textColorOut = 0xFFa8a8a8; //鍒嗗壊绾夸互澶栫殑鏂囧瓧棰滆壊
+ public int textColorCenter = 0xFF2a2a2a; //鍒嗗壊绾夸箣闂寸殑鏂囧瓧棰滆壊
+ public int dividerColor = 0xFFd5d5d5; //鍒嗗壊绾跨殑棰滆壊
+ public int outSideColor = -1; //鏄剧ず鏃剁殑澶栭儴鑳屾櫙鑹查鑹�,榛樿鏄伆鑹�
+
+ public float lineSpacingMultiplier = 1.6f; // 鏉$洰闂磋窛鍊嶆暟 榛樿1.6
+ public boolean isDialog;//鏄惁鏄璇濇妯″紡
+
+ public boolean cancelable = true;//鏄惁鑳藉彇娑�
+ public boolean isCenterLabel = false;//鏄惁鍙樉绀轰腑闂寸殑label,榛樿姣忎釜item閮芥樉绀�
+ public Typeface font = Typeface.MONOSPACE;//瀛椾綋鏍峰紡
+ public WheelView.DividerType dividerType = WheelView.DividerType.FILL;//鍒嗛殧绾跨被鍨�
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/adapter/WheelAdapter.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/adapter/WheelAdapter.java
new file mode 100644
index 0000000..6a4dc0b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/adapter/WheelAdapter.java
@@ -0,0 +1,25 @@
+package com.hdl.widget.pickerview.contrarywind.adapter;
+
+
+public interface WheelAdapter<T> {
+ /**
+ * Gets items count
+ * @return the count of wheel items
+ */
+ int getItemsCount();
+
+ /**
+ * Gets a wheel item by index.
+ * @param index the item index
+ * @return the wheel item text or null
+ */
+ T getItem(int index);
+
+ /**
+ * Gets maximum item length. It is used to determine the wheel width.
+ * If -1 is returned there will be used the default wheel width.
+ * @param o the item object
+ * @return the maximum item length or -1
+ */
+ int indexOf(T o);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/interfaces/IPickerViewData.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/interfaces/IPickerViewData.java
new file mode 100644
index 0000000..c553be5
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/interfaces/IPickerViewData.java
@@ -0,0 +1,8 @@
+package com.hdl.widget.pickerview.contrarywind.interfaces;
+
+/**
+ * Created by Sai on 2016/7/13.
+ */
+public interface IPickerViewData {
+ String getPickerViewText();
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/LoopViewGestureListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/LoopViewGestureListener.java
new file mode 100644
index 0000000..f812f24
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/LoopViewGestureListener.java
@@ -0,0 +1,26 @@
+package com.hdl.widget.pickerview.contrarywind.listener;
+
+import android.view.MotionEvent;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+
+
+/**
+ * 鎵嬪娍鐩戝惉
+ */
+public final class LoopViewGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
+
+ private final WheelView wheelView;
+
+
+ public LoopViewGestureListener(WheelView wheelView) {
+ this.wheelView = wheelView;
+ }
+
+ @Override
+ public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ wheelView.scrollBy(velocityY);
+ return true;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/OnItemSelectedListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/OnItemSelectedListener.java
new file mode 100644
index 0000000..c0264df
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/listener/OnItemSelectedListener.java
@@ -0,0 +1,6 @@
+package com.hdl.widget.pickerview.contrarywind.listener;
+
+
+public interface OnItemSelectedListener {
+ void onItemSelected(int index);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/InertiaTimerTask.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/InertiaTimerTask.java
new file mode 100644
index 0000000..e805b47
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/InertiaTimerTask.java
@@ -0,0 +1,79 @@
+package com.hdl.widget.pickerview.contrarywind.timer;
+
+import java.util.TimerTask;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * 婊氬姩鎯�х殑瀹炵幇
+ *
+ * @author 灏忓旦
+ * date: 2017-12-23 23:20:44
+ */
+public final class InertiaTimerTask extends TimerTask {
+
+ private float mCurrentVelocityY; //褰撳墠婊戝姩閫熷害
+ private final float mFirstVelocityY;//鎵嬫寚绂诲紑灞忓箷鏃剁殑鍒濆閫熷害
+ private final WheelView mWheelView;
+
+ /**
+ * @param wheelView 婊氳疆瀵硅薄
+ * @param velocityY Y杞存粦琛岄�熷害
+ */
+ public InertiaTimerTask(WheelView wheelView, float velocityY) {
+ super();
+ this.mWheelView = wheelView;
+ this.mFirstVelocityY = velocityY;
+ mCurrentVelocityY = Integer.MAX_VALUE;
+ }
+
+ @Override
+ public final void run() {
+
+ //闃叉闂姩锛屽閫熷害鍋氫竴涓檺鍒躲��
+ if (mCurrentVelocityY == Integer.MAX_VALUE) {
+ if (Math.abs(mFirstVelocityY) > 2000F) {
+ mCurrentVelocityY = mFirstVelocityY > 0 ? 2000F : -2000F;
+ } else {
+ mCurrentVelocityY = mFirstVelocityY;
+ }
+ }
+
+ //鍙戦�乭andler娑堟伅 澶勭悊骞抽『鍋滄婊氬姩閫昏緫
+ if (Math.abs(mCurrentVelocityY) >= 0.0F && Math.abs(mCurrentVelocityY) <= 20F) {
+ mWheelView.cancelFuture();
+ mWheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_SMOOTH_SCROLL);
+ return;
+ }
+
+ int dy = (int) (mCurrentVelocityY / 100F);
+ mWheelView.setTotalScrollY(mWheelView.getTotalScrollY() - dy);
+ if (!mWheelView.isLoop()) {
+ float itemHeight = mWheelView.getItemHeight();
+ float top = (-mWheelView.getInitPosition()) * itemHeight;
+ float bottom = (mWheelView.getItemsCount() - 1 - mWheelView.getInitPosition()) * itemHeight;
+ if (mWheelView.getTotalScrollY() - itemHeight * 0.25 < top) {
+ top = mWheelView.getTotalScrollY() + dy;
+ } else if (mWheelView.getTotalScrollY() + itemHeight * 0.25 > bottom) {
+ bottom = mWheelView.getTotalScrollY() + dy;
+ }
+
+ if (mWheelView.getTotalScrollY() <= top) {
+ mCurrentVelocityY = 40F;
+ mWheelView.setTotalScrollY((int) top);
+ } else if (mWheelView.getTotalScrollY() >= bottom) {
+ mWheelView.setTotalScrollY((int) bottom);
+ mCurrentVelocityY = -40F;
+ }
+ }
+
+ if (mCurrentVelocityY < 0.0F) {
+ mCurrentVelocityY = mCurrentVelocityY + 20F;
+ } else {
+ mCurrentVelocityY = mCurrentVelocityY - 20F;
+ }
+
+ //鍒锋柊UI
+ mWheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/MessageHandler.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/MessageHandler.java
new file mode 100644
index 0000000..514fa31
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/MessageHandler.java
@@ -0,0 +1,42 @@
+package com.hdl.widget.pickerview.contrarywind.timer;
+
+import android.os.Handler;
+import android.os.Message;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * Handler 娑堟伅绫�
+ *
+ * @author 灏忓旦
+ * date: 2017-12-23 23:20:44
+ */
+public final class MessageHandler extends Handler {
+ public static final int WHAT_INVALIDATE_LOOP_VIEW = 1000;
+ public static final int WHAT_SMOOTH_SCROLL = 2000;
+ public static final int WHAT_ITEM_SELECTED = 3000;
+
+ private final WheelView wheelView;
+
+ public MessageHandler(WheelView wheelView) {
+ this.wheelView = wheelView;
+ }
+
+ @Override
+ public final void handleMessage(Message msg) {
+ switch (msg.what) {
+ case WHAT_INVALIDATE_LOOP_VIEW:
+ wheelView.invalidate();
+ break;
+
+ case WHAT_SMOOTH_SCROLL:
+ wheelView.smoothScroll(WheelView.ACTION.FLING);
+ break;
+
+ case WHAT_ITEM_SELECTED:
+ wheelView.onItemSelected();
+ break;
+ }
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/SmoothScrollTimerTask.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/SmoothScrollTimerTask.java
new file mode 100644
index 0000000..aee9b6c
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/timer/SmoothScrollTimerTask.java
@@ -0,0 +1,64 @@
+package com.hdl.widget.pickerview.contrarywind.timer;
+
+import java.util.TimerTask;
+
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * 骞虫粦婊氬姩鐨勫疄鐜�
+ *
+ * @author 灏忓旦
+ */
+public final class SmoothScrollTimerTask extends TimerTask {
+
+ private int realTotalOffset;
+ private int realOffset;
+ private int offset;
+ private final WheelView wheelView;
+
+ public SmoothScrollTimerTask(WheelView wheelView, int offset) {
+ this.wheelView = wheelView;
+ this.offset = offset;
+ realTotalOffset = Integer.MAX_VALUE;
+ realOffset = 0;
+ }
+
+ @Override
+ public final void run() {
+ if (realTotalOffset == Integer.MAX_VALUE) {
+ realTotalOffset = offset;
+ }
+ //鎶婅婊氬姩鐨勮寖鍥寸粏鍒嗘垚10灏忎唤锛屾寜10灏忎唤鍗曚綅鏉ラ噸缁�
+ realOffset = (int) ((float) realTotalOffset * 0.1F);
+
+ if (realOffset == 0) {
+ if (realTotalOffset < 0) {
+ realOffset = -1;
+ } else {
+ realOffset = 1;
+ }
+ }
+
+ if (Math.abs(realTotalOffset) <= 1) {
+ wheelView.cancelFuture();
+ wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
+ } else {
+ wheelView.setTotalScrollY(wheelView.getTotalScrollY() + realOffset);
+
+ //杩欓噷濡傛灉涓嶆槸寰幆妯″紡锛屽垯鐐瑰嚮绌虹櫧浣嶇疆闇�瑕佸洖婊氾紝涓嶇劧灏变細鍑虹幇閫夊埌锛�1 item鐨� 鎯呭喌
+ if (!wheelView.isLoop()) {
+ float itemHeight = wheelView.getItemHeight();
+ float top = (float) (-wheelView.getInitPosition()) * itemHeight;
+ float bottom = (float) (wheelView.getItemsCount() - 1 - wheelView.getInitPosition()) * itemHeight;
+ if (wheelView.getTotalScrollY() <= top || wheelView.getTotalScrollY() >= bottom) {
+ wheelView.setTotalScrollY(wheelView.getTotalScrollY() - realOffset);
+ wheelView.cancelFuture();
+ wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
+ return;
+ }
+ }
+ wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
+ realTotalOffset = realTotalOffset - realOffset;
+ }
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/view/WheelView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/view/WheelView.java
new file mode 100644
index 0000000..635d4e2
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/contrarywind/view/WheelView.java
@@ -0,0 +1,802 @@
+package com.hdl.widget.pickerview.contrarywind.view;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import com.hdl.widget.pickerview.contrarywind.adapter.WheelAdapter;
+import com.hdl.widget.pickerview.contrarywind.interfaces.IPickerViewData;
+import com.hdl.widget.pickerview.contrarywind.listener.LoopViewGestureListener;
+import com.hdl.widget.pickerview.contrarywind.listener.OnItemSelectedListener;
+import com.hdl.widget.pickerview.contrarywind.timer.InertiaTimerTask;
+import com.hdl.widget.pickerview.contrarywind.timer.MessageHandler;
+import com.hdl.widget.pickerview.contrarywind.timer.SmoothScrollTimerTask;
+
+/**
+ * 3d婊氳疆鎺т欢
+ */
+public class WheelView extends View {
+
+ public enum ACTION { // 鐐瑰嚮锛屾粦缈�(婊戝埌灏藉ご)锛屾嫋鎷戒簨浠�
+ CLICK, FLING, DAGGLE
+ }
+
+ public enum DividerType { // 鍒嗛殧绾跨被鍨�
+ FILL, WRAP
+ }
+
+ private static final String[] TIME_NUM = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09"};
+
+ private DividerType dividerType;//鍒嗛殧绾跨被鍨�
+
+ private Context context;
+ private Handler handler;
+ private GestureDetector gestureDetector;
+ private OnItemSelectedListener onItemSelectedListener;
+
+ private boolean isOptions = false;
+ private boolean isCenterLabel = true;
+
+ // Timer mTimer;
+ private ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
+ private ScheduledFuture<?> mFuture;
+
+ private Paint paintOuterText;
+ private Paint paintCenterText;
+ private Paint paintIndicator;
+
+ private WheelAdapter adapter;
+
+ private String label;//闄勫姞鍗曚綅
+ private int textSize;//閫夐」鐨勬枃瀛楀ぇ灏�
+ private int maxTextWidth;
+ private int maxTextHeight;
+ private int textXOffset;
+ private float itemHeight;//姣忚楂樺害
+
+
+ private Typeface typeface = Typeface.MONOSPACE;//瀛椾綋鏍峰紡锛岄粯璁ゆ槸绛夊瀛椾綋
+ private int textColorOut;
+ private int textColorCenter;
+ private int dividerColor;
+
+ // 鏉$洰闂磋窛鍊嶆暟
+ private float lineSpacingMultiplier = 1.6F;
+ private boolean isLoop;
+
+ // 绗竴鏉$嚎Y鍧愭爣鍊�
+ private float firstLineY;
+ //绗簩鏉$嚎Y鍧愭爣
+ private float secondLineY;
+ //涓棿label缁樺埗鐨刌鍧愭爣
+ private float centerY;
+
+ //褰撳墠婊氬姩鎬婚珮搴鍊�
+ private float totalScrollY;
+
+ //鍒濆鍖栭粯璁ら�変腑椤�
+ private int initPosition;
+
+ //閫変腑鐨処tem鏄鍑犱釜
+ private int selectedItem;
+ private int preCurrentIndex;
+ //婊氬姩鍋忕Щ鍊�,鐢ㄤ簬璁板綍婊氬姩浜嗗灏戜釜item
+ private int change;
+
+ // 缁樺埗鍑犱釜鏉$洰锛屽疄闄呬笂绗竴椤瑰拰鏈�鍚庝竴椤筜杞村帇缂╂垚0%浜嗭紝鎵�浠ュ彲瑙佺殑鏁扮洰瀹為檯涓�9
+ private int itemsVisible = 11;
+
+ private int measuredHeight;// WheelView 鎺т欢楂樺害
+ private int measuredWidth;// WheelView 鎺т欢瀹藉害
+
+ // 鍗婂緞
+ private int radius;
+
+ private int mOffset = 0;
+ private float previousY = 0;
+ private long startTime = 0;
+
+ // 淇敼杩欎釜鍊煎彲浠ユ敼鍙樻粦琛岄�熷害
+ private static final int VELOCITY_FLING = 5;
+ private int widthMeasureSpec;
+
+ private int mGravity = Gravity.CENTER;
+ private int drawCenterContentStart = 0;//涓棿閫変腑鏂囧瓧寮�濮嬬粯鍒朵綅缃�
+ private int drawOutContentStart = 0;//闈炰腑闂存枃瀛楀紑濮嬬粯鍒朵綅缃�
+ private static final float SCALE_CONTENT = 0.8F;//闈炰腑闂存枃瀛楀垯鐢ㄦ鎺у埗楂樺害锛屽帇鎵佸舰鎴�3d閿欒
+ private float CENTER_CONTENT_OFFSET;//鍋忕Щ閲�
+
+ private final float DEFAULT_TEXT_TARGET_SKEW_X = 0.5f;
+
+ public WheelView(Context context) {
+ this(context, null);
+ }
+
+ public WheelView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ textSize = getResources().getDimensionPixelSize(R.dimen.pickerview_textsize);//榛樿澶у皬
+
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float density = dm.density; // 灞忓箷瀵嗗害姣旓紙0.75/1.0/1.5/2.0/3.0锛�
+
+ if (density < 1) {//鏍规嵁瀵嗗害涓嶅悓杩涜閫傞厤
+ CENTER_CONTENT_OFFSET = 2.4F;
+ } else if (1 <= density && density < 2) {
+ CENTER_CONTENT_OFFSET = 3.6F;
+ } else if (1 <= density && density < 2) {
+ CENTER_CONTENT_OFFSET = 4.5F;
+ } else if (2 <= density && density < 3) {
+ CENTER_CONTENT_OFFSET = 6.0F;
+ } else if (density >= 3) {
+ CENTER_CONTENT_OFFSET = density * 2.5F;
+ }
+
+ if (attrs != null) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.pickerview, 0, 0);
+ mGravity = a.getInt(R.styleable.pickerview_wheelview_gravity, Gravity.CENTER);
+ textColorOut = a.getColor(R.styleable.pickerview_wheelview_textColorOut, 0xFFa8a8a8);
+ textColorCenter = a.getColor(R.styleable.pickerview_wheelview_textColorCenter, 0xFF2a2a2a);
+ dividerColor = a.getColor(R.styleable.pickerview_wheelview_dividerColor, 0xFFd5d5d5);
+ textSize = a.getDimensionPixelOffset(R.styleable.pickerview_wheelview_textSize, textSize);
+ lineSpacingMultiplier = a.getFloat(R.styleable.pickerview_wheelview_lineSpacingMultiplier, lineSpacingMultiplier);
+ a.recycle();//鍥炴敹鍐呭瓨
+ }
+
+ judgeLineSpace();
+ initLoopView(context);
+ }
+
+ /**
+ * 鍒ゆ柇闂磋窛鏄惁鍦�1.0-4.0涔嬮棿
+ */
+ private void judgeLineSpace() {
+ if (lineSpacingMultiplier < 1.0f) {
+ lineSpacingMultiplier = 1.0f;
+ } else if (lineSpacingMultiplier > 4.0f) {
+ lineSpacingMultiplier = 4.0f;
+ }
+ }
+
+ private void initLoopView(Context context) {
+ this.context = context;
+ handler = new MessageHandler(this);
+ gestureDetector = new GestureDetector(context, new LoopViewGestureListener(this));
+ gestureDetector.setIsLongpressEnabled(false);
+ isLoop = true;
+
+ totalScrollY = 0;
+ initPosition = -1;
+ initPaints();
+ }
+
+ private void initPaints() {
+ paintOuterText = new Paint();
+ paintOuterText.setColor(textColorOut);
+ paintOuterText.setAntiAlias(true);
+ paintOuterText.setTypeface(typeface);
+ paintOuterText.setTextSize(textSize);
+
+ paintCenterText = new Paint();
+ paintCenterText.setColor(textColorCenter);
+ paintCenterText.setAntiAlias(true);
+ paintCenterText.setTextScaleX(1.1F);
+ paintCenterText.setTypeface(typeface);
+ paintCenterText.setTextSize(textSize);
+
+ paintIndicator = new Paint();
+ paintIndicator.setColor(dividerColor);
+ paintIndicator.setAntiAlias(true);
+
+ setLayerType(LAYER_TYPE_SOFTWARE, null);
+ }
+
+ private void reMeasure() {//閲嶆柊娴嬮噺
+ if (adapter == null) {
+ return;
+ }
+
+ measureTextWidthHeight();
+
+ //鍗婂渾鐨勫懆闀� = item楂樺害涔樹互item鏁扮洰-1
+ int halfCircumference = (int) (itemHeight * (itemsVisible - 1));
+ //鏁翠釜鍦嗙殑鍛ㄩ暱闄や互PI寰楀埌鐩村緞锛岃繖涓洿寰勭敤浣滄帶浠剁殑鎬婚珮搴�
+ measuredHeight = (int) ((halfCircumference * 2) / Math.PI);
+ //姹傚嚭鍗婂緞
+ radius = (int) (halfCircumference / Math.PI);
+ //鎺т欢瀹藉害锛岃繖閲屾敮鎸亀eight
+ measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
+ //璁$畻涓ゆ潯妯嚎 鍜� 閫変腑椤圭敾绗旂殑鍩虹嚎Y浣嶇疆
+ firstLineY = (measuredHeight - itemHeight) / 2.0F;
+ secondLineY = (measuredHeight + itemHeight) / 2.0F;
+ centerY = secondLineY - (itemHeight - maxTextHeight) / 2.0f - CENTER_CONTENT_OFFSET;
+
+ //鍒濆鍖栨樉绀虹殑item鐨刾osition
+ if (initPosition == -1) {
+ if (isLoop) {
+ initPosition = (adapter.getItemsCount() + 1) / 2;
+ } else {
+ initPosition = 0;
+ }
+ }
+ preCurrentIndex = initPosition;
+ }
+
+ /**
+ * 璁$畻鏈�澶ength鐨凾ext鐨勫楂樺害
+ */
+ private void measureTextWidthHeight() {
+ Rect rect = new Rect();
+ for (int i = 0; i < adapter.getItemsCount(); i++) {
+ String s1 = getContentText(adapter.getItem(i));
+ paintCenterText.getTextBounds(s1, 0, s1.length(), rect);
+
+ int textWidth = rect.width();
+ if (textWidth > maxTextWidth) {
+ maxTextWidth = textWidth;
+ }
+ }
+ paintCenterText.getTextBounds("\u661F\u671F", 0, 2, rect); // 鏄熸湡鐨勫瓧绗︾紪鐮侊紙浠ュ畠涓烘爣鍑嗛珮搴︼級
+ maxTextHeight = rect.height() + 2;
+ itemHeight = lineSpacingMultiplier * maxTextHeight;
+ }
+
+ public void smoothScroll(ACTION action) {//骞虫粦婊氬姩鐨勫疄鐜�
+ cancelFuture();
+ if (action == ACTION.FLING || action == ACTION.DAGGLE) {
+ mOffset = (int) ((totalScrollY % itemHeight + itemHeight) % itemHeight);
+ if ((float) mOffset > itemHeight / 2.0F) {//濡傛灉瓒呰繃Item楂樺害鐨勪竴鍗婏紝婊氬姩鍒颁笅涓�涓狪tem鍘�
+ mOffset = (int) (itemHeight - (float) mOffset);
+ } else {
+ mOffset = -mOffset;
+ }
+ }
+ //鍋滄鐨勬椂鍊欙紝浣嶇疆鏈夊亸绉伙紝涓嶆槸鍏ㄩ儴閮借兘姝g‘鍋滄鍒颁腑闂翠綅缃殑锛岃繖閲屾妸鏂囧瓧浣嶇疆鎸洖涓棿鍘�
+ mFuture = mExecutor.scheduleWithFixedDelay(new SmoothScrollTimerTask(this, mOffset), 0, 10, TimeUnit.MILLISECONDS);
+ }
+
+ public final void scrollBy(float velocityY) {//婊氬姩鎯�х殑瀹炵幇
+ cancelFuture();
+ mFuture = mExecutor.scheduleWithFixedDelay(new InertiaTimerTask(this, velocityY), 0, VELOCITY_FLING, TimeUnit.MILLISECONDS);
+ }
+
+ public void cancelFuture() {
+ if (mFuture != null && !mFuture.isCancelled()) {
+ mFuture.cancel(true);
+ mFuture = null;
+ }
+ }
+
+ /**
+ * 璁剧疆鏄惁寰幆婊氬姩
+ *
+ * @param cyclic 鏄惁寰幆
+ */
+ public final void setCyclic(boolean cyclic) {
+ isLoop = cyclic;
+ }
+
+ public final void setTypeface(Typeface font) {
+ typeface = font;
+ paintOuterText.setTypeface(typeface);
+ paintCenterText.setTypeface(typeface);
+ }
+
+ public final void setTextSize(float size) {
+ if (size > 0.0F) {
+ textSize = (int) (context.getResources().getDisplayMetrics().density * size);
+ paintOuterText.setTextSize(textSize);
+ paintCenterText.setTextSize(textSize);
+ }
+ }
+
+ public final void setCurrentItem(int currentItem) {
+ //涓嶆坊鍔犺繖鍙�,褰撹繖涓獁heelView涓嶅彲瑙佹椂,榛樿閮芥槸0,浼氬鑷磋幏鍙栧埌鐨勬椂闂撮敊璇�
+ this.selectedItem = currentItem;
+ this.initPosition = currentItem;
+ totalScrollY = 0;//鍥炲綊椤堕儴锛屼笉鐒堕噸璁緎etCurrentItem鐨勮瘽浣嶇疆浼氬亸绉荤殑锛屽氨浼氭樉绀哄嚭涓嶅浣嶇疆鐨勬暟鎹�
+ invalidate();
+ }
+
+ public final void setOnItemSelectedListener(OnItemSelectedListener OnItemSelectedListener) {
+ this.onItemSelectedListener = OnItemSelectedListener;
+ }
+
+ public final void setAdapter(WheelAdapter adapter) {
+ this.adapter = adapter;
+ reMeasure();
+ invalidate();
+ }
+
+ public final WheelAdapter getAdapter() {
+ return adapter;
+ }
+
+ public final int getCurrentItem() {
+ // return selectedItem;
+ if (adapter == null) {
+ return 0;
+ }
+ if (isLoop && (selectedItem < 0 || selectedItem >= adapter.getItemsCount())) {
+ return Math.max(0, Math.min(Math.abs(Math.abs(selectedItem) - adapter.getItemsCount()), adapter.getItemsCount() - 1));
+ }
+ return Math.max(0, Math.min(selectedItem, adapter.getItemsCount() - 1));
+ }
+
+ public final void onItemSelected() {
+ if (onItemSelectedListener != null) {
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ onItemSelectedListener.onItemSelected(getCurrentItem());
+ }
+ }, 200L);
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (adapter == null) {
+ return;
+ }
+ //initPosition瓒婄晫浼氶�犳垚preCurrentIndex鐨勫�间笉姝g‘
+ initPosition = Math.min(Math.max(0, initPosition), adapter.getItemsCount() - 1);
+
+ //鍙鐨刬tem鏁扮粍
+ @SuppressLint("DrawAllocation")
+ Object visibles[] = new Object[itemsVisible];
+ //婊氬姩鐨刌鍊奸珮搴﹂櫎鍘绘瘡琛孖tem鐨勯珮搴︼紝寰楀埌婊氬姩浜嗗灏戜釜item锛屽嵆change鏁�
+ change = (int) (totalScrollY / itemHeight);
+ // Log.d("change", "" + change);
+
+ try {
+ //婊氬姩涓疄闄呯殑棰勯�変腑鐨刬tem(鍗崇粡杩囦簡涓棿浣嶇疆鐨刬tem) 锛� 婊戝姩鍓嶇殑浣嶇疆 锛� 婊戝姩鐩稿浣嶇疆
+ preCurrentIndex = initPosition + change % adapter.getItemsCount();
+
+ } catch (ArithmeticException e) {
+ Log.e("WheelView", "鍑洪敊浜嗭紒adapter.getItemsCount() == 0锛岃仈鍔ㄦ暟鎹笉鍖归厤");
+ }
+ if (!isLoop) {//涓嶅惊鐜殑鎯呭喌
+ if (preCurrentIndex < 0) {
+ preCurrentIndex = 0;
+ }
+ if (preCurrentIndex > adapter.getItemsCount() - 1) {
+ preCurrentIndex = adapter.getItemsCount() - 1;
+ }
+ } else {//寰幆
+ if (preCurrentIndex < 0) {//涓句釜渚嬪瓙锛氬鏋滄�绘暟鏄�5锛宲reCurrentIndex 锛� 锛�1锛岄偅涔坧reCurrentIndex鎸夊惊鐜潵璇达紝鍏跺疄鏄�0鐨勪笂闈紝涔熷氨鏄�4鐨勪綅缃�
+ preCurrentIndex = adapter.getItemsCount() + preCurrentIndex;
+ }
+ if (preCurrentIndex > adapter.getItemsCount() - 1) {//鍚岀悊涓婇潰,鑷繁鑴戣ˉ涓�涓�
+ preCurrentIndex = preCurrentIndex - adapter.getItemsCount();
+ }
+ }
+ //璺熸粴鍔ㄦ祦鐣呭害鏈夊叧锛屾�绘粦鍔ㄨ窛绂讳笌姣忎釜item楂樺害鍙栦綑锛屽嵆骞朵笉鏄竴鏍兼牸鐨勬粴鍔紝姣忎釜item涓嶄竴瀹氭粴鍒板搴擱ect閲岀殑锛岃繖涓猧tem瀵瑰簲鏍煎瓙鐨勫亸绉诲��
+ float itemHeightOffset = (totalScrollY % itemHeight);
+
+ // 璁剧疆鏁扮粍涓瘡涓厓绱犵殑鍊�
+ int counter = 0;
+ while (counter < itemsVisible) {
+ int index = preCurrentIndex - (itemsVisible / 2 - counter);//绱㈠紩鍊硷紝鍗冲綋鍓嶅湪鎺т欢涓棿鐨刬tem鐪嬩綔鏁版嵁婧愮殑涓棿锛岃绠楀嚭鐩稿婧愭暟鎹簮鐨刬ndex鍊�
+ //鍒ゆ柇鏄惁寰幆锛屽鏋滄槸寰幆鏁版嵁婧愪篃浣跨敤鐩稿寰幆鐨刾osition鑾峰彇瀵瑰簲鐨刬tem鍊硷紝濡傛灉涓嶆槸寰幆鍒欒秴鍑烘暟鎹簮鑼冨洿浣跨敤""绌虹櫧瀛楃涓插~鍏咃紝鍦ㄧ晫闈笂褰㈡垚绌虹櫧鏃犳暟鎹殑item椤�
+ if (isLoop) {
+ index = getLoopMappingIndex(index);
+ visibles[counter] = adapter.getItem(index);
+ } else if (index < 0) {
+ visibles[counter] = "";
+ } else if (index > adapter.getItemsCount() - 1) {
+ visibles[counter] = "";
+ } else {
+ visibles[counter] = adapter.getItem(index);
+ }
+
+ counter++;
+
+ }
+
+ //缁樺埗涓棿涓ゆ潯妯嚎
+ if (dividerType == DividerType.WRAP) {//妯嚎闀垮害浠呭寘瑁瑰唴瀹�
+ float startX;
+ float endX;
+
+ if (TextUtils.isEmpty(label)) {//闅愯棌Label鐨勬儏鍐�
+ startX = (measuredWidth - maxTextWidth) / 2 - 12;
+ } else {
+ startX = (measuredWidth - maxTextWidth) / 4 - 12;
+ }
+
+ if (startX <= 0) {//濡傛灉瓒呰繃浜哤heelView鐨勮竟缂�
+ startX = 10;
+ }
+ endX = measuredWidth - startX;
+ canvas.drawLine(startX, firstLineY, endX, firstLineY, paintIndicator);
+ canvas.drawLine(startX, secondLineY, endX, secondLineY, paintIndicator);
+ } else {
+ canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
+ canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
+ }
+
+ //鍙樉绀洪�変腑椤筁abel鏂囧瓧鐨勬ā寮忥紝骞朵笖Label鏂囧瓧涓嶄负绌猴紝鍒欒繘琛岀粯鍒�
+ if (!TextUtils.isEmpty(label) && isCenterLabel) {
+ //缁樺埗鏂囧瓧锛岄潬鍙冲苟鐣欏嚭绌洪殭
+ int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText, label);
+ canvas.drawText(label, drawRightContentStart - CENTER_CONTENT_OFFSET, centerY, paintCenterText);
+ }
+
+ counter = 0;
+ while (counter < itemsVisible) {
+ canvas.save();
+ // 寮ч暱 L = itemHeight * counter - itemHeightOffset
+ // 姹傚姬搴� 伪 = L / r (寮ч暱/鍗婂緞) [0,蟺]
+ double radian = ((itemHeight * counter - itemHeightOffset)) / radius;
+ // 寮у害杞崲鎴愯搴�(鎶婂崐鍦嗕互Y杞翠负杞村績鍚戝彸杞�90搴︼紝浣垮叾澶勪簬绗竴璞¢檺鍙婄鍥涜薄闄�
+ // angle [-90掳,90掳]
+ float angle = (float) (90D - (radian / Math.PI) * 180D);//item绗竴椤�,浠�90搴﹀紑濮嬶紝閫愭笎閫掑噺鍒� -90搴�
+
+ // 璁$畻鍙栧�煎彲鑳芥湁缁嗗井鍋忓樊锛屼繚璇佽礋90掳鍒�90掳浠ュ鐨勪笉缁樺埗
+ if (angle >= 90F || angle <= -90F) {
+ canvas.restore();
+ } else {
+ // 鏍规嵁褰撳墠瑙掑害璁$畻鍑哄亸宸郴鏁帮紝鐢ㄤ互鍦ㄧ粯鍒舵椂鎺у埗鏂囧瓧鐨� 姘村钩绉诲姩 閫忔槑搴� 鍊炬枩绋嬪害
+ float offsetCoefficient = (float) Math.pow(Math.abs(angle) / 90f, 2.2);
+ //鑾峰彇鍐呭鏂囧瓧
+ String contentText;
+
+ //濡傛灉鏄痩abel姣忛」閮芥樉绀虹殑妯″紡锛屽苟涓攊tem鍐呭涓嶄负绌恒�乴abel 涔熶笉涓虹┖
+ if (!isCenterLabel && !TextUtils.isEmpty(label) && !TextUtils.isEmpty(getContentText(visibles[counter]))) {
+ contentText = getContentText(visibles[counter]) + label;
+ } else {
+ contentText = getContentText(visibles[counter]);
+ }
+
+ reMeasureTextSize(contentText);
+ //璁$畻寮�濮嬬粯鍒剁殑浣嶇疆
+ measuredCenterContentStart(contentText);
+ measuredOutContentStart(contentText);
+ float translateY = (float) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
+ //鏍规嵁Math.sin(radian)鏉ユ洿鏀筩anvas鍧愭爣绯诲師鐐癸紝鐒跺悗缂╂斁鐢诲竷锛屼娇寰楁枃瀛楅珮搴﹁繘琛岀缉鏀撅紝褰㈡垚寮у舰3d瑙嗚宸�
+ canvas.translate(0.0F, translateY);
+// canvas.scale(1.0F, (float) Math.sin(radian));
+ if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) {
+ // 鏉$洰缁忚繃绗竴鏉$嚎
+ canvas.save();
+ canvas.clipRect(0, 0, measuredWidth, firstLineY - translateY);
+ canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT);
+ canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
+ canvas.restore();
+ canvas.save();
+ canvas.clipRect(0, firstLineY - translateY, measuredWidth, (int) (itemHeight));
+ canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F);
+ canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTER_CONTENT_OFFSET, paintCenterText);
+ canvas.restore();
+ } else if (translateY <= secondLineY && maxTextHeight + translateY >= secondLineY) {
+ // 鏉$洰缁忚繃绗簩鏉$嚎
+ canvas.save();
+ canvas.clipRect(0, 0, measuredWidth, secondLineY - translateY);
+ canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F);
+ canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTER_CONTENT_OFFSET, paintCenterText);
+ canvas.restore();
+ canvas.save();
+ canvas.clipRect(0, secondLineY - translateY, measuredWidth, (int) (itemHeight));
+ canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT);
+ canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
+ canvas.restore();
+ } else if (translateY >= firstLineY && maxTextHeight + translateY <= secondLineY) {
+ // 涓棿鏉$洰
+ // canvas.clipRect(0, 0, measuredWidth, maxTextHeight);
+ //璁╂枃瀛楀眳涓�
+ float Y = maxTextHeight - CENTER_CONTENT_OFFSET;//鍥犱负鍦嗗姬瑙掓崲绠楃殑鍚戜笅鍙栧�硷紝瀵艰嚧瑙掑害绋嶅井鏈夌偣鍋忓樊锛屽姞涓婄敾绗旂殑鍩虹嚎浼氬亸涓婏紝鍥犳闇�瑕佸亸绉婚噺淇涓�涓�
+ canvas.drawText(contentText, drawCenterContentStart, Y, paintCenterText);
+
+ //璁剧疆閫変腑椤�
+ selectedItem = preCurrentIndex - (itemsVisible / 2 - counter);
+
+ } else {
+ // 鍏朵粬鏉$洰
+ canvas.save();
+ canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
+ canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT);
+ // 鎺у埗鏂囧瓧鍊炬枩瑙掑害
+ paintOuterText.setTextSkewX((textXOffset == 0 ? 0 : (textXOffset > 0 ? 1 : -1)) * (angle > 0 ? -1 : 1) * DEFAULT_TEXT_TARGET_SKEW_X * offsetCoefficient);
+ // 鎺у埗閫忔槑搴�
+ paintOuterText.setAlpha((int) ((1 - offsetCoefficient) * 255));
+ // 鎺у埗鏂囧瓧姘村钩鍋忕Щ璺濈
+ canvas.drawText(contentText, drawOutContentStart + textXOffset * offsetCoefficient, maxTextHeight, paintOuterText);
+ canvas.restore();
+ }
+ canvas.restore();
+ paintCenterText.setTextSize(textSize);
+ }
+ counter++;
+ }
+ }
+
+ /**
+ * reset the size of the text Let it can fully display
+ *
+ * @param contentText item text content.
+ */
+ private void reMeasureTextSize(String contentText) {
+ Rect rect = new Rect();
+ paintCenterText.getTextBounds(contentText, 0, contentText.length(), rect);
+ int width = rect.width();
+ int size = textSize;
+ while (width > measuredWidth) {
+ size--;
+ //璁剧疆2鏉℃í绾夸腑闂寸殑鏂囧瓧澶у皬
+ paintCenterText.setTextSize(size);
+ paintCenterText.getTextBounds(contentText, 0, contentText.length(), rect);
+ width = rect.width();
+ }
+ //璁剧疆2鏉℃í绾垮闈㈢殑鏂囧瓧澶у皬
+ paintOuterText.setTextSize(size);
+ }
+
+
+ //閫掑綊璁$畻鍑哄搴旂殑index
+ private int getLoopMappingIndex(int index) {
+ if (index < 0) {
+ index = index + adapter.getItemsCount();
+ index = getLoopMappingIndex(index);
+ } else if (index > adapter.getItemsCount() - 1) {
+ index = index - adapter.getItemsCount();
+ index = getLoopMappingIndex(index);
+ }
+ return index;
+ }
+
+ /**
+ * 鑾峰彇鎵�鏄剧ず鐨勬暟鎹簮
+ *
+ * @param item data resource
+ * @return 瀵瑰簲鏄剧ず鐨勫瓧绗︿覆
+ */
+ private String getContentText(Object item) {
+ if (item == null) {
+ return "";
+ } else if (item instanceof IPickerViewData) {
+ return ((IPickerViewData) item).getPickerViewText();
+ } else if (item instanceof Integer) {
+ //濡傛灉涓烘暣褰㈠垯鏈�灏戜繚鐣欎袱浣嶆暟.
+ return getFixNum((int) item);
+ }
+ return item.toString();
+ }
+
+ private String getFixNum(int timeNum) {
+ return timeNum >= 0 && timeNum < 10 ? TIME_NUM[timeNum] : String.valueOf(timeNum);
+ }
+
+ private void measuredCenterContentStart(String content) {
+ Rect rect = new Rect();
+ paintCenterText.getTextBounds(content, 0, content.length(), rect);
+ switch (mGravity) {
+ case Gravity.CENTER://鏄剧ず鍐呭灞呬腑
+ if (isOptions || label == null || label.equals("") || !isCenterLabel) {
+ drawCenterContentStart = (int) ((measuredWidth - rect.width()) * 0.5);
+ } else {//鍙樉绀轰腑闂磍abel鏃讹紝鏃堕棿閫夋嫨鍣ㄥ唴瀹瑰亸宸︿竴鐐癸紝鐣欏嚭绌洪棿缁樺埗鍗曚綅鏍囩
+ drawCenterContentStart = (int) ((measuredWidth - rect.width()) * 0.25);
+ }
+ break;
+ case Gravity.LEFT:
+ drawCenterContentStart = 0;
+ break;
+ case Gravity.RIGHT://娣诲姞鍋忕Щ閲�
+ drawCenterContentStart = measuredWidth - rect.width() - (int) CENTER_CONTENT_OFFSET;
+ break;
+ }
+ }
+
+ private void measuredOutContentStart(String content) {
+ Rect rect = new Rect();
+ paintOuterText.getTextBounds(content, 0, content.length(), rect);
+ switch (mGravity) {
+ case Gravity.CENTER:
+ if (isOptions || label == null || label.equals("") || !isCenterLabel) {
+ drawOutContentStart = (int) ((measuredWidth - rect.width()) * 0.5);
+ } else {//鍙樉绀轰腑闂磍abel鏃讹紝鏃堕棿閫夋嫨鍣ㄥ唴瀹瑰亸宸︿竴鐐癸紝鐣欏嚭绌洪棿缁樺埗鍗曚綅鏍囩
+ drawOutContentStart = (int) ((measuredWidth - rect.width()) * 0.25);
+ }
+ break;
+ case Gravity.LEFT:
+ drawOutContentStart = 0;
+ break;
+ case Gravity.RIGHT:
+ drawOutContentStart = measuredWidth - rect.width() - (int) CENTER_CONTENT_OFFSET;
+ break;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ this.widthMeasureSpec = widthMeasureSpec;
+ reMeasure();
+ setMeasuredDimension(measuredWidth, measuredHeight);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean eventConsumed = gestureDetector.onTouchEvent(event);
+ boolean isIgnore = false;//瓒呰繃杈圭晫婊戝姩鏃讹紝涓嶅啀缁樺埗UI銆�
+
+ float top = -initPosition * itemHeight;
+ float bottom = (adapter.getItemsCount() - 1 - initPosition) * itemHeight;
+ float ratio = 0.25f;
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ startTime = System.currentTimeMillis();
+ cancelFuture();
+ previousY = event.getRawY();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ float dy = previousY - event.getRawY();
+ previousY = event.getRawY();
+ totalScrollY = totalScrollY + dy;
+
+ // normal mode銆�
+ if (!isLoop) {
+ if ((totalScrollY - itemHeight * ratio < top && dy < 0)
+ || (totalScrollY + itemHeight * ratio > bottom && dy > 0)) {
+ //蹇粦鍔ㄥ埌杈圭晫浜嗭紝璁剧疆宸叉粦鍔ㄥ埌杈圭晫鐨勬爣蹇�
+ totalScrollY -= dy;
+ isIgnore = true;
+ } else {
+ isIgnore = false;
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ default:
+ if (!eventConsumed) {//鏈秷璐规帀浜嬩欢
+
+ /**
+ *@describe <鍏充簬寮ч暱鐨勮绠�>
+ *
+ * 寮ч暱鍏紡锛� L = 伪*R
+ * 鍙嶄綑寮﹀叕寮忥細arccos(cos伪) = 伪
+ * 鐢变簬涔嬪墠鏄湁椤烘椂閽堝亸绉�90搴︼紝
+ * 鎵�浠ュ疄闄呭姬搴﹁寖鍥次�2鐨勫�� 锛毼�2 = 蟺/2-伪 锛埼�=[0,蟺] 伪2 = [-蟺/2,蟺/2]锛�
+ * 鏍规嵁姝e鸡浣欏鸡杞崲鍏紡 cos伪 = sin(蟺/2-伪)
+ * 浠e叆锛屽緱锛� cos伪 = sin(蟺/2-伪) = sin伪2 = (R - y) / R
+ * 鎵�浠ュ姬闀� L = arccos(cos伪)*R = arccos((R - y) / R)*R
+ */
+
+ float y = event.getY();
+ double L = Math.acos((radius - y) / radius) * radius;
+ //item0 鏈変竴鍗婃槸鍦ㄤ笉鍙鍖哄煙锛屾墍浠ラ渶瑕佸姞涓� itemHeight / 2
+ int circlePosition = (int) ((L + itemHeight / 2) / itemHeight);
+ float extraOffset = (totalScrollY % itemHeight + itemHeight) % itemHeight;
+ //宸叉粦鍔ㄧ殑寮ч暱鍊�
+ mOffset = (int) ((circlePosition - itemsVisible / 2) * itemHeight - extraOffset);
+
+ if ((System.currentTimeMillis() - startTime) > 120) {
+ // 澶勭悊鎷栨嫿浜嬩欢
+ smoothScroll(ACTION.DAGGLE);
+ } else {
+ // 澶勭悊鏉$洰鐐瑰嚮浜嬩欢
+ smoothScroll(ACTION.CLICK);
+ }
+ }
+ break;
+ }
+ if (!isIgnore && event.getAction() != MotionEvent.ACTION_DOWN) {
+ invalidate();
+ }
+ return true;
+ }
+
+ public int getItemsCount() {
+ return adapter != null ? adapter.getItemsCount() : 0;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public void isCenterLabel(boolean isCenterLabel) {
+ this.isCenterLabel = isCenterLabel;
+ }
+
+ public void setGravity(int gravity) {
+ this.mGravity = gravity;
+ }
+
+ public int getTextWidth(Paint paint, String str) { //calculate text width
+ int iRet = 0;
+ if (str != null && str.length() > 0) {
+ int len = str.length();
+ float[] widths = new float[len];
+ paint.getTextWidths(str, widths);
+ for (int j = 0; j < len; j++) {
+ iRet += (int) Math.ceil(widths[j]);
+ }
+ }
+ return iRet;
+ }
+
+ public void setIsOptions(boolean options) {
+ isOptions = options;
+ }
+
+ public void setTextColorOut(int textColorOut) {
+
+ this.textColorOut = textColorOut;
+ paintOuterText.setColor(this.textColorOut);
+ }
+
+ public void setTextColorCenter(int textColorCenter) {
+ this.textColorCenter = textColorCenter;
+ paintCenterText.setColor(this.textColorCenter);
+ }
+
+ public void setTextXOffset(int textXOffset) {
+ this.textXOffset = textXOffset;
+ if (textXOffset != 0) {
+ paintCenterText.setTextScaleX(1.0f);
+ }
+ }
+
+ public void setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ paintIndicator.setColor(dividerColor);
+ }
+
+ public void setDividerType(DividerType dividerType) {
+ this.dividerType = dividerType;
+ }
+
+ public void setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ if (lineSpacingMultiplier != 0) {
+ this.lineSpacingMultiplier = lineSpacingMultiplier;
+ judgeLineSpace();
+ }
+ }
+
+ public boolean isLoop() {
+ return isLoop;
+ }
+
+ public float getTotalScrollY() {
+ return totalScrollY;
+ }
+
+ public void setTotalScrollY(float totalScrollY) {
+ this.totalScrollY = totalScrollY;
+ }
+
+ public float getItemHeight() {
+ return itemHeight;
+ }
+
+ public int getInitPosition() {
+ return initPosition;
+ }
+
+ @Override
+ public Handler getHandler() {
+ return handler;
+ }
+}
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/CustomListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/CustomListener.java
new file mode 100644
index 0000000..30e3ee4
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/CustomListener.java
@@ -0,0 +1,13 @@
+package com.hdl.widget.pickerview.listener;
+
+import android.view.View;
+
+/**
+ * Created by KyuYi on 2017/3/2.
+ * E-Mail:kyu_yi@sina.com
+ * 鍔熻兘锛�
+ */
+
+public interface CustomListener {
+ void customLayout(View v);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/ISelectTimeCallback.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/ISelectTimeCallback.java
new file mode 100644
index 0000000..73f65d0
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/ISelectTimeCallback.java
@@ -0,0 +1,10 @@
+package com.hdl.widget.pickerview.listener;
+
+/**
+ * Created by zengsong on 2018/3/21.
+ */
+
+public interface ISelectTimeCallback {
+
+ public void onTimeSelectChanged();
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnDismissListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnDismissListener.java
new file mode 100644
index 0000000..8f1dabd
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnDismissListener.java
@@ -0,0 +1,8 @@
+package com.hdl.widget.pickerview.listener;
+
+/**
+ * Created by Sai on 15/8/9.
+ */
+public interface OnDismissListener {
+ public void onDismiss(Object o);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectChangeListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectChangeListener.java
new file mode 100644
index 0000000..b3dbe7b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectChangeListener.java
@@ -0,0 +1,11 @@
+package com.hdl.widget.pickerview.listener;
+
+/**
+ * Created by xiaosong on 2018/3/20.
+ */
+
+public interface OnOptionsSelectChangeListener {
+
+ void onOptionsSelectChanged(int options1, int options2, int options3);
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectListener.java
new file mode 100644
index 0000000..af6511f
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnOptionsSelectListener.java
@@ -0,0 +1,13 @@
+package com.hdl.widget.pickerview.listener;
+
+import android.view.View;
+
+/**
+ * Created by xiaosong on 2018/3/20.
+ */
+
+public interface OnOptionsSelectListener {
+
+ void onOptionsSelect(int options1, int options2, int options3, View v);
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectChangeListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectChangeListener.java
new file mode 100644
index 0000000..b2e797b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectChangeListener.java
@@ -0,0 +1,12 @@
+package com.hdl.widget.pickerview.listener;
+
+import java.util.Date;
+
+/**
+ * Created by xiaosong on 2018/3/20.
+ */
+
+public interface OnTimeSelectChangeListener {
+
+ void onTimeSelectChanged(Date date);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectListener.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectListener.java
new file mode 100644
index 0000000..4c96f03
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/listener/OnTimeSelectListener.java
@@ -0,0 +1,14 @@
+package com.hdl.widget.pickerview.listener;
+
+import android.view.View;
+
+import java.util.Date;
+
+/**
+ * Created by xiaosong on 2018/3/20.
+ */
+
+public interface OnTimeSelectListener {
+
+ void onTimeSelect(Date date, View v);
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/ChinaDate.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/ChinaDate.java
new file mode 100644
index 0000000..b83e99d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/ChinaDate.java
@@ -0,0 +1,352 @@
+package com.hdl.widget.pickerview.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+public class ChinaDate {
+
+ /**
+ * <lunarInfo 鏁扮粍鍊肩殑璁$畻鍘熺悊>
+ *
+ * 0x浠h〃鍗佸叚杩涘埗锛屽悗闈㈢殑浜斾綅鏁版槸鍗佸叚杩涘埗鏁般��
+ * 涓句釜渚嬪瓙: 1980骞寸殑鏁版嵁鏄� 0x095b0
+ * 浜岃繘鍒�: 0000 1001 0101 1011 0000
+ * 1-4: 琛ㄧず褰撳勾鏄惁涓洪棸骞达紝鏄殑璇濅负1锛屽惁鍒欎负0銆�
+ * 5-16: 涓洪櫎浜嗛棸鏈堝鐨勬甯告湀浠芥槸澶ф湀杩樻槸灏忔湀锛�1涓�30澶╋紝0涓�29澶┿��
+ * 娉ㄦ剰: 浠�1鏈堝埌12鏈堝搴旂殑鏄16浣嶅埌绗�5浣嶃��
+ * 17-20: 闈為棸骞翠负0锛屽ぇ浜�0琛ㄧず闂版湀鏈堜唤锛屼粎褰撳瓨鍦ㄩ棸鏈堢殑鎯呭喌涓嬫湁鎰忎箟銆�
+ */
+ final private static long[] lunarInfo = new long[]{
+ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,//1900-1909
+ 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,//1910-1919
+ 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,//1920-1929
+ 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,//1930-1939
+ 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,//1940-1949
+ 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0,//1950-1959
+ 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,//1960-1969
+ 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6,//1970-1979
+ 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,//1980-1989
+ 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,//1990-1999
+ 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,//2000-2009
+ 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,//2010-2019
+ 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,//2020-2029
+ 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,//2030-2039
+ 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0,//2040-2049
+ 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0,//2050-2059
+ 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4,//2060-2069
+ 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0,//2070-2079
+ 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160,//2080-2089
+ 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099
+ 0x0d520};//2100
+
+ private final static String[] nStr1 = new String[]{"", "姝�", "浜�", "涓�", "鍥�",
+ "浜�", "鍏�", "涓�", "鍏�", "涔�", "鍗�", "鍐�", "鑵�"};
+ private final static String[] Gan = new String[]{"鐢�", "涔�", "涓�", "涓�", "鎴�",
+ "宸�", "搴�", "杈�", "澹�", "鐧�"};
+ private final static String[] Zhi = new String[]{"瀛�", "涓�", "瀵�", "鍗�", "杈�",
+ "宸�", "鍗�", "鏈�", "鐢�", "閰�", "鎴�", "浜�"};
+ private final static String[] Animals = new String[]{"榧�", "鐗�", "铏�", "鍏�",
+ "榫�", "铔�", "椹�", "缇�", "鐚�", "楦�", "鐙�", "鐚�"};
+
+ /**
+ * 浼犲洖鍐滃巻
+ *
+ * @param y 骞寸殑鎬诲ぉ鏁�
+ * @return 鍐滃巻
+ */
+ final private static int lYearDays(int y) {
+ int i, sum = 348;
+ for (i = 0x8000; i > 0x8; i >>= 1) {
+ if ((lunarInfo[y - 1900] & i) != 0)
+ sum += 1;
+ }
+ return (sum + leapDays(y));
+ }
+
+ /**
+ * 浼犲洖鍐滃巻
+ *
+ * @param y 骞撮棸鏈堢殑澶╂暟
+ * @return 鍐滃巻
+ */
+ final public static int leapDays(int y) {
+ if (leapMonth(y) != 0) {
+ if ((lunarInfo[y - 1900] & 0x10000) != 0)
+ return 30;
+ else
+ return 29;
+ } else
+ return 0;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻
+ *
+ * @param y 骞撮棸鍝釜鏈� 1-12 , 娌¢棸浼犲洖 0
+ * @return 鍐滃巻
+ */
+ final public static int leapMonth(int y) {
+ return (int) (lunarInfo[y - 1900] & 0xf);
+ }
+
+ /**
+ * 浼犲洖鍐滃巻 y
+ *
+ * @param y y骞磎鏈堢殑鎬诲ぉ鏁�
+ * @param m y骞磎鏈堢殑鎬诲ぉ鏁�
+ * @return 鍐滃巻
+ */
+ final public static int monthDays(int y, int m) {
+ if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
+ return 29;
+ else
+ return 30;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻
+ *
+ * @param y 骞寸殑鐢熻倴
+ * @return
+ */
+ final public static String AnimalsYear(int y) {
+ return Animals[(y - 4) % 12];
+ }
+
+ /**
+ * 浼犲叆
+ *
+ * @param num 鏈堟棩鐨刼ffset 浼犲洖骞叉敮,0鏄敳瀛�
+ * @return 骞叉敮
+ */
+ final private static String cyclicalm(int num) {
+ return (Gan[num % 10] + Zhi[num % 12]);
+ }
+
+ /**
+ * 浼犲叆 offset 浼犲洖骞叉敮
+ *
+ * @param y 0鏄敳瀛�
+ * @return 骞叉敮
+ */
+ final public static String cyclical(int y) {
+ int num = y - 1900 + 36;
+ return (cyclicalm(num));
+ }
+
+
+ /**
+ * 浼犲嚭y骞磎鏈坉鏃ュ搴旂殑鍐滃巻.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
+ *
+ * @param y 骞�
+ * @param m 鏈�
+ * @param d 鏃�
+ * @return y骞磎鏈坉鏃ュ搴旂殑鍐滃巻
+ */
+ final public static long[] calElement(int y, int m, int d) {
+ long[] nongDate = new long[7];
+ int i = 0, temp = 0, leap = 0;
+ Date baseDate = new GregorianCalendar(0 + 1900, 0, 31).getTime();
+ Date objDate = new GregorianCalendar(y, m - 1, d).getTime();
+ long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;
+ nongDate[5] = offset + 40;
+ nongDate[4] = 14;
+ for (i = 1900; i < 2100 && offset > 0; i++) {
+ temp = lYearDays(i);
+ offset -= temp;
+ nongDate[4] += 12;
+ }
+ if (offset < 0) {
+ offset += temp;
+ i--;
+ nongDate[4] -= 12;
+ }
+ nongDate[0] = i;
+ nongDate[3] = i - 1864;
+ leap = leapMonth(i); // 闂板摢涓湀
+ nongDate[6] = 0;
+ for (i = 1; i < 13 && offset > 0; i++) {
+ // 闂版湀
+ if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {
+ --i;
+ nongDate[6] = 1;
+ temp = leapDays((int) nongDate[0]);
+ } else {
+ temp = monthDays((int) nongDate[0], i);
+ }
+ // 瑙i櫎闂版湀
+ if (nongDate[6] == 1 && i == (leap + 1))
+ nongDate[6] = 0;
+ offset -= temp;
+ if (nongDate[6] == 0)
+ nongDate[4]++;
+ }
+ if (offset == 0 && leap > 0 && i == leap + 1) {
+ if (nongDate[6] == 1) {
+ nongDate[6] = 0;
+ } else {
+ nongDate[6] = 1;
+ --i;
+ --nongDate[4];
+ }
+ }
+ if (offset < 0) {
+ offset += temp;
+ --i;
+ --nongDate[4];
+ }
+ nongDate[1] = i;
+ nongDate[2] = offset + 1;
+ return nongDate;
+ }
+
+ public final static String getChinaDate(int day) {
+ String a = "";
+ if (day == 10)
+ return "鍒濆崄";
+ if (day == 20)
+ return "浜屽崄";
+ if (day == 30)
+ return "涓夊崄";
+ int two = (int) ((day) / 10);
+ if (two == 0)
+ a = "鍒�";
+ if (two == 1)
+ a = "鍗�";
+ if (two == 2)
+ a = "寤�";
+ if (two == 3)
+ a = "涓�";
+ int one = (int) (day % 10);
+ switch (one) {
+ case 1:
+ a += "涓�";
+ break;
+ case 2:
+ a += "浜�";
+ break;
+ case 3:
+ a += "涓�";
+ break;
+ case 4:
+ a += "鍥�";
+ break;
+ case 5:
+ a += "浜�";
+ break;
+ case 6:
+ a += "鍏�";
+ break;
+ case 7:
+ a += "涓�";
+ break;
+ case 8:
+ a += "鍏�";
+ break;
+ case 9:
+ a += "涔�";
+ break;
+ }
+ return a;
+ }
+
+ public static String getCurrentLunarDate() {
+ Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE);
+ int year = today.get(Calendar.YEAR);
+ int month = today.get(Calendar.MONTH) + 1;
+ int date = today.get(Calendar.DATE);
+ long[] l = calElement(year, month, date);
+ StringBuffer sToday = new StringBuffer();
+ try {
+ sToday.append(sdf.format(today.getTime()));
+ sToday.append(" 鍐滃巻");
+ sToday.append(cyclical(year));
+ sToday.append('(');
+ sToday.append(AnimalsYear(year));
+ sToday.append(")骞�");
+ sToday.append(nStr1[(int) l[1]]);
+ sToday.append("鏈�");
+ sToday.append(getChinaDate((int) (l[2])));
+ return sToday.toString();
+ } finally {
+ sToday = null;
+ }
+ }
+
+ public static String oneDay(int year, int month, int day) {
+ // Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE);
+ long[] l = calElement(year, month, day);
+ StringBuffer sToday = new StringBuffer();
+ try {
+ // sToday.append(sdf.format(today.getTime()));
+ sToday.append(" 鍐滃巻");
+ sToday.append(cyclical(year));
+ sToday.append('(');
+ sToday.append(AnimalsYear(year));
+ sToday.append(")骞�");
+ sToday.append(nStr1[(int) l[1]]);
+ sToday.append("鏈�");
+ sToday.append(getChinaDate((int) (l[2])));
+ return sToday.toString();
+ } finally {
+ sToday = null;
+ }
+ }
+
+ private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy骞碝鏈坉鏃� EEEEE");
+
+
+ /**
+ * @param lunarYear 鍐滃巻骞翠唤
+ * @return String of Ganzhi: 鐢插瓙骞�
+ * 鐢蹭箼涓欎竵鎴婂繁搴氳緵澹櫢
+ * 瀛愪笐瀵呭嵂杈板烦鏃犱负鐢抽厜鎴屼亥
+ */
+ public static String getLunarYearText(int lunarYear) {
+ return Gan[(lunarYear - 4) % 10] + Zhi[(lunarYear - 4) % 12] + "骞�";
+ }
+
+
+ public static ArrayList<String> getYears(int startYear, int endYear) {
+ ArrayList<String> years = new ArrayList<>();
+ for (int i = startYear; i < endYear; i++) {
+ years.add(String.format("%s(%d)", getLunarYearText(i), i));
+ }
+ return years;
+ }
+
+ /**
+ * 鑾峰彇year骞寸殑鎵�鏈夋湀浠�
+ *
+ * @param year 骞�
+ * @return 鏈堜唤鍒楄〃
+ */
+ public static ArrayList<String> getMonths(int year) {
+ ArrayList<String> baseMonths = new ArrayList<>();
+ for (int i = 1; i < nStr1.length; i++) {
+ baseMonths.add(nStr1[i] + "鏈�");
+ }
+ if (leapMonth(year) != 0) {
+ baseMonths.add(leapMonth(year), "闂�" + nStr1[leapMonth(year)] + "鏈�");
+ }
+ return baseMonths;
+ }
+
+ /**
+ * 鑾峰彇姣忔湀鍐滃巻鏄剧ず鍚嶇О
+ *
+ * @param maxDay 澶�
+ * @return 鍚嶇О鍒楄〃
+ */
+ public static ArrayList<String> getLunarDays(int maxDay) {
+ ArrayList<String> days = new ArrayList<>();
+ for (int i = 1; i <= maxDay; i++) {
+ days.add(getChinaDate(i));
+ }
+ return days;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/LunarCalendar.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/LunarCalendar.java
new file mode 100644
index 0000000..244f907
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/LunarCalendar.java
@@ -0,0 +1,429 @@
+package com.hdl.widget.pickerview.utils;
+
+import android.util.Log;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * author: Jerry on 2016/7/11 11:29.
+ * description:宸ュ叿绫伙紝瀹炵幇鍏啘鍘嗕簰杞�
+ */
+public class LunarCalendar {
+
+ /**
+ * 鏀寔杞崲鐨勬渶灏忓啘鍘嗗勾浠�
+ */
+ public static final int MIN_YEAR = 1900;
+ /**
+ * 鏀寔杞崲鐨勬渶澶у啘鍘嗗勾浠�
+ */
+ public static final int MAX_YEAR = 2099;
+
+ /**
+ * 鍏巻姣忔湀鍓嶇殑澶╂暟
+ */
+ private static final int DAYS_BEFORE_MONTH[] = {0, 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334, 365};
+
+ /**
+ * 鐢ㄦ潵琛ㄧず1900骞村埌2099骞撮棿鍐滃巻骞翠唤鐨勭浉鍏充俊鎭紝鍏�24浣峛it鐨�16杩涘埗琛ㄧず锛屽叾涓細
+ * 1. 鍓�4浣嶈〃绀鸿骞撮棸鍝釜鏈堬紱
+ * 2. 5-17浣嶈〃绀哄啘鍘嗗勾浠�13涓湀鐨勫ぇ灏忔湀鍒嗗竷锛�0琛ㄧず灏忥紝1琛ㄧず澶э紱
+ * 3. 鏈�鍚�7浣嶈〃绀哄啘鍘嗗勾棣栵紙姝f湀鍒濅竴锛夊搴旂殑鍏巻鏃ユ湡銆�
+ * <p>
+ * 浠�2014骞寸殑鏁版嵁0x955ABF涓轰緥璇存槑锛�
+ * 1001 0101 0101 1010 1011 1111
+ * 闂颁節鏈� 鍐滃巻姝f湀鍒濅竴瀵瑰簲鍏巻1鏈�31鍙�
+ */
+ private static final int LUNAR_INFO[] = {
+ 0x84B6BF,/*1900*/
+ 0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A,/*1901-1910*/
+ 0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754,/*1911-1920*/
+ 0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E,/*1921-1930*/
+ 0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48,/*1931-1940*/
+ 0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51,/*1941-1950*/
+ 0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x6AD53C,/*1951-1960*/
+ 0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46,/*1961-1970*/
+ 0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50,/*1971-1980*/
+ 0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x095746, 0x5497BB,/*1981-1990*/
+ 0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645,/*1991-2000*/
+ 0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E,/*2001-2010*/
+ 0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9,/*2011-2020*/
+ 0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x6a573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43,/*2021-2030*/
+ 0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C,/*2031-2040*/
+ 0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37,/*2041-2050*/
+ 0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06AA44, 0x4AB638, 0x0AAE4C, 0x092E42,/*2051-2060*/
+ 0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B,/*2061-2070*/
+ 0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6,/*2071-2080*/
+ 0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E,/*2081-2090*/
+ 0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5 /*2091-2099*/
+ };
+ private static int[] solar_1_1 = {1887, 0xec04c, 0xec23f, 0xec435, 0xec649,
+ 0xec83e, 0xeca51, 0xecc46, 0xece3a, 0xed04d, 0xed242, 0xed436,
+ 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244,
+ 0xee439, 0xee64d, 0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052,
+ 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41,
+ 0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d,
+ 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651, 0xf1846, 0xf1a3a,
+ 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848,
+ 0xf2a3b, 0xf2c4f, 0xf2e45, 0xf3039, 0xf324d, 0xf3442, 0xf3636,
+ 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443,
+ 0xf4638, 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f,
+ 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49, 0xf603e,
+ 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b,
+ 0xf703f, 0xf7252, 0xf7447, 0xf763c, 0xf7850, 0xf7a45, 0xf7c39,
+ 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46,
+ 0xf8c3b, 0xf8e4f, 0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853,
+ 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641,
+ 0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e,
+ 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53, 0xfc048, 0xfc23c,
+ 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a,
+ 0xfd23d, 0xfd451, 0xfd646, 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37,
+ 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44,
+ 0xfee38, 0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51,
+ 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437, 0x10064b, 0x100841,
+ 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438,
+ 0x10164c, 0x101842, 0x101a35, 0x101c49, 0x101e3d, 0x102051,
+ 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b,
+ 0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845,
+ 0x103a38, 0x103c4c, 0x103e42, 0x104036, 0x104249, 0x10443d,
+ 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038,
+ 0x10524a, 0x10543e, 0x105652, 0x105847, 0x105a3b, 0x105c4f,
+ 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849,
+ 0x106a3d, 0x106c51, 0x106e47, 0x10703c, 0x10724f, 0x107444,
+ 0x107638, 0x10784c, 0x107a3f, 0x107c53, 0x107e48};
+ private static int[] lunar_month_days = {1887, 0x1694, 0x16aa, 0x4ad5,
+ 0xab6, 0xc4b7, 0x4ae, 0xa56, 0xb52a, 0x1d2a, 0xd54, 0x75aa, 0x156a,
+ 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4,
+ 0x135a, 0x495d, 0x95c, 0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8,
+ 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a,
+ 0xda8, 0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94,
+ 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d, 0x192a,
+ 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b,
+ 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5, 0x9b4, 0x14b6, 0x6a57,
+ 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae,
+ 0x14ae, 0xa4c, 0x7d26, 0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d,
+ 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da,
+ 0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4,
+ 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a, 0x1d4a, 0x10d65,
+ 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a,
+ 0x4b55, 0xad4, 0xf55b, 0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694,
+ 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526,
+ 0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c,
+ 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da, 0x1695d, 0x95a, 0x149a,
+ 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936,
+ 0xf497, 0x1496, 0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e,
+ 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c,
+ 0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4,
+ 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a, 0x1694, 0xd6aa, 0x15aa,
+ 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa,
+ 0xa9b5, 0x96c, 0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54,
+ 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25, 0x1aa4,
+ 0xfb52, 0x16b4, 0xaba, 0xa95b, 0x936, 0x1496, 0x9a4b, 0x154a,
+ 0x136a5, 0xda4, 0x15ac};
+
+ /**
+ * 灏嗗啘鍘嗘棩鏈熻浆鎹负鍏巻鏃ユ湡
+ *
+ * @param year 鍐滃巻骞翠唤
+ * @param month 鍐滃巻鏈�
+ * @param monthDay 鍐滃巻鏃�
+ * @param isLeapMonth 璇ユ湀鏄惁鏄棸鏈�
+ * @return 杩斿洖鍐滃巻鏃ユ湡瀵瑰簲鐨勫叕鍘嗘棩鏈燂紝year0, month1, day2.
+ */
+ public static final int[] lunarToSolar(int year, int month, int monthDay,
+ boolean isLeapMonth) {
+ int dayOffset;
+ int leapMonth;
+ int i;
+
+ if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12
+ || monthDay < 1 || monthDay > 30) {
+ throw new IllegalArgumentException(
+ "Illegal lunar date, must be like that:\n\t" +
+ "year : 1900~2099\n\t" +
+ "month : 1~12\n\t" +
+ "day : 1~30");
+ }
+
+ dayOffset = (LUNAR_INFO[year - MIN_YEAR] & 0x001F) - 1;
+
+ if (((LUNAR_INFO[year - MIN_YEAR] & 0x0060) >> 5) == 2)
+ dayOffset += 31;
+
+ for (i = 1; i < month; i++) {
+ if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (i - 1))) == 0)
+ dayOffset += 29;
+ else
+ dayOffset += 30;
+ }
+
+ dayOffset += monthDay;
+ leapMonth = (LUNAR_INFO[year - MIN_YEAR] & 0xf00000) >> 20;
+
+ // 杩欎竴骞存湁闂版湀
+ if (leapMonth != 0) {
+ if (month > leapMonth || (month == leapMonth && isLeapMonth)) {
+ if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (month - 1))) == 0)
+ dayOffset += 29;
+ else
+ dayOffset += 30;
+ }
+ }
+
+ if (dayOffset > 366 || (year % 4 != 0 && dayOffset > 365)) {
+ year += 1;
+ if (year % 4 == 1)
+ dayOffset -= 366;
+ else
+ dayOffset -= 365;
+ }
+
+ int[] solarInfo = new int[3];
+ for (i = 1; i < 13; i++) {
+ int iPos = DAYS_BEFORE_MONTH[i];
+ if (year % 4 == 0 && i > 2) {
+ iPos += 1;
+ }
+
+ if (year % 4 == 0 && i == 2 && iPos + 1 == dayOffset) {
+ solarInfo[1] = i;
+ solarInfo[2] = dayOffset - 31;
+ break;
+ }
+
+ if (iPos >= dayOffset) {
+ solarInfo[1] = i;
+ iPos = DAYS_BEFORE_MONTH[i - 1];
+ if (year % 4 == 0 && i > 2) {
+ iPos += 1;
+ }
+ if (dayOffset > iPos)
+ solarInfo[2] = dayOffset - iPos;
+ else if (dayOffset == iPos) {
+ if (year % 4 == 0 && i == 2)
+ solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1] + 1;
+ else
+ solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1];
+
+ } else
+ solarInfo[2] = dayOffset;
+ break;
+ }
+ }
+ solarInfo[0] = year;
+
+ return solarInfo;
+ }
+
+ public static final int[] solarToLunar(int year, int month, int monthDay) {
+ int[] lunarDate = new int[4];
+
+ int index = year - solar_1_1[0];
+ int data = (year << 9) | (month << 5)
+ | (monthDay);
+ int solar11 = 0;
+ if (solar_1_1[index] > data) {
+ index--;
+ }
+ solar11 = solar_1_1[index];
+ int y = getBitInt(solar11, 12, 9);
+ int m = getBitInt(solar11, 4, 5);
+ int d = getBitInt(solar11, 5, 0);
+ long offset = solarToInt(year, month,
+ monthDay) - solarToInt(y, m, d);
+
+ int days = lunar_month_days[index];
+ int leap = getBitInt(days, 4, 13);
+
+ int lunarY = index + solar_1_1[0];
+ int lunarM = 1;
+ int lunarD = 1;
+ offset += 1;
+
+ for (int i = 0; i < 13; i++) {
+ int dm = getBitInt(days, 1, 12 - i) == 1 ? 30 : 29;
+ if (offset > dm) {
+ lunarM++;
+ offset -= dm;
+ } else {
+ break;
+ }
+ }
+ lunarD = (int) (offset);
+ lunarDate[0] = lunarY;
+ lunarDate[1] = lunarM;
+ boolean isLeap = false;
+ if (leap != 0 && lunarM > leap) {
+ lunarDate[1] = lunarM - 1;
+ if (lunarM == leap + 1) {
+ isLeap = true;
+ }
+ }
+
+ lunarDate[2] = lunarD;
+ lunarDate[3] = isLeap ? 1 : 0;
+ //Log.i("----------->",year+"-"+month+"-"+monthDay+"====>"+lunarDate[0]+"-"+lunarDate[1]+"-"+lunarDate[2]+"-"+lunarDate[3]);
+ return lunarDate;
+ }
+
+
+ /**
+ * 灏嗗叕鍘嗘棩鏈熻浆鎹负鍐滃巻鏃ユ湡锛屼笖鏍囪瘑鏄惁鏄棸鏈�
+ *
+ * @param year
+ * @param month
+ * @param monthDay
+ * @return 杩斿洖鍏巻鏃ユ湡瀵瑰簲鐨勫啘鍘嗘棩鏈燂紝year0锛宮onth1锛宒ay2锛宭eap3
+ * @deprecated 涓嶅噯纭�
+ */
+ @Deprecated
+ public static final int[] solarToLunarDeprecated(int year, int month, int monthDay) {
+ int[] lunarDate = new int[4];
+ Date baseDate = new GregorianCalendar(1900, 0, 31).getTime();
+ Date objDate = new GregorianCalendar(year, month - 1, monthDay).getTime();
+ int offset = (int) ((objDate.getTime() - baseDate.getTime()) / 86400000L);
+
+ // 鐢╫ffset鍑忓幓姣忓啘鍘嗗勾鐨勫ぉ鏁拌绠楀綋澶╂槸鍐滃巻绗嚑澶�
+ // iYear鏈�缁堢粨鏋滄槸鍐滃巻鐨勫勾浠�, offset鏄綋骞寸殑绗嚑澶�
+ int iYear, daysOfYear = 0;
+ for (iYear = MIN_YEAR; iYear <= MAX_YEAR && offset > 0; iYear++) {
+ daysOfYear = daysInLunarYear(iYear);
+ offset -= daysOfYear;
+ }
+ if (offset < 0) {
+ offset += daysOfYear;
+ iYear--;
+ }
+
+ // 鍐滃巻骞翠唤
+ lunarDate[0] = iYear;
+
+ int leapMonth = leapMonth(iYear); // 闂板摢涓湀,1-12
+ boolean isLeap = false;
+ // 鐢ㄥ綋骞寸殑澶╂暟offset,閫愪釜鍑忓幓姣忔湀锛堝啘鍘嗭級鐨勫ぉ鏁帮紝姹傚嚭褰撳ぉ鏄湰鏈堢殑绗嚑澶�
+ int iMonth, daysOfMonth = 0;
+ for (iMonth = 1; iMonth <= 13 && offset > 0; iMonth++) {
+ daysOfMonth = daysInLunarMonth(iYear, iMonth);
+ offset -= daysOfMonth;
+ }
+ // 褰撳墠鏈堣秴杩囬棸鏈堬紝瑕佹牎姝�
+ if (leapMonth != 0 && iMonth > leapMonth) {
+ --iMonth;
+ Log.i("----------->", year + "-" + month + "-" + monthDay + "====>" + iMonth + "-" + leapMonth);
+ if (iMonth == leapMonth) {
+ isLeap = true;
+ }
+ }
+ // offset灏忎簬0鏃讹紝涔熻鏍℃
+ if (offset < 0) {
+ offset += daysOfMonth;
+ --iMonth;
+ }
+
+ lunarDate[1] = iMonth;
+ lunarDate[2] = offset + 1;
+ lunarDate[3] = isLeap ? 1 : 0;
+
+ //Log.i("----------->",year+"-"+month+"-"+monthDay+"====>"+lunarDate[0]+"-"+lunarDate[1]+"-"+lunarDate[2]+"-"+lunarDate[3]);
+ return lunarDate;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻year骞磎onth鏈堢殑鎬诲ぉ鏁�
+ *
+ * @param year 瑕佽绠楃殑骞翠唤
+ * @param month 瑕佽绠楃殑鏈�
+ * @return 浼犲洖澶╂暟
+ */
+ final public static int daysInMonth(int year, int month) {
+ return daysInMonth(year, month, false);
+ }
+
+ /**
+ * 浼犲洖鍐滃巻year骞磎onth鏈堢殑鎬诲ぉ鏁�
+ *
+ * @param year 瑕佽绠楃殑骞翠唤
+ * @param month 瑕佽绠楃殑鏈�
+ * @param leap 褰撴湀鏄惁鏄棸鏈�
+ * @return 浼犲洖澶╂暟锛屽鏋滈棸鏈堟槸閿欒鐨勶紝杩斿洖0.
+ */
+ public static final int daysInMonth(int year, int month, boolean leap) {
+ int leapMonth = leapMonth(year);
+ int offset = 0;
+
+ // 濡傛灉鏈勾鏈夐棸鏈堜笖month澶т簬闂版湀鏃讹紝闇�瑕佹牎姝�
+ if (leapMonth != 0 && month > leapMonth) {
+ offset = 1;
+ }
+
+ // 涓嶈�冭檻闂版湀
+ if (!leap) {
+ return daysInLunarMonth(year, month + offset);
+ } else {
+ // 浼犲叆鐨勯棸鏈堟槸姝g‘鐨勬湀浠�
+ if (leapMonth != 0 && leapMonth == month) {
+ return daysInLunarMonth(year, month + 1);
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻 year骞寸殑鎬诲ぉ鏁�
+ *
+ * @param year 灏嗚璁$畻鐨勫勾浠�
+ * @return 杩斿洖浼犲叆骞翠唤鐨勬�诲ぉ鏁�
+ */
+ private static int daysInLunarYear(int year) {
+ int i, sum = 348;
+ if (leapMonth(year) != 0) {
+ sum = 377;
+ }
+ int monthInfo = LUNAR_INFO[year - MIN_YEAR] & 0x0FFF80;
+ for (i = 0x80000; i > 0x7; i >>= 1) {
+ if ((monthInfo & i) != 0)
+ sum += 1;
+ }
+ return sum;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻 year骞磎onth鏈堢殑鎬诲ぉ鏁帮紝鎬诲叡鏈�13涓湀鍖呮嫭闂版湀
+ *
+ * @param year 灏嗚璁$畻鐨勫勾浠�
+ * @param month 灏嗚璁$畻鐨勬湀浠�
+ * @return 浼犲洖鍐滃巻 year骞磎onth鏈堢殑鎬诲ぉ鏁�
+ */
+ private static int daysInLunarMonth(int year, int month) {
+ if ((LUNAR_INFO[year - MIN_YEAR] & (0x100000 >> month)) == 0)
+ return 29;
+ else
+ return 30;
+ }
+
+ /**
+ * 浼犲洖鍐滃巻 year骞撮棸鍝釜鏈� 1-12 , 娌¢棸浼犲洖 0
+ *
+ * @param year 灏嗚璁$畻鐨勫勾浠�
+ * @return 浼犲洖鍐滃巻 year骞撮棸鍝釜鏈�1-12, 娌¢棸浼犲洖 0
+ */
+ public static int leapMonth(int year) {
+ return (int) ((LUNAR_INFO[year - MIN_YEAR] & 0xF00000)) >> 20;
+ }
+
+
+ private static int getBitInt(int data, int length, int shift) {
+ return (data & (((1 << length) - 1) << shift)) >> shift;
+ }
+
+ private static long solarToInt(int y, int m, int d) {
+ m = (m + 9) % 12;
+ y = y - m / 10;
+ return 365 * y + y / 4 - y / 100 + y / 400 + (m * 306 + 5) / 10
+ + (d - 1);
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/PickerViewAnimateUtil.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/PickerViewAnimateUtil.java
new file mode 100644
index 0000000..ba327e0
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/utils/PickerViewAnimateUtil.java
@@ -0,0 +1,26 @@
+package com.hdl.widget.pickerview.utils;
+
+import android.view.Gravity;
+
+import com.hdl.widgetxm.R;
+
+/**
+ * Created by Sai on 15/8/9.
+ */
+public class PickerViewAnimateUtil {
+ private static final int INVALID = -1;
+ /**
+ * Get default animation resource when not defined by the user
+ *
+ * @param gravity the animGravity of the dialog
+ * @param isInAnimation determine if is in or out animation. true when is is
+ * @return the id of the animation resource
+ */
+ public static int getAnimationResource(int gravity, boolean isInAnimation) {
+ switch (gravity) {
+ case Gravity.BOTTOM:
+ return isInAnimation ? R.anim.pickerview_slide_in_bottom : R.anim.pickerview_slide_out_bottom;
+ }
+ return INVALID;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/BasePickerView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/BasePickerView.java
new file mode 100644
index 0000000..f2e2d17
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/BasePickerView.java
@@ -0,0 +1,361 @@
+package com.hdl.widget.pickerview.view;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.configure.PickerOptions;
+import com.hdl.widget.pickerview.listener.OnDismissListener;
+import com.hdl.widget.pickerview.utils.PickerViewAnimateUtil;
+
+/**
+ * Created by Sai on 15/11/22.
+ * 绮句豢iOSPickerViewController鎺т欢
+ */
+public class BasePickerView {
+
+ private Context context;
+ protected ViewGroup contentContainer;
+ private ViewGroup rootView;//闄勫姞View 鐨� 鏍筕iew
+ private ViewGroup dialogView;//闄勫姞Dialog 鐨� 鏍筕iew
+
+ protected PickerOptions mPickerOptions;
+ private OnDismissListener onDismissListener;
+ private boolean dismissing;
+
+ private Animation outAnim;
+ private Animation inAnim;
+ private boolean isShowing;
+
+ protected int animGravity = Gravity.BOTTOM;
+
+ private Dialog mDialog;
+ protected View clickView;//鏄�氳繃鍝釜View寮瑰嚭鐨�
+ private boolean isAnim = true;
+
+ public BasePickerView(Context context) {
+ this.context = context;
+ }
+
+
+ protected void initViews() {
+
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);
+
+ LayoutInflater layoutInflater = LayoutInflater.from(context);
+ if (isDialog()) {
+ //濡傛灉鏄璇濇妯″紡
+ dialogView = (ViewGroup) layoutInflater.inflate(R.layout.hdl_widget_layout_basepickerview, null, false);
+ //璁剧疆鐣岄潰鐨勮儗鏅负閫忔槑
+ dialogView.setBackgroundColor(Color.TRANSPARENT);
+ //杩欎釜鏄湡姝h鍔犺浇閫夋嫨鍣ㄧ殑鐖跺竷灞�
+ contentContainer = (ViewGroup) dialogView.findViewById(R.id.content_container);
+ //璁剧疆瀵硅瘽妗� 榛樿宸﹀彸闂磋窛灞忓箷30
+ params.leftMargin = 30;
+ params.rightMargin = 30;
+ contentContainer.setLayoutParams(params);
+ //鍒涘缓瀵硅瘽妗�
+ createDialog();
+ //缁欒儗鏅缃偣鍑讳簨浠�,杩欐牱褰撶偣鍑诲唴瀹逛互澶栫殑鍦版柟浼氬叧闂晫闈�
+ dialogView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ dismiss();
+ }
+ });
+ } else {
+ //濡傛灉鍙槸瑕佹樉绀哄湪灞忓箷鐨勪笅鏂�
+ //decorView鏄痑ctivity鐨勬牴View,鍖呭惈 contentView 鍜� titleView
+ if (mPickerOptions.decorView == null) {
+ mPickerOptions.decorView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
+ }
+ //灏嗘帶浠舵坊鍔犲埌decorView涓�
+ rootView = (ViewGroup) layoutInflater.inflate(R.layout.hdl_widget_layout_basepickerview, mPickerOptions.decorView, false);
+ rootView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ if (mPickerOptions.outSideColor != -1) {
+ rootView.setBackgroundColor(mPickerOptions.outSideColor);
+ }
+ //杩欎釜鏄湡姝h鍔犺浇鏃堕棿閫夊彇鍣ㄧ殑鐖跺竷灞�
+ contentContainer = (ViewGroup) rootView.findViewById(R.id.content_container);
+ contentContainer.setLayoutParams(params);
+ }
+ setKeyBackCancelable(true);
+ }
+
+ protected void initAnim() {
+ inAnim = getInAnimation();
+ outAnim = getOutAnimation();
+ }
+
+ protected void initEvents() {
+ }
+
+
+ /**
+ * @param v (鏄�氳繃鍝釜View寮瑰嚭鐨�)
+ * @param isAnim 鏄惁鏄剧ず鍔ㄧ敾鏁堟灉
+ */
+ public void show(View v, boolean isAnim) {
+ this.clickView = v;
+ this.isAnim = isAnim;
+ show();
+ }
+
+ public void show(boolean isAnim) {
+ show(null, isAnim);
+ }
+
+ public void show(View v) {
+ this.clickView = v;
+ show();
+ }
+
+
+ /**
+ * 娣诲姞View鍒版牴瑙嗗浘
+ */
+ public void show() {
+ if (isDialog()) {
+ showDialog();
+ } else {
+ if (isShowing()) {
+ return;
+ }
+ isShowing = true;
+ onAttached(rootView);
+ rootView.requestFocus();
+ }
+ }
+
+
+ /**
+ * show鐨勬椂鍊欒皟鐢�
+ *
+ * @param view 杩欎釜View
+ */
+ private void onAttached(View view) {
+ mPickerOptions.decorView.addView(view);
+ if (isAnim) {
+ contentContainer.startAnimation(inAnim);
+ }
+ }
+
+
+ /**
+ * 妫�娴嬭View鏄笉鏄凡缁忔坊鍔犲埌鏍硅鍥�
+ *
+ * @return 濡傛灉瑙嗗浘宸茬粡瀛樺湪璇iew杩斿洖true
+ */
+ public boolean isShowing() {
+ if (isDialog()) {
+ return false;
+ } else {
+ return rootView.getParent() != null || isShowing;
+ }
+
+ }
+
+ public void dismiss() {
+ if (isDialog()) {
+ dismissDialog();
+ } else {
+ if (dismissing) {
+ return;
+ }
+
+ if (isAnim) {
+ //娑堝け鍔ㄧ敾
+ outAnim.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ dismissImmediately();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ contentContainer.startAnimation(outAnim);
+ } else {
+ dismissImmediately();
+ }
+ dismissing = true;
+ }
+
+
+ }
+
+ public void dismissImmediately() {
+
+ mPickerOptions.decorView.post(new Runnable() {
+ @Override
+ public void run() {
+ //浠庢牴瑙嗗浘绉婚櫎
+ mPickerOptions.decorView.removeView(rootView);
+ isShowing = false;
+ dismissing = false;
+ if (onDismissListener != null) {
+ onDismissListener.onDismiss(BasePickerView.this);
+ }
+ }
+ });
+
+
+ }
+
+ private Animation getInAnimation() {
+ int res = PickerViewAnimateUtil.getAnimationResource(this.animGravity, true);
+ return AnimationUtils.loadAnimation(context, res);
+ }
+
+ private Animation getOutAnimation() {
+ int res = PickerViewAnimateUtil.getAnimationResource(this.animGravity, false);
+ return AnimationUtils.loadAnimation(context, res);
+ }
+
+ public BasePickerView setOnDismissListener(OnDismissListener onDismissListener) {
+ this.onDismissListener = onDismissListener;
+ return this;
+ }
+
+ public void setKeyBackCancelable(boolean isCancelable) {
+
+ ViewGroup View;
+ if (isDialog()) {
+ View = dialogView;
+ } else {
+ View = rootView;
+ }
+
+ View.setFocusable(isCancelable);
+ View.setFocusableInTouchMode(isCancelable);
+ if (isCancelable) {
+ View.setOnKeyListener(onKeyBackListener);
+ } else {
+ View.setOnKeyListener(null);
+ }
+ }
+
+ private View.OnKeyListener onKeyBackListener = new View.OnKeyListener() {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == MotionEvent.ACTION_DOWN && isShowing()) {
+ dismiss();
+ return true;
+ }
+ return false;
+ }
+ };
+
+ protected BasePickerView setOutSideCancelable(boolean isCancelable) {
+
+ if (rootView != null) {
+ View view = rootView.findViewById(R.id.outmost_container);
+
+ if (isCancelable) {
+ view.setOnTouchListener(onCancelableTouchListener);
+ } else {
+ view.setOnTouchListener(null);
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * 璁剧疆瀵硅瘽妗嗘ā寮忔槸鍚﹀彲浠ョ偣鍑诲閮ㄥ彇娑�
+ */
+ public void setDialogOutSideCancelable() {
+ if (mDialog != null) {
+ mDialog.setCancelable(mPickerOptions.cancelable);
+ }
+ }
+
+
+ /**
+ * Called when the user touch on black overlay, in order to dismiss the dialog.
+ */
+ private final View.OnTouchListener onCancelableTouchListener = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ dismiss();
+ }
+ return false;
+ }
+ };
+
+ public View findViewById(int id) {
+ return contentContainer.findViewById(id);
+ }
+
+ public void createDialog() {
+ if (dialogView != null) {
+ mDialog = new Dialog(context, R.style.custom_dialog2);
+ mDialog.setCancelable(mPickerOptions.cancelable);//涓嶈兘鐐瑰闈㈠彇娑�,涔熶笉鑳界偣back鍙栨秷
+ mDialog.setContentView(dialogView);
+
+ Window dialogWindow = mDialog.getWindow();
+ if (dialogWindow != null) {
+ dialogWindow.setWindowAnimations(R.style.picker_view_scale_anim);
+ dialogWindow.setGravity(Gravity.CENTER);//鍙互鏀规垚Bottom
+ }
+
+ mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (onDismissListener != null) {
+ onDismissListener.onDismiss(BasePickerView.this);
+ }
+ }
+ });
+ }
+ }
+
+ private void showDialog() {
+ if (mDialog != null) {
+ mDialog.show();
+ }
+ }
+
+ private void dismissDialog() {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+
+ public ViewGroup getDialogContainerLayout() {
+ return contentContainer;
+ }
+
+
+ public Dialog getDialog() {
+ return mDialog;
+ }
+
+
+ public boolean isDialog() {
+ return false;
+ }
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerView.java
new file mode 100644
index 0000000..ef6d44f
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerView.java
@@ -0,0 +1,521 @@
+package com.hdl.widget.pickerview.view;
+
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.adapter.ArrayWheelAdapter;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+
+import java.util.List;
+
+import com.hdl.widget.pickerview.contrarywind.listener.OnItemSelectedListener;
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+/**
+ * Created by JLChen on 2019/9/25
+ */
+public class HDLPickerView<T> extends LinearLayout {
+
+ private WheelView wv_option1, wv_option2, wv_option3;
+ private Context context;
+ // private HDLWheelOptions mHDLWheelOptions;
+// private LinearLayout hdl_pickerview_ll;
+// protected PickerOptions mPickerOptions;
+ private List<T> mOptions1Items;
+ private List<List<T>> mOptions2Items;
+ private List<List<List<T>>> mOptions3Items;
+
+ private boolean linkage = false;//榛樿鑱斿姩
+ private boolean isRestoreItem; //鍒囨崲鏃讹紝杩樺師绗竴椤�
+ private OnItemSelectedListener wheelListener_option1;
+ private OnItemSelectedListener wheelListener_option2;
+
+ private OnOptionsSelectChangeListener optionsSelectChangeListener;
+
+ //鏂囧瓧鐨勯鑹插拰鍒嗗壊绾跨殑棰滆壊
+ private int textColorOut;
+ private int textColorCenter;
+ private int dividerColor;
+ private WheelView.DividerType dividerType;
+ // 鏉$洰闂磋窛鍊嶆暟
+ private float lineSpacingMultiplier;
+
+ public HDLPickerView(Context context) {
+ super(context);
+ this.context = context;
+ initView(context);
+ }
+
+ public HDLPickerView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+ initView(context);
+// initAttrs(context, attrs);
+ }
+
+ //鍒濆鍖朥I锛屽彲鏍规嵁涓氬姟闇�姹傝缃粯璁ゅ�笺��
+ private void initView(Context context) {
+ LayoutInflater.from(context).inflate(R.layout.hdl_widget_pickerview, this, true);
+ wv_option1 = (WheelView) findViewById(R.id.hdl_options1);
+ wv_option2 = (WheelView) findViewById(R.id.hdl_options2);
+ wv_option3 = (WheelView) findViewById(R.id.hdl_options3);
+
+ }
+
+
+ //涓嶈仈鍔ㄦ儏鍐典笅
+ public void setNPicker(List<T> options1Items, List<T> options2Items, List<T> options3Items) {
+ linkage = false;
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(options1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (options2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(options2Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (options3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(options3Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+ setCyclic(false,false,false);
+
+ if (optionsSelectChangeListener != null) {
+ wv_option1.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, wv_option2.getCurrentItem(), wv_option3.getCurrentItem());
+ }
+ });
+ }
+
+ if (options2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option2.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, wv_option3.getCurrentItem());
+ }
+ });
+ }
+ }
+ if (options3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+ }
+
+ public void setPicker(List<T> options1Items,
+ List<List<T>> options2Items,
+ List<List<List<T>>> options3Items) {
+ this.mOptions1Items = options1Items;
+ this.mOptions2Items = options2Items;
+ this.mOptions3Items = options3Items;
+ setCyclic(false,false,false);
+ linkage = true;
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(mOptions1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(0).get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+
+ if (this.mOptions2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ }
+ if (this.mOptions3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ }
+
+ // 鑱斿姩鐩戝惉鍣�
+ wheelListener_option1 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ int opt2Select = 0;
+ if (mOptions2Items == null) {//鍙湁1绾ц仈鍔ㄦ暟鎹�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), 0, 0);
+ }
+ } else {
+ if (!isRestoreItem) {
+ opt2Select = wv_option2.getCurrentItem();//涓婁竴涓猳pt2鐨勯�変腑浣嶇疆
+ //鏂皁pt2鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt2Select = opt2Select >= mOptions2Items.get(index).size() - 1 ? mOptions2Items.get(index).size() - 1 : opt2Select;
+ }
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(index)));
+ wv_option2.setCurrentItem(opt2Select);
+
+ if (mOptions3Items != null) {
+ wheelListener_option2.onItemSelected(opt2Select);
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�1椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, opt2Select, 0);
+ }
+ }
+ }
+ }
+ };
+
+ wheelListener_option2 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ if (mOptions3Items != null) {
+ int opt1Select = wv_option1.getCurrentItem();
+ opt1Select = opt1Select >= mOptions3Items.size() - 1 ? mOptions3Items.size() - 1 : opt1Select;
+ index = index >= mOptions2Items.get(opt1Select).size() - 1 ? mOptions2Items.get(opt1Select).size() - 1 : index;
+ int opt3 = 0;
+ if (!isRestoreItem) {
+ // wv_option3.getCurrentItem() 涓婁竴涓猳pt3鐨勯�変腑浣嶇疆
+ //鏂皁pt3鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt3 = wv_option3.getCurrentItem() >= mOptions3Items.get(opt1Select).get(index).size() - 1 ?
+ mOptions3Items.get(opt1Select).get(index).size() - 1 : wv_option3.getCurrentItem();
+ }
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(wv_option1.getCurrentItem()).get(index)));
+ wv_option3.setCurrentItem(opt3);
+
+ //3绾ц仈鍔ㄦ暟鎹疄鏃跺洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, opt3);
+ }
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�2椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, 0);
+ }
+ }
+ }
+ };
+
+ // 娣诲姞鑱斿姩鐩戝惉
+ if (options1Items != null && linkage) {
+ wv_option1.setOnItemSelectedListener(wheelListener_option1);
+ }
+ if (options2Items != null && linkage) {
+ wv_option2.setOnItemSelectedListener(wheelListener_option2);
+ }
+ if (options3Items != null && linkage && optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+
+ public void setTextContentSize(int textSize) {
+ wv_option1.setTextSize(textSize);
+ wv_option2.setTextSize(textSize);
+ wv_option3.setTextSize(textSize);
+ }
+
+ private void setTextColorOut() {
+ wv_option1.setTextColorOut(textColorOut);
+ wv_option2.setTextColorOut(textColorOut);
+ wv_option3.setTextColorOut(textColorOut);
+ }
+
+ private void setTextColorCenter() {
+ wv_option1.setTextColorCenter(textColorCenter);
+ wv_option2.setTextColorCenter(textColorCenter);
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+
+ private void setDividerColor() {
+ wv_option1.setDividerColor(dividerColor);
+ wv_option2.setDividerColor(dividerColor);
+ wv_option3.setDividerColor(dividerColor);
+ }
+
+ private void setDividerType() {
+ wv_option1.setDividerType(dividerType);
+ wv_option2.setDividerType(dividerType);
+ wv_option3.setDividerType(dividerType);
+ }
+
+ private void setLineSpacingMultiplier() {
+ wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier);
+
+ }
+
+ /**
+ * 璁剧疆閫夐」鐨勫崟浣�
+ *
+ * @param label1 鍗曚綅
+ * @param label2 鍗曚綅
+ * @param label3 鍗曚綅
+ */
+ public void setLabels(String label1, String label2, String label3) {
+ if (label1 != null) {
+ wv_option1.setLabel(label1);
+ }
+ if (label2 != null) {
+ wv_option2.setLabel(label2);
+ }
+ if (label3 != null) {
+ wv_option3.setLabel(label3);
+ }
+ }
+
+ /**
+ * 璁剧疆x杞村亸绉婚噺
+ */
+ public void setTextXOffset(int x_offset_one, int x_offset_two, int x_offset_three) {
+ wv_option1.setTextXOffset(x_offset_one);
+ wv_option2.setTextXOffset(x_offset_two);
+ wv_option3.setTextXOffset(x_offset_three);
+ }
+
+ /**
+ * 璁剧疆鏄惁寰幆婊氬姩
+ *
+ * @param cyclic 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic) {
+ wv_option1.setCyclic(cyclic);
+ wv_option2.setCyclic(cyclic);
+ wv_option3.setCyclic(cyclic);
+ }
+
+ /**
+ * 璁剧疆瀛椾綋鏍峰紡
+ *
+ * @param font 绯荤粺鎻愪緵鐨勫嚑绉嶆牱寮�
+ */
+ public void setTypeface(Typeface font) {
+ wv_option1.setTypeface(font);
+ wv_option2.setTypeface(font);
+ wv_option3.setTypeface(font);
+ }
+
+ /**
+ * 鍒嗗埆璁剧疆绗竴浜屼笁绾ф槸鍚﹀惊鐜粴鍔�
+ *
+ * @param cyclic1,cyclic2,cyclic3 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
+ wv_option1.setCyclic(cyclic1);
+ wv_option2.setCyclic(cyclic2);
+ wv_option3.setCyclic(cyclic3);
+ }
+
+
+ /**
+ * 杩斿洖褰撳墠閫変腑鐨勭粨鏋滃搴旂殑浣嶇疆鏁扮粍 鍥犱负鏀寔涓夌骇鑱斿姩鏁堟灉锛屽垎涓変釜绾у埆绱㈠紩锛�0锛�1锛�2銆�
+ * 鍦ㄥ揩閫熸粦鍔ㄦ湭鍋滄鏃讹紝鐐瑰嚮纭畾鎸夐挳锛屼細杩涜鍒ゆ柇锛屽鏋滃尮閰嶆暟鎹秺鐣岋紝鍒欒涓�0锛岄槻姝ndex鍑洪敊瀵艰嚧宕╂簝銆�
+ *
+ * @return 绱㈠紩鏁扮粍
+ */
+ public int[] getCurrentItems() {
+ int[] currentItems = new int[3];
+ currentItems[0] = wv_option1.getCurrentItem();
+
+ if (mOptions2Items != null && mOptions2Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[1] = wv_option2.getCurrentItem() > (mOptions2Items.get(currentItems[0]).size() - 1) ? 0 : wv_option2.getCurrentItem();
+ } else {
+ currentItems[1] = wv_option2.getCurrentItem();
+ }
+
+ if (mOptions3Items != null && mOptions3Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[2] = wv_option3.getCurrentItem() > (mOptions3Items.get(currentItems[0]).get(currentItems[1]).size() - 1) ? 0 : wv_option3.getCurrentItem();
+ } else {
+ currentItems[2] = wv_option3.getCurrentItem();
+ }
+
+ return currentItems;
+ }
+
+ public void setCurrentItems(int option1, int option2, int option3) {
+ if (linkage) {
+ itemSelected(option1, option2, option3);
+ } else {
+ wv_option1.setCurrentItem(option1);
+ wv_option2.setCurrentItem(option2);
+ wv_option3.setCurrentItem(option3);
+ }
+ }
+
+ private void itemSelected(int opt1Select, int opt2Select, int opt3Select) {
+ if (mOptions1Items != null) {
+ wv_option1.setCurrentItem(opt1Select);
+ }
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(opt1Select)));
+ wv_option2.setCurrentItem(opt2Select);
+ }
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(opt1Select).get(opt2Select)));
+ wv_option3.setCurrentItem(opt3Select);
+ }
+ }
+
+ /**
+ * 璁剧疆闂磋窛鍊嶆暟,浣嗘槸鍙兘鍦�1.2-4.0f涔嬮棿
+ *
+ * @param lineSpacingMultiplier
+ */
+ public void setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ this.lineSpacingMultiplier = lineSpacingMultiplier;
+ setLineSpacingMultiplier();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑棰滆壊
+ *
+ * @param dividerColor
+ */
+ public void setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ setDividerColor();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑绫诲瀷
+ *
+ * @param dividerType
+ */
+ public void setDividerType(WheelView.DividerType dividerType) {
+ this.dividerType = dividerType;
+ setDividerType();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenter(int textColorCenter) {
+ this.textColorCenter = textColorCenter;
+ setTextColorCenter();
+ }
+
+ /**
+ * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ * @param optionId
+ */
+ public void setTextColorCenter(int textColorCenter, int optionId) {
+ if(optionId == 0){
+ wv_option1.setTextColorCenter(textColorCenter);
+ }else if(optionId == 1){
+ wv_option2.setTextColorCenter(textColorCenter);
+ }else if(optionId == 2){
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+ }
+
+ /**
+ * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ * @param textColorCenter1
+ * @param textColorCenter2
+ * @param textColorCenter3
+ */
+ public void setTextColorCenterAlone(int textColorCenter1, int textColorCenter2, int textColorCenter3) {
+ wv_option1.setTextColorCenter(textColorCenter1);
+ wv_option2.setTextColorCenter(textColorCenter2);
+ wv_option3.setTextColorCenter(textColorCenter3);
+ }
+
+ /**
+ * 缁熶竴璁剧疆璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenterAll(int textColorCenter) {
+ wv_option1.setTextColorCenter(textColorCenter);
+ wv_option2.setTextColorCenter(textColorCenter);
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+
+// /**
+// * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+// *
+// * @param bEnable
+// * @param optionId
+// */
+// public void setOptionViewEnable(int bEnable, int optionId) {
+// if(optionId == 0){
+// wv_option1.setEnabled(bEnable);
+// }else if(optionId == 1){
+// wv_option2.setTextColorCenter(textColorCenter);
+// }else if(optionId == 2){
+// wv_option3.setTextColorCenter(textColorCenter);
+// }
+// }
+
+
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸互澶栨枃瀛楃殑棰滆壊
+ *
+ * @param textColorOut
+ */
+ public void setTextColorOut(int textColorOut) {
+ this.textColorOut = textColorOut;
+ setTextColorOut();
+ }
+
+ /**
+ * Label 鏄惁鍙樉绀轰腑闂撮�変腑椤圭殑
+ *
+ * @param isCenterLabel
+ */
+
+ public void isCenterLabel(boolean isCenterLabel) {
+ wv_option1.isCenterLabel(isCenterLabel);
+ wv_option2.isCenterLabel(isCenterLabel);
+ wv_option3.isCenterLabel(isCenterLabel);
+ }
+
+ public void setOptionsSelectChangeListener(OnOptionsSelectChangeListener optionsSelectChangeListener) {
+ this.optionsSelectChangeListener = optionsSelectChangeListener;
+ }
+
+ public void setLinkage(boolean linkage) {
+ this.linkage = linkage;
+ }
+
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerViewNT.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerViewNT.java
new file mode 100644
index 0000000..314b4bd
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/HDLPickerViewNT.java
@@ -0,0 +1,567 @@
+package com.hdl.widget.pickerview.view;
+
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.hdl.widget.pickerview.adapter.ArrayWheelAdapter;
+import com.hdl.widget.pickerview.contrarywind.listener.OnItemSelectedListener;
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+import com.hdl.widgetxm.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Created by JLChen on 2019/9/25
+ * 涓嶆寚瀹氭硾鍨�
+ */
+public class HDLPickerViewNT extends LinearLayout {
+
+ private WheelView wv_option1, wv_option2, wv_option3;
+ private Context context;
+ // private HDLWheelOptions mHDLWheelOptions;
+// private LinearLayout hdl_pickerview_ll;
+// protected PickerOptions mPickerOptions;
+ private List<String> mOptions1Items;
+ private List<List<String>> mOptions2Items;
+ private List<List<List<String>>> mOptions3Items;
+
+ private boolean linkage = false;//榛樿鑱斿姩
+ private boolean isRestoreItem; //鍒囨崲鏃讹紝杩樺師绗竴椤�
+ private OnItemSelectedListener wheelListener_option1;
+ private OnItemSelectedListener wheelListener_option2;
+
+ private OnOptionsSelectChangeListener optionsSelectChangeListener;
+
+ //鏂囧瓧鐨勯鑹插拰鍒嗗壊绾跨殑棰滆壊
+ private int textColorOut;
+ private int textColorCenter;
+ private int dividerColor;
+ private WheelView.DividerType dividerType;
+ // 鏉$洰闂磋窛鍊嶆暟
+ private float lineSpacingMultiplier;
+
+ public HDLPickerViewNT(Context context) {
+ super(context);
+ this.context = context;
+ initView(context);
+ }
+
+ public HDLPickerViewNT(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+ initView(context);
+// initAttrs(context, attrs);
+ }
+
+ //鍒濆鍖朥I锛屽彲鏍规嵁涓氬姟闇�姹傝缃粯璁ゅ�笺��
+ private void initView(Context context) {
+ LayoutInflater.from(context).inflate(R.layout.hdl_widget_pickerview, this, true);
+ wv_option1 = (WheelView) findViewById(R.id.hdl_options1);
+ wv_option2 = (WheelView) findViewById(R.id.hdl_options2);
+ wv_option3 = (WheelView) findViewById(R.id.hdl_options3);
+
+ }
+
+
+ //涓嶈仈鍔ㄦ儏鍐典笅
+ public void setNPicker(List<String> options1Items, List<String> options2Items, List<String> options3Items) {
+ linkage = false;
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(options1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (options2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(options2Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (options3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(options3Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+ setCyclic(false,false,false);
+
+ if (optionsSelectChangeListener != null) {
+ wv_option1.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, wv_option2.getCurrentItem(), wv_option3.getCurrentItem());
+ }
+ });
+ }
+
+ if (options2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option2.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, wv_option3.getCurrentItem());
+ }
+ });
+ }
+ }
+ if (options3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+ }
+
+
+// public void setPickerHashMap(List<String> options1Items,
+// HashMap<String, ArrayList<String>> options2Items) {
+// List<List<String>> newoptions2Items = new ArrayList();
+// for(int i=0;i<options2Items.size();i++){
+// newoptions2Items.add(options2Items.get(options1Items.get(i)));
+// }
+//
+// setPicker(options1Items, newoptions2Items,null);
+// }
+// public void setPickerArrayList(ArrayList<String> options1Items,
+// ArrayList<ArrayList<String>> options2Items) {
+// List<List<String>> newoptions2Items = new ArrayList();
+// for(int i=0;i<options2Items.size();i++){
+// newoptions2Items.add(options2Items.get(i));
+// }
+//
+// setPicker(options1Items, newoptions2Items,null);
+// }
+
+ public void setPickerString(List<String> options1Items, List<String> options2Items) {
+ try {
+ List<List<String>> options2Itemss = new ArrayList<>();
+ for(int i =0; i< options2Items.size();i++){
+ String[] arr = options2Items.get(i).split(">-<");
+ List<String> list = Arrays.asList(arr);
+ options2Itemss.add(list);
+ }
+ this.setPicker(options1Items, options2Itemss, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+
+ public void setPicker(List<String> options1Items,
+ List<List<String>> options2Items) {
+
+ setPicker(options1Items,options2Items,null);
+ }
+
+
+ public void setPicker(List<String> options1Items,
+ List<List<String>> options2Items,
+ List<List<List<String>>> options3Items) {
+ this.mOptions1Items = options1Items;
+ this.mOptions2Items = options2Items;
+ this.mOptions3Items = options3Items;
+ setCyclic(false,false,false);
+ linkage = true;
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(mOptions1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(0).get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+
+ if (this.mOptions2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ }
+ if (this.mOptions3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ }
+
+ // 鑱斿姩鐩戝惉鍣�
+ wheelListener_option1 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ int opt2Select = 0;
+ if (mOptions2Items == null) {//鍙湁1绾ц仈鍔ㄦ暟鎹�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), 0, 0);
+ }
+ } else {
+ if (!isRestoreItem) {
+ opt2Select = wv_option2.getCurrentItem();//涓婁竴涓猳pt2鐨勯�変腑浣嶇疆
+ //鏂皁pt2鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt2Select = opt2Select >= mOptions2Items.get(index).size() - 1 ? mOptions2Items.get(index).size() - 1 : opt2Select;
+ }
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(index)));
+ wv_option2.setCurrentItem(opt2Select);
+
+ if (mOptions3Items != null) {
+ wheelListener_option2.onItemSelected(opt2Select);
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�1椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, opt2Select, 0);
+ }
+ }
+ }
+ }
+ };
+
+ wheelListener_option2 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ if (mOptions3Items != null) {
+ int opt1Select = wv_option1.getCurrentItem();
+ opt1Select = opt1Select >= mOptions3Items.size() - 1 ? mOptions3Items.size() - 1 : opt1Select;
+ index = index >= mOptions2Items.get(opt1Select).size() - 1 ? mOptions2Items.get(opt1Select).size() - 1 : index;
+ int opt3 = 0;
+ if (!isRestoreItem) {
+ // wv_option3.getCurrentItem() 涓婁竴涓猳pt3鐨勯�変腑浣嶇疆
+ //鏂皁pt3鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt3 = wv_option3.getCurrentItem() >= mOptions3Items.get(opt1Select).get(index).size() - 1 ?
+ mOptions3Items.get(opt1Select).get(index).size() - 1 : wv_option3.getCurrentItem();
+ }
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(wv_option1.getCurrentItem()).get(index)));
+ wv_option3.setCurrentItem(opt3);
+
+ //3绾ц仈鍔ㄦ暟鎹疄鏃跺洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, opt3);
+ }
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�2椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, 0);
+ }
+ }
+ }
+ };
+
+ // 娣诲姞鑱斿姩鐩戝惉
+ if (options1Items != null && linkage) {
+ wv_option1.setOnItemSelectedListener(wheelListener_option1);
+ }
+ if (options2Items != null && linkage) {
+ wv_option2.setOnItemSelectedListener(wheelListener_option2);
+ }
+ if (options3Items != null && linkage && optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+
+ public void setTextContentSize(int textSize) {
+ wv_option1.setTextSize(textSize);
+ wv_option2.setTextSize(textSize);
+ wv_option3.setTextSize(textSize);
+ }
+
+ private void setTextColorOut() {
+ wv_option1.setTextColorOut(textColorOut);
+ wv_option2.setTextColorOut(textColorOut);
+ wv_option3.setTextColorOut(textColorOut);
+ }
+
+ private void setTextColorCenter() {
+ wv_option1.setTextColorCenter(textColorCenter);
+ wv_option2.setTextColorCenter(textColorCenter);
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+
+ private void setDividerColor() {
+ wv_option1.setDividerColor(dividerColor);
+ wv_option2.setDividerColor(dividerColor);
+ wv_option3.setDividerColor(dividerColor);
+ }
+
+ private void setDividerType() {
+ wv_option1.setDividerType(dividerType);
+ wv_option2.setDividerType(dividerType);
+ wv_option3.setDividerType(dividerType);
+ }
+
+ private void setLineSpacingMultiplier() {
+ wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier);
+
+ }
+
+ /**
+ * 璁剧疆閫夐」鐨勫崟浣�
+ *
+ * @param label1 鍗曚綅
+ * @param label2 鍗曚綅
+ * @param label3 鍗曚綅
+ */
+ public void setLabels(String label1, String label2, String label3) {
+ if (label1 != null) {
+ wv_option1.setLabel(label1);
+ }
+ if (label2 != null) {
+ wv_option2.setLabel(label2);
+ }
+ if (label3 != null) {
+ wv_option3.setLabel(label3);
+ }
+ }
+
+ /**
+ * 璁剧疆x杞村亸绉婚噺
+ */
+ public void setTextXOffset(int x_offset_one, int x_offset_two, int x_offset_three) {
+ wv_option1.setTextXOffset(x_offset_one);
+ wv_option2.setTextXOffset(x_offset_two);
+ wv_option3.setTextXOffset(x_offset_three);
+ }
+
+ /**
+ * 璁剧疆鏄惁寰幆婊氬姩
+ *
+ * @param cyclic 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic) {
+ wv_option1.setCyclic(cyclic);
+ wv_option2.setCyclic(cyclic);
+ wv_option3.setCyclic(cyclic);
+ }
+
+ /**
+ * 璁剧疆瀛椾綋鏍峰紡
+ *
+ * @param font 绯荤粺鎻愪緵鐨勫嚑绉嶆牱寮�
+ */
+ public void setTypeface(Typeface font) {
+ wv_option1.setTypeface(font);
+ wv_option2.setTypeface(font);
+ wv_option3.setTypeface(font);
+ }
+
+ /**
+ * 鍒嗗埆璁剧疆绗竴浜屼笁绾ф槸鍚﹀惊鐜粴鍔�
+ *
+ * @param cyclic1,cyclic2,cyclic3 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
+ wv_option1.setCyclic(cyclic1);
+ wv_option2.setCyclic(cyclic2);
+ wv_option3.setCyclic(cyclic3);
+ }
+
+
+ /**
+ * 杩斿洖褰撳墠閫変腑鐨勭粨鏋滃搴旂殑浣嶇疆鏁扮粍 鍥犱负鏀寔涓夌骇鑱斿姩鏁堟灉锛屽垎涓変釜绾у埆绱㈠紩锛�0锛�1锛�2銆�
+ * 鍦ㄥ揩閫熸粦鍔ㄦ湭鍋滄鏃讹紝鐐瑰嚮纭畾鎸夐挳锛屼細杩涜鍒ゆ柇锛屽鏋滃尮閰嶆暟鎹秺鐣岋紝鍒欒涓�0锛岄槻姝ndex鍑洪敊瀵艰嚧宕╂簝銆�
+ *
+ * @return 绱㈠紩鏁扮粍
+ */
+ public int[] getCurrentItems() {
+ int[] currentItems = new int[3];
+ currentItems[0] = wv_option1.getCurrentItem();
+
+ if (mOptions2Items != null && mOptions2Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[1] = wv_option2.getCurrentItem() > (mOptions2Items.get(currentItems[0]).size() - 1) ? 0 : wv_option2.getCurrentItem();
+ } else {
+ currentItems[1] = wv_option2.getCurrentItem();
+ }
+
+ if (mOptions3Items != null && mOptions3Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[2] = wv_option3.getCurrentItem() > (mOptions3Items.get(currentItems[0]).get(currentItems[1]).size() - 1) ? 0 : wv_option3.getCurrentItem();
+ } else {
+ currentItems[2] = wv_option3.getCurrentItem();
+ }
+
+ return currentItems;
+ }
+
+ public void setCurrentItems(int option1, int option2, int option3) {
+ if (linkage) {
+ itemSelected(option1, option2, option3);
+ } else {
+ wv_option1.setCurrentItem(option1);
+ wv_option2.setCurrentItem(option2);
+ wv_option3.setCurrentItem(option3);
+ }
+ }
+
+ private void itemSelected(int opt1Select, int opt2Select, int opt3Select) {
+ if (mOptions1Items != null) {
+ wv_option1.setCurrentItem(opt1Select);
+ }
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(opt1Select)));
+ wv_option2.setCurrentItem(opt2Select);
+ }
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(opt1Select).get(opt2Select)));
+ wv_option3.setCurrentItem(opt3Select);
+ }
+ }
+
+ /**
+ * 璁剧疆闂磋窛鍊嶆暟,浣嗘槸鍙兘鍦�1.2-4.0f涔嬮棿
+ *
+ * @param lineSpacingMultiplier
+ */
+ public void setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ this.lineSpacingMultiplier = lineSpacingMultiplier;
+ setLineSpacingMultiplier();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑棰滆壊
+ *
+ * @param dividerColor
+ */
+ public void setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ setDividerColor();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑绫诲瀷
+ *
+ * @param dividerType
+ */
+ public void setDividerType(WheelView.DividerType dividerType) {
+ this.dividerType = dividerType;
+ setDividerType();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenter(int textColorCenter) {
+ this.textColorCenter = textColorCenter;
+ setTextColorCenter();
+ }
+
+ /**
+ * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ * @param optionId
+ */
+ public void setTextColorCenter(int textColorCenter, int optionId) {
+ if(optionId == 0){
+ wv_option1.setTextColorCenter(textColorCenter);
+ }else if(optionId == 1){
+ wv_option2.setTextColorCenter(textColorCenter);
+ }else if(optionId == 2){
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+ }
+
+ /**
+ * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ * @param textColorCenter1
+ * @param textColorCenter2
+ * @param textColorCenter3
+ */
+ public void setTextColorCenterAlone(int textColorCenter1, int textColorCenter2, int textColorCenter3) {
+ wv_option1.setTextColorCenter(textColorCenter1);
+ wv_option2.setTextColorCenter(textColorCenter2);
+ wv_option3.setTextColorCenter(textColorCenter3);
+ }
+
+ /**
+ * 缁熶竴璁剧疆璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenterAll(int textColorCenter) {
+ wv_option1.setTextColorCenter(textColorCenter);
+ wv_option2.setTextColorCenter(textColorCenter);
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+
+// /**
+// * 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+// *
+// * @param bEnable
+// * @param optionId
+// */
+// public void setOptionViewEnable(int bEnable, int optionId) {
+// if(optionId == 0){
+// wv_option1.setEnabled(bEnable);
+// }else if(optionId == 1){
+// wv_option2.setTextColorCenter(textColorCenter);
+// }else if(optionId == 2){
+// wv_option3.setTextColorCenter(textColorCenter);
+// }
+// }
+
+
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸互澶栨枃瀛楃殑棰滆壊
+ *
+ * @param textColorOut
+ */
+ public void setTextColorOut(int textColorOut) {
+ this.textColorOut = textColorOut;
+ setTextColorOut();
+ }
+
+ /**
+ * Label 鏄惁鍙樉绀轰腑闂撮�変腑椤圭殑
+ *
+ * @param isCenterLabel
+ */
+
+ public void isCenterLabel(boolean isCenterLabel) {
+ wv_option1.isCenterLabel(isCenterLabel);
+ wv_option2.isCenterLabel(isCenterLabel);
+ wv_option3.isCenterLabel(isCenterLabel);
+ }
+
+ public void setOptionsSelectChangeListener(OnOptionsSelectChangeListener optionsSelectChangeListener) {
+ this.optionsSelectChangeListener = optionsSelectChangeListener;
+ }
+
+ public void setLinkage(boolean linkage) {
+ this.linkage = linkage;
+ }
+
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/OptionsPickerView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/OptionsPickerView.java
new file mode 100644
index 0000000..74db933
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/OptionsPickerView.java
@@ -0,0 +1,256 @@
+package com.hdl.widget.pickerview.view;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.support.annotation.ColorInt;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.hdl.widget.HDLUtlisXM;
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.configure.PickerOptions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 鏉′欢閫夋嫨鍣�
+ * Created by Sai on 15/11/22.
+ */
+public class OptionsPickerView extends BasePickerView implements View.OnClickListener {
+
+ private WheelOptions wheelOptions;
+
+ private static final String TAG_SUBMIT = "submit";
+ private static final String TAG_CANCEL = "cancel";
+
+
+ public OptionsPickerView(PickerOptions pickerOptions) {
+ super(pickerOptions.context);
+ mPickerOptions = pickerOptions;
+ initView(pickerOptions.context);
+ }
+
+ private void initView(Context context) {
+ setDialogOutSideCancelable();
+ initViews();
+ initAnim();
+ initEvents();
+ if (mPickerOptions.customListener == null) {
+ LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer);
+
+ //椤堕儴鏍囬
+ TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
+ RelativeLayout rv_top_bar = (RelativeLayout) findViewById(R.id.rv_topbar);
+
+ //纭畾鍜屽彇娑堟寜閽�
+ Button btnSubmit = (Button) findViewById(R.id.btnSubmit);
+ Button btnCancel = (Button) findViewById(R.id.btnCancel);
+
+ btnSubmit.setTag(TAG_SUBMIT);
+ btnCancel.setTag(TAG_CANCEL);
+ btnSubmit.setOnClickListener(this);
+ btnCancel.setOnClickListener(this);
+
+ //璁剧疆鏂囧瓧
+ btnSubmit.setText(TextUtils.isEmpty(mPickerOptions.textContentConfirm) ? context.getResources().getString(R.string.pickerview_submit) : mPickerOptions.textContentConfirm);
+ btnCancel.setText(TextUtils.isEmpty(mPickerOptions.textContentCancel) ? context.getResources().getString(R.string.pickerview_cancel) : mPickerOptions.textContentCancel);
+ tvTitle.setText(TextUtils.isEmpty(mPickerOptions.textContentTitle) ? "" : mPickerOptions.textContentTitle);//榛樿涓虹┖
+
+ //璁剧疆color
+ btnSubmit.setTextColor(mPickerOptions.textColorConfirm);
+ btnCancel.setTextColor(mPickerOptions.textColorCancel);
+ tvTitle.setTextColor(mPickerOptions.textColorTitle);
+ rv_top_bar.setBackgroundColor(mPickerOptions.bgColorTitle);
+
+ //璁剧疆鏂囧瓧澶у皬
+ btnSubmit.setTextSize(mPickerOptions.textSizeSubmitCancel);
+ btnCancel.setTextSize(mPickerOptions.textSizeSubmitCancel);
+ tvTitle.setTextSize(mPickerOptions.textSizeTitle);
+
+ int ddd = HDLUtlisXM.dp2px(context,20);
+ float[] foo ={ddd,ddd,0f,0f};
+ GradientDrawable drawable = createRectangleDrawable(Color.WHITE, foo);
+ float[] foo1 ={ddd,0f,0f,0f};
+ GradientDrawable drawable1 = createRectangleDrawable(Color.WHITE, foo1);
+ float[] foo2 ={0f,ddd,0f,0f};
+ GradientDrawable drawable2 = createRectangleDrawable(Color.WHITE, foo2);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ rv_top_bar.setBackground(drawable);
+ btnCancel.setBackground(drawable1);
+ btnSubmit.setBackground(drawable2);
+ }
+ } else {
+ mPickerOptions.customListener.customLayout(LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer));
+ }
+
+ // ----婊氳疆甯冨眬
+ final LinearLayout optionsPicker = (LinearLayout) findViewById(R.id.optionspicker);
+ optionsPicker.setBackgroundColor(mPickerOptions.bgColorWheel);
+
+ wheelOptions = new WheelOptions(optionsPicker, mPickerOptions.isRestoreItem);
+ if (mPickerOptions.optionsSelectChangeListener != null) {
+ wheelOptions.setOptionsSelectChangeListener(mPickerOptions.optionsSelectChangeListener);
+ }
+
+ wheelOptions.setTextContentSize(mPickerOptions.textSizeContent);
+ wheelOptions.setLabels(mPickerOptions.label1, mPickerOptions.label2, mPickerOptions.label3);
+ wheelOptions.setTextXOffset(mPickerOptions.x_offset_one, mPickerOptions.x_offset_two, mPickerOptions.x_offset_three);
+ wheelOptions.setCyclic(mPickerOptions.cyclic1, mPickerOptions.cyclic2, mPickerOptions.cyclic3);
+ wheelOptions.setTypeface(mPickerOptions.font);
+
+ setOutSideCancelable(mPickerOptions.cancelable);
+
+ wheelOptions.setDividerColor(mPickerOptions.dividerColor);
+ wheelOptions.setDividerType(mPickerOptions.dividerType);
+ wheelOptions.setLineSpacingMultiplier(mPickerOptions.lineSpacingMultiplier);
+ wheelOptions.setTextColorOut(mPickerOptions.textColorOut);
+ wheelOptions.setTextColorCenter(mPickerOptions.textColorCenter);
+ wheelOptions.isCenterLabel(mPickerOptions.isCenterLabel);
+ }
+
+ /**
+ * 鍒涘缓鑳屾櫙棰滆壊
+ *
+ * @param color 濉厖鑹�
+ * @param radius 瑙掑害 px,闀垮害涓�4,鍒嗗埆琛ㄧず宸︿笂,鍙充笂,鍙充笅,宸︿笅鐨勮搴�
+ */
+ public static GradientDrawable createRectangleDrawable(@ColorInt int color, float radius[]) {
+ try {
+ GradientDrawable radiusBg = new GradientDrawable();
+ //璁剧疆Shape绫诲瀷
+ radiusBg.setShape(GradientDrawable.RECTANGLE);
+ //璁剧疆濉厖棰滆壊
+ radiusBg.setColor(color);
+// //璁剧疆绾挎潯绮楀績鍜岄鑹�,px
+// radiusBg.setStroke(strokeWidth, strokeColor);
+ //姣忚繛缁殑涓や釜鏁板�艰〃绀烘槸涓�涓搴�,鍥涚粍:宸︿笂,鍙充笂,鍙充笅,宸︿笅
+ if (radius != null && radius.length == 4) {
+ radiusBg.setCornerRadii(new float[]{radius[0], radius[0], radius[1], radius[1], radius[2], radius[2], radius[3], radius[3]});
+ }
+ return radiusBg;
+ } catch (Exception e) {
+ return new GradientDrawable();
+ }
+ }
+
+
+ /**
+ * 鍔ㄦ�佽缃爣棰�
+ *
+ * @param text 鏍囬鏂囨湰鍐呭
+ */
+ public void setTitleText(String text) {
+ TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
+ if (tvTitle != null) {
+ tvTitle.setText(text);
+ }
+ }
+
+ /**
+ * 璁剧疆榛樿閫変腑椤�
+ *
+ * @param option1
+ */
+ public void setSelectOptions(int option1) {
+ mPickerOptions.option1 = option1;
+ reSetCurrentItems();
+ }
+
+
+ public void setSelectOptions(int option1, int option2) {
+ mPickerOptions.option1 = option1;
+ mPickerOptions.option2 = option2;
+ reSetCurrentItems();
+ }
+
+ public void setSelectOptions(int option1, int option2, int option3) {
+ mPickerOptions.option1 = option1;
+ mPickerOptions.option2 = option2;
+ mPickerOptions.option3 = option3;
+ reSetCurrentItems();
+ }
+
+ private void reSetCurrentItems() {
+ if (wheelOptions != null) {
+ wheelOptions.setCurrentItems(mPickerOptions.option1, mPickerOptions.option2, mPickerOptions.option3);
+ }
+ }
+
+ public void setPicker(List<String> optionsItems) {
+ this.setPicker(optionsItems, null, null);
+ }
+
+ public void setPicker(List<String> options1Items, List<List<String>> options2Items) {
+ this.setPicker(options1Items, options2Items, null);
+ }
+
+ public void setPickerString(List<String> options1Items, List<String> options2Items) {
+ try {
+ List<List<String>> options2Itemss = new ArrayList<>();
+ for(int i =0; i< options2Items.size();i++){
+ String[] arr = options2Items.get(i).split(">-<");
+ List<String> list = Arrays.asList(arr);
+ options2Itemss.add(list);
+ }
+ this.setPicker(options1Items, options2Itemss, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void setPicker(List<String> options1Items,
+ List<List<String>> options2Items,
+ List<List<List<String>>> options3Items) {
+
+ wheelOptions.setPicker(options1Items, options2Items, options3Items);
+ reSetCurrentItems();
+ }
+
+
+ //涓嶈仈鍔ㄦ儏鍐典笅璋冪敤
+ public void setNPicker(List<String> options1Items,
+ List<String> options2Items,
+ List<String> options3Items) {
+
+ wheelOptions.setLinkage(false);
+ wheelOptions.setNPicker(options1Items, options2Items, options3Items);
+ reSetCurrentItems();
+ }
+
+ @Override
+ public void onClick(View v) {
+ String tag = (String) v.getTag();
+ if (tag.equals(TAG_SUBMIT)) {
+ returnData();
+ } else if (tag.equals(TAG_CANCEL)) {
+ if (mPickerOptions.cancelListener != null) {
+ mPickerOptions.cancelListener.onClick(v);
+ }
+ }
+ dismiss();
+ }
+
+ //鎶界鎺ュ彛鍥炶皟鐨勬柟娉�
+ public void returnData() {
+ if (mPickerOptions.optionsSelectListener != null) {
+ int[] optionsCurrentItems = wheelOptions.getCurrentItems();
+ mPickerOptions.optionsSelectListener.onOptionsSelect(optionsCurrentItems[0], optionsCurrentItems[1], optionsCurrentItems[2], clickView);
+ }
+ }
+
+
+ @Override
+ public boolean isDialog() {
+ return mPickerOptions.isDialog;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/TimePickerView.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/TimePickerView.java
new file mode 100644
index 0000000..2f704b8
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/TimePickerView.java
@@ -0,0 +1,288 @@
+package com.hdl.widget.pickerview.view;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.configure.PickerOptions;
+import com.hdl.widget.pickerview.listener.ISelectTimeCallback;
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 鏃堕棿閫夋嫨鍣�
+ * Created by Sai on 15/11/22.
+ * Updated by XiaoSong on 2017-2-22.
+ */
+public class TimePickerView extends BasePickerView implements View.OnClickListener {
+
+ private WheelTime wheelTime; //鑷畾涔夋帶浠�
+ private static final String TAG_SUBMIT = "submit";
+ private static final String TAG_CANCEL = "cancel";
+
+ public TimePickerView(PickerOptions pickerOptions) {
+ super(pickerOptions.context);
+ mPickerOptions = pickerOptions;
+ initView(pickerOptions.context);
+ }
+
+ private void initView(Context context) {
+ setDialogOutSideCancelable();
+ initViews();
+ initAnim();
+
+ if (mPickerOptions.customListener == null) {
+ LayoutInflater.from(context).inflate(R.layout.hdl_widget_pickerview_time, contentContainer);
+
+ //椤堕儴鏍囬
+ TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
+ RelativeLayout rv_top_bar = (RelativeLayout) findViewById(R.id.rv_topbar);
+
+ //纭畾鍜屽彇娑堟寜閽�
+ Button btnSubmit = (Button) findViewById(R.id.btnSubmit);
+ Button btnCancel = (Button) findViewById(R.id.btnCancel);
+
+ btnSubmit.setTag(TAG_SUBMIT);
+ btnCancel.setTag(TAG_CANCEL);
+
+ btnSubmit.setOnClickListener(this);
+ btnCancel.setOnClickListener(this);
+
+ //璁剧疆鏂囧瓧
+ btnSubmit.setText(TextUtils.isEmpty(mPickerOptions.textContentConfirm) ? context.getResources().getString(R.string.pickerview_submit) : mPickerOptions.textContentConfirm);
+ btnCancel.setText(TextUtils.isEmpty(mPickerOptions.textContentCancel) ? context.getResources().getString(R.string.pickerview_cancel) : mPickerOptions.textContentCancel);
+ tvTitle.setText(TextUtils.isEmpty(mPickerOptions.textContentTitle) ? "" : mPickerOptions.textContentTitle);//榛樿涓虹┖
+
+ //璁剧疆color
+ btnSubmit.setTextColor(mPickerOptions.textColorConfirm);
+ btnCancel.setTextColor(mPickerOptions.textColorCancel);
+ tvTitle.setTextColor(mPickerOptions.textColorTitle);
+ rv_top_bar.setBackgroundColor(mPickerOptions.bgColorTitle);
+
+ //璁剧疆鏂囧瓧澶у皬
+ btnSubmit.setTextSize(mPickerOptions.textSizeSubmitCancel);
+ btnCancel.setTextSize(mPickerOptions.textSizeSubmitCancel);
+ tvTitle.setTextSize(mPickerOptions.textSizeTitle);
+
+ } else {
+ mPickerOptions.customListener.customLayout(LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer));
+ }
+ // 鏃堕棿杞疆 鑷畾涔夋帶浠�
+ LinearLayout timePickerView = (LinearLayout) findViewById(R.id.timepicker);
+ timePickerView.setBackgroundColor(mPickerOptions.bgColorWheel);
+
+ initWheelTime(timePickerView);
+ }
+
+ private void initWheelTime(LinearLayout timePickerView) {
+ wheelTime = new WheelTime(timePickerView, mPickerOptions.type, mPickerOptions.textGravity, mPickerOptions.textSizeContent);
+ if (mPickerOptions.timeSelectChangeListener != null) {
+ wheelTime.setSelectChangeCallback(new ISelectTimeCallback() {
+ @Override
+ public void onTimeSelectChanged() {
+ try {
+ Date date = WheelTime.dateFormat.parse(wheelTime.getTime());
+ mPickerOptions.timeSelectChangeListener.onTimeSelectChanged(date);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ wheelTime.setLunarMode(mPickerOptions.isLunarCalendar);
+
+ if (mPickerOptions.startYear != 0 && mPickerOptions.endYear != 0
+ && mPickerOptions.startYear <= mPickerOptions.endYear) {
+ setRange();
+ }
+
+ //鑻ユ墜鍔ㄨ缃簡鏃堕棿鑼冨洿闄愬埗
+ if (mPickerOptions.startDate != null && mPickerOptions.endDate != null) {
+ if (mPickerOptions.startDate.getTimeInMillis() > mPickerOptions.endDate.getTimeInMillis()) {
+ throw new IllegalArgumentException("startDate can't be later than endDate");
+ } else {
+ setRangDate();
+ }
+ } else if (mPickerOptions.startDate != null) {
+ if (mPickerOptions.startDate.get(Calendar.YEAR) < 1900) {
+ throw new IllegalArgumentException("The startDate can not as early as 1900");
+ } else {
+ setRangDate();
+ }
+ } else if (mPickerOptions.endDate != null) {
+ if (mPickerOptions.endDate.get(Calendar.YEAR) > 2100) {
+ throw new IllegalArgumentException("The endDate should not be later than 2100");
+ } else {
+ setRangDate();
+ }
+ } else {//娌℃湁璁剧疆鏃堕棿鑼冨洿闄愬埗锛屽垯浼氫娇鐢ㄩ粯璁よ寖鍥淬��
+ setRangDate();
+ }
+
+ setTime();
+ wheelTime.setLabels(mPickerOptions.label_year, mPickerOptions.label_month, mPickerOptions.label_day
+ , mPickerOptions.label_hours, mPickerOptions.label_minutes, mPickerOptions.label_seconds);
+ wheelTime.setTextXOffset(mPickerOptions.x_offset_year, mPickerOptions.x_offset_month, mPickerOptions.x_offset_day,
+ mPickerOptions.x_offset_hours, mPickerOptions.x_offset_minutes, mPickerOptions.x_offset_seconds);
+
+ setOutSideCancelable(mPickerOptions.cancelable);
+ wheelTime.setCyclic(mPickerOptions.cyclic);
+ wheelTime.setDividerColor(mPickerOptions.dividerColor);
+ wheelTime.setDividerType(mPickerOptions.dividerType);
+ wheelTime.setLineSpacingMultiplier(mPickerOptions.lineSpacingMultiplier);
+ wheelTime.setTextColorOut(mPickerOptions.textColorOut);
+ wheelTime.setTextColorCenter(mPickerOptions.textColorCenter);
+ wheelTime.isCenterLabel(mPickerOptions.isCenterLabel);
+ }
+
+
+ /**
+ * 璁剧疆榛樿鏃堕棿
+ */
+ public void setDate(Calendar date) {
+ mPickerOptions.date = date;
+ setTime();
+ }
+
+ /**
+ * 璁剧疆鍙互閫夋嫨鐨勬椂闂磋寖鍥�, 瑕佸湪setTime涔嬪墠璋冪敤鎵嶆湁鏁堟灉
+ */
+ private void setRange() {
+ wheelTime.setStartYear(mPickerOptions.startYear);
+ wheelTime.setEndYear(mPickerOptions.endYear);
+
+ }
+
+ /**
+ * 璁剧疆鍙互閫夋嫨鐨勬椂闂磋寖鍥�, 瑕佸湪setTime涔嬪墠璋冪敤鎵嶆湁鏁堟灉
+ */
+ private void setRangDate() {
+ wheelTime.setRangDate(mPickerOptions.startDate, mPickerOptions.endDate);
+ initDefaultSelectedDate();
+ }
+
+ private void initDefaultSelectedDate() {
+ //濡傛灉鎵嬪姩璁剧疆浜嗘椂闂磋寖鍥�
+ if (mPickerOptions.startDate != null && mPickerOptions.endDate != null) {
+ //鑻ラ粯璁ゆ椂闂存湭璁剧疆锛屾垨鑰呰缃殑榛樿鏃堕棿瓒婄晫浜嗭紝鍒欒缃粯璁ら�変腑鏃堕棿涓哄紑濮嬫椂闂淬��
+ if (mPickerOptions.date == null || mPickerOptions.date.getTimeInMillis() < mPickerOptions.startDate.getTimeInMillis()
+ || mPickerOptions.date.getTimeInMillis() > mPickerOptions.endDate.getTimeInMillis()) {
+ mPickerOptions.date = mPickerOptions.startDate;
+ }
+ } else if (mPickerOptions.startDate != null) {
+ //娌℃湁璁剧疆榛樿閫変腑鏃堕棿,閭e氨鎷垮紑濮嬫椂闂村綋榛樿鏃堕棿
+ mPickerOptions.date = mPickerOptions.startDate;
+ } else if (mPickerOptions.endDate != null) {
+ mPickerOptions.date = mPickerOptions.endDate;
+ }
+ }
+
+ /**
+ * 璁剧疆閫変腑鏃堕棿,榛樿閫変腑褰撳墠鏃堕棿
+ */
+ private void setTime() {
+ int year, month, day, hours, minute, seconds;
+ Calendar calendar = Calendar.getInstance();
+
+ if (mPickerOptions.date == null) {
+ calendar.setTimeInMillis(System.currentTimeMillis());
+ year = calendar.get(Calendar.YEAR);
+ month = calendar.get(Calendar.MONTH);
+ day = calendar.get(Calendar.DAY_OF_MONTH);
+ hours = calendar.get(Calendar.HOUR_OF_DAY);
+ minute = calendar.get(Calendar.MINUTE);
+ seconds = calendar.get(Calendar.SECOND);
+ } else {
+ year = mPickerOptions.date.get(Calendar.YEAR);
+ month = mPickerOptions.date.get(Calendar.MONTH);
+ day = mPickerOptions.date.get(Calendar.DAY_OF_MONTH);
+ hours = mPickerOptions.date.get(Calendar.HOUR_OF_DAY);
+ minute = mPickerOptions.date.get(Calendar.MINUTE);
+ seconds = mPickerOptions.date.get(Calendar.SECOND);
+ }
+
+ wheelTime.setPicker(year, month, day, hours, minute, seconds);
+ }
+
+
+ @Override
+ public void onClick(View v) {
+ String tag = (String) v.getTag();
+ if (tag.equals(TAG_SUBMIT)) {
+ returnData();
+ } else if (tag.equals(TAG_CANCEL)) {
+ if (mPickerOptions.cancelListener != null) {
+ mPickerOptions.cancelListener.onClick(v);
+ }
+ }
+ dismiss();
+ }
+
+ public void returnData() {
+ if (mPickerOptions.timeSelectListener != null) {
+ try {
+ Date date = WheelTime.dateFormat.parse(wheelTime.getTime());
+ mPickerOptions.timeSelectListener.onTimeSelect(date, clickView);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * 鍔ㄦ�佽缃爣棰�
+ *
+ * @param text 鏍囬鏂囨湰鍐呭
+ */
+ public void setTitleText(String text) {
+ TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
+ if (tvTitle != null) {
+ tvTitle.setText(text);
+ }
+ }
+
+ /**
+ * 鐩墠鏆傛椂鍙敮鎸佽缃�1900 - 2100骞�
+ *
+ * @param lunar 鍐滃巻鐨勫紑鍏�
+ */
+ public void setLunarCalendar(boolean lunar) {
+ try {
+ int year, month, day, hours, minute, seconds;
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(WheelTime.dateFormat.parse(wheelTime.getTime()));
+ year = calendar.get(Calendar.YEAR);
+ month = calendar.get(Calendar.MONTH);
+ day = calendar.get(Calendar.DAY_OF_MONTH);
+ hours = calendar.get(Calendar.HOUR_OF_DAY);
+ minute = calendar.get(Calendar.MINUTE);
+ seconds = calendar.get(Calendar.SECOND);
+
+ wheelTime.setLunarMode(lunar);
+ wheelTime.setLabels(mPickerOptions.label_year, mPickerOptions.label_month, mPickerOptions.label_day,
+ mPickerOptions.label_hours, mPickerOptions.label_minutes, mPickerOptions.label_seconds);
+ wheelTime.setPicker(year, month, day, hours, minute, seconds);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isLunarCalendar() {
+ return wheelTime.isLunarMode();
+ }
+
+
+ @Override
+ public boolean isDialog() {
+ return mPickerOptions.isDialog;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelOptions.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelOptions.java
new file mode 100644
index 0000000..48ffbde
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelOptions.java
@@ -0,0 +1,447 @@
+package com.hdl.widget.pickerview.view;
+
+import android.graphics.Typeface;
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.adapter.ArrayWheelAdapter;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+
+import java.util.List;
+
+import com.hdl.widget.pickerview.contrarywind.listener.OnItemSelectedListener;
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+public class WheelOptions<T> {
+ private View view;
+ private WheelView wv_option1;
+ private WheelView wv_option2;
+ private WheelView wv_option3;
+
+ private List<T> mOptions1Items;
+ private List<List<T>> mOptions2Items;
+ private List<List<List<T>>> mOptions3Items;
+
+ private boolean linkage = true;//榛樿鑱斿姩
+ private boolean isRestoreItem; //鍒囨崲鏃讹紝杩樺師绗竴椤�
+ private OnItemSelectedListener wheelListener_option1;
+ private OnItemSelectedListener wheelListener_option2;
+
+ private OnOptionsSelectChangeListener optionsSelectChangeListener;
+
+ //鏂囧瓧鐨勯鑹插拰鍒嗗壊绾跨殑棰滆壊
+ private int textColorOut;
+ private int textColorCenter;
+ private int dividerColor;
+
+ private WheelView.DividerType dividerType;
+
+ // 鏉$洰闂磋窛鍊嶆暟
+ private float lineSpacingMultiplier;
+
+ public View getView() {
+ return view;
+ }
+
+ public void setView(View view) {
+ this.view = view;
+ }
+
+ public WheelOptions(View view, boolean isRestoreItem) {
+ super();
+ this.isRestoreItem = isRestoreItem;
+ this.view = view;
+ wv_option1 = (WheelView) view.findViewById(R.id.options1);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ wv_option2 = (WheelView) view.findViewById(R.id.options2);
+ wv_option3 = (WheelView) view.findViewById(R.id.options3);
+ }
+
+
+ public void setPicker(List<T> options1Items,
+ List<List<T>> options2Items,
+ List<List<List<T>>> options3Items) {
+ this.mOptions1Items = options1Items;
+ this.mOptions2Items = options2Items;
+ this.mOptions3Items = options3Items;
+
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(mOptions1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(0).get(0)));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+
+ if (this.mOptions2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ }
+ if (this.mOptions3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ }
+
+ // 鑱斿姩鐩戝惉鍣�
+ wheelListener_option1 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ int opt2Select = 0;
+ if (mOptions2Items == null) {//鍙湁1绾ц仈鍔ㄦ暟鎹�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), 0, 0);
+ }
+ } else {
+ if (!isRestoreItem) {
+ opt2Select = wv_option2.getCurrentItem();//涓婁竴涓猳pt2鐨勯�変腑浣嶇疆
+ //鏂皁pt2鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt2Select = opt2Select >= mOptions2Items.get(index).size() - 1 ? mOptions2Items.get(index).size() - 1 : opt2Select;
+ }
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(index)));
+ wv_option2.setCurrentItem(opt2Select);
+
+ if (mOptions3Items != null) {
+ wheelListener_option2.onItemSelected(opt2Select);
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�1椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, opt2Select, 0);
+ }
+ }
+ }
+ }
+ };
+
+ wheelListener_option2 = new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(int index) {
+ if (mOptions3Items != null) {
+ int opt1Select = wv_option1.getCurrentItem();
+ opt1Select = opt1Select >= mOptions3Items.size() - 1 ? mOptions3Items.size() - 1 : opt1Select;
+ index = index >= mOptions2Items.get(opt1Select).size() - 1 ? mOptions2Items.get(opt1Select).size() - 1 : index;
+ int opt3 = 0;
+ if (!isRestoreItem) {
+ // wv_option3.getCurrentItem() 涓婁竴涓猳pt3鐨勯�変腑浣嶇疆
+ //鏂皁pt3鐨勪綅缃紝鍒ゆ柇濡傛灉鏃т綅缃病鏈夎秴杩囨暟鎹寖鍥达紝鍒欐部鐢ㄦ棫浣嶇疆锛屽惁鍒欓�変腑鏈�鍚庝竴椤�
+ opt3 = wv_option3.getCurrentItem() >= mOptions3Items.get(opt1Select).get(index).size() - 1 ?
+ mOptions3Items.get(opt1Select).get(index).size() - 1 : wv_option3.getCurrentItem();
+ }
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(wv_option1.getCurrentItem()).get(index)));
+ wv_option3.setCurrentItem(opt3);
+
+ //3绾ц仈鍔ㄦ暟鎹疄鏃跺洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, opt3);
+ }
+ } else {//鍙湁2绾ц仈鍔ㄦ暟鎹紝婊戝姩绗�2椤瑰洖璋�
+ if (optionsSelectChangeListener != null) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, 0);
+ }
+ }
+ }
+ };
+
+ // 娣诲姞鑱斿姩鐩戝惉
+ if (options1Items != null && linkage) {
+ wv_option1.setOnItemSelectedListener(wheelListener_option1);
+ }
+ if (options2Items != null && linkage) {
+ wv_option2.setOnItemSelectedListener(wheelListener_option2);
+ }
+ if (options3Items != null && linkage && optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+
+
+ //涓嶈仈鍔ㄦ儏鍐典笅
+ public void setNPicker(List<T> options1Items, List<T> options2Items, List<T> options3Items) {
+
+ // 閫夐」1
+ wv_option1.setAdapter(new ArrayWheelAdapter(options1Items));// 璁剧疆鏄剧ず鏁版嵁
+ wv_option1.setCurrentItem(0);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」2
+ if (options2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(options2Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ // 閫夐」3
+ if (options3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(options3Items));// 璁剧疆鏄剧ず鏁版嵁
+ }
+ wv_option3.setCurrentItem(wv_option3.getCurrentItem());
+ wv_option1.setIsOptions(true);
+ wv_option2.setIsOptions(true);
+ wv_option3.setIsOptions(true);
+
+ if (optionsSelectChangeListener != null) {
+ wv_option1.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(index, wv_option2.getCurrentItem(), wv_option3.getCurrentItem());
+ }
+ });
+ }
+
+ if (options2Items == null) {
+ wv_option2.setVisibility(View.GONE);
+ } else {
+ wv_option2.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option2.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, wv_option3.getCurrentItem());
+ }
+ });
+ }
+ }
+ if (options3Items == null) {
+ wv_option3.setVisibility(View.GONE);
+ } else {
+ wv_option3.setVisibility(View.VISIBLE);
+ if (optionsSelectChangeListener != null) {
+ wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index);
+ }
+ });
+ }
+ }
+ }
+
+ public void setTextContentSize(int textSize) {
+ wv_option1.setTextSize(textSize);
+ wv_option2.setTextSize(textSize);
+ wv_option3.setTextSize(textSize);
+ }
+
+ private void setTextColorOut() {
+ wv_option1.setTextColorOut(textColorOut);
+ wv_option2.setTextColorOut(textColorOut);
+ wv_option3.setTextColorOut(textColorOut);
+ }
+
+ private void setTextColorCenter() {
+ wv_option1.setTextColorCenter(textColorCenter);
+ wv_option2.setTextColorCenter(textColorCenter);
+ wv_option3.setTextColorCenter(textColorCenter);
+ }
+
+ private void setDividerColor() {
+ wv_option1.setDividerColor(dividerColor);
+ wv_option2.setDividerColor(dividerColor);
+ wv_option3.setDividerColor(dividerColor);
+ }
+
+ private void setDividerType() {
+ wv_option1.setDividerType(dividerType);
+ wv_option2.setDividerType(dividerType);
+ wv_option3.setDividerType(dividerType);
+ }
+
+ private void setLineSpacingMultiplier() {
+ wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier);
+
+ }
+
+ /**
+ * 璁剧疆閫夐」鐨勫崟浣�
+ *
+ * @param label1 鍗曚綅
+ * @param label2 鍗曚綅
+ * @param label3 鍗曚綅
+ */
+ public void setLabels(String label1, String label2, String label3) {
+ if (label1 != null) {
+ wv_option1.setLabel(label1);
+ }
+ if (label2 != null) {
+ wv_option2.setLabel(label2);
+ }
+ if (label3 != null) {
+ wv_option3.setLabel(label3);
+ }
+ }
+
+ /**
+ * 璁剧疆x杞村亸绉婚噺
+ */
+ public void setTextXOffset(int x_offset_one, int x_offset_two, int x_offset_three) {
+ wv_option1.setTextXOffset(x_offset_one);
+ wv_option2.setTextXOffset(x_offset_two);
+ wv_option3.setTextXOffset(x_offset_three);
+ }
+
+ /**
+ * 璁剧疆鏄惁寰幆婊氬姩
+ *
+ * @param cyclic 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic) {
+ wv_option1.setCyclic(cyclic);
+ wv_option2.setCyclic(cyclic);
+ wv_option3.setCyclic(cyclic);
+ }
+
+ /**
+ * 璁剧疆瀛椾綋鏍峰紡
+ *
+ * @param font 绯荤粺鎻愪緵鐨勫嚑绉嶆牱寮�
+ */
+ public void setTypeface(Typeface font) {
+ wv_option1.setTypeface(font);
+ wv_option2.setTypeface(font);
+ wv_option3.setTypeface(font);
+ }
+
+ /**
+ * 鍒嗗埆璁剧疆绗竴浜屼笁绾ф槸鍚﹀惊鐜粴鍔�
+ *
+ * @param cyclic1,cyclic2,cyclic3 鏄惁寰幆
+ */
+ public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
+ wv_option1.setCyclic(cyclic1);
+ wv_option2.setCyclic(cyclic2);
+ wv_option3.setCyclic(cyclic3);
+ }
+
+
+ /**
+ * 杩斿洖褰撳墠閫変腑鐨勭粨鏋滃搴旂殑浣嶇疆鏁扮粍 鍥犱负鏀寔涓夌骇鑱斿姩鏁堟灉锛屽垎涓変釜绾у埆绱㈠紩锛�0锛�1锛�2銆�
+ * 鍦ㄥ揩閫熸粦鍔ㄦ湭鍋滄鏃讹紝鐐瑰嚮纭畾鎸夐挳锛屼細杩涜鍒ゆ柇锛屽鏋滃尮閰嶆暟鎹秺鐣岋紝鍒欒涓�0锛岄槻姝ndex鍑洪敊瀵艰嚧宕╂簝銆�
+ *
+ * @return 绱㈠紩鏁扮粍
+ */
+ public int[] getCurrentItems() {
+ int[] currentItems = new int[3];
+ currentItems[0] = wv_option1.getCurrentItem();
+
+ if (mOptions2Items != null && mOptions2Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[1] = wv_option2.getCurrentItem() > (mOptions2Items.get(currentItems[0]).size() - 1) ? 0 : wv_option2.getCurrentItem();
+ } else {
+ currentItems[1] = wv_option2.getCurrentItem();
+ }
+
+ if (mOptions3Items != null && mOptions3Items.size() > 0) {//闈炵┖鍒ゆ柇
+ currentItems[2] = wv_option3.getCurrentItem() > (mOptions3Items.get(currentItems[0]).get(currentItems[1]).size() - 1) ? 0 : wv_option3.getCurrentItem();
+ } else {
+ currentItems[2] = wv_option3.getCurrentItem();
+ }
+
+ return currentItems;
+ }
+
+ public void setCurrentItems(int option1, int option2, int option3) {
+ if (linkage) {
+ itemSelected(option1, option2, option3);
+ } else {
+ wv_option1.setCurrentItem(option1);
+ wv_option2.setCurrentItem(option2);
+ wv_option3.setCurrentItem(option3);
+ }
+ }
+
+ private void itemSelected(int opt1Select, int opt2Select, int opt3Select) {
+ if (mOptions1Items != null) {
+ wv_option1.setCurrentItem(opt1Select);
+ }
+ if (mOptions2Items != null) {
+ wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(opt1Select)));
+ wv_option2.setCurrentItem(opt2Select);
+ }
+ if (mOptions3Items != null) {
+ wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(opt1Select).get(opt2Select)));
+ wv_option3.setCurrentItem(opt3Select);
+ }
+ }
+
+ /**
+ * 璁剧疆闂磋窛鍊嶆暟,浣嗘槸鍙兘鍦�1.2-4.0f涔嬮棿
+ *
+ * @param lineSpacingMultiplier
+ */
+ public void setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ this.lineSpacingMultiplier = lineSpacingMultiplier;
+ setLineSpacingMultiplier();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑棰滆壊
+ *
+ * @param dividerColor
+ */
+ public void setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ setDividerColor();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑绫诲瀷
+ *
+ * @param dividerType
+ */
+ public void setDividerType(WheelView.DividerType dividerType) {
+ this.dividerType = dividerType;
+ setDividerType();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenter(int textColorCenter) {
+ this.textColorCenter = textColorCenter;
+ setTextColorCenter();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸互澶栨枃瀛楃殑棰滆壊
+ *
+ * @param textColorOut
+ */
+ public void setTextColorOut(int textColorOut) {
+ this.textColorOut = textColorOut;
+ setTextColorOut();
+ }
+
+ /**
+ * Label 鏄惁鍙樉绀轰腑闂撮�変腑椤圭殑
+ *
+ * @param isCenterLabel
+ */
+
+ public void isCenterLabel(boolean isCenterLabel) {
+ wv_option1.isCenterLabel(isCenterLabel);
+ wv_option2.isCenterLabel(isCenterLabel);
+ wv_option3.isCenterLabel(isCenterLabel);
+ }
+
+ public void setOptionsSelectChangeListener(OnOptionsSelectChangeListener optionsSelectChangeListener) {
+ this.optionsSelectChangeListener = optionsSelectChangeListener;
+ }
+
+ public void setLinkage(boolean linkage) {
+ this.linkage = linkage;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelTime.java b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelTime.java
new file mode 100644
index 0000000..e057034
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/java/com/hdl/widget/pickerview/view/WheelTime.java
@@ -0,0 +1,929 @@
+package com.hdl.widget.pickerview.view;
+
+import android.view.View;
+
+import com.hdl.widgetxm.R;
+import com.hdl.widget.pickerview.adapter.ArrayWheelAdapter;
+import com.hdl.widget.pickerview.adapter.NumericWheelAdapter;
+import com.hdl.widget.pickerview.listener.ISelectTimeCallback;
+import com.hdl.widget.pickerview.utils.ChinaDate;
+import com.hdl.widget.pickerview.utils.LunarCalendar;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+import com.hdl.widget.pickerview.contrarywind.listener.OnItemSelectedListener;
+import com.hdl.widget.pickerview.contrarywind.view.WheelView;
+
+
+public class WheelTime {
+ public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private View view;
+ private WheelView wv_year;
+ private WheelView wv_month;
+ private WheelView wv_day;
+ private WheelView wv_hours;
+ private WheelView wv_minutes;
+ private WheelView wv_seconds;
+ private int gravity;
+
+ private boolean[] type;
+ private static final int DEFAULT_START_YEAR = 1900;
+ private static final int DEFAULT_END_YEAR = 2100;
+ private static final int DEFAULT_START_MONTH = 1;
+ private static final int DEFAULT_END_MONTH = 12;
+ private static final int DEFAULT_START_DAY = 1;
+ private static final int DEFAULT_END_DAY = 31;
+
+ private int startYear = DEFAULT_START_YEAR;
+ private int endYear = DEFAULT_END_YEAR;
+ private int startMonth = DEFAULT_START_MONTH;
+ private int endMonth = DEFAULT_END_MONTH;
+ private int startDay = DEFAULT_START_DAY;
+ private int endDay = DEFAULT_END_DAY; //琛ㄧず31澶╃殑
+ private int currentYear;
+
+ private int textSize;
+
+ //鏂囧瓧鐨勯鑹插拰鍒嗗壊绾跨殑棰滆壊
+ private int textColorOut;
+ private int textColorCenter;
+ private int dividerColor;
+
+ private float lineSpacingMultiplier;
+ private WheelView.DividerType dividerType;
+ private boolean isLunarCalendar = false;
+ private ISelectTimeCallback mSelectChangeCallback;
+
+ public WheelTime(View view, boolean[] type, int gravity, int textSize) {
+ super();
+ this.view = view;
+ this.type = type;
+ this.gravity = gravity;
+ this.textSize = textSize;
+ }
+
+ public void setLunarMode(boolean isLunarCalendar) {
+ this.isLunarCalendar = isLunarCalendar;
+ }
+
+ public boolean isLunarMode() {
+ return isLunarCalendar;
+ }
+
+ public void setPicker(int year, int month, int day) {
+ this.setPicker(year, month, day, 0, 0, 0);
+ }
+
+ public void setPicker(int year, final int month, int day, int h, int m, int s) {
+ if (isLunarCalendar) {
+ int[] lunar = LunarCalendar.solarToLunar(year, month + 1, day);
+ setLunar(lunar[0], lunar[1] - 1, lunar[2], lunar[3] == 1, h, m, s);
+ } else {
+ setSolar(year, month, day, h, m, s);
+ }
+ }
+
+ /**
+ * 璁剧疆鍐滃巻
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @param h
+ * @param m
+ * @param s
+ */
+ private void setLunar(int year, final int month, int day, boolean isLeap, int h, int m, int s) {
+ // 骞�
+ wv_year = (WheelView) view.findViewById(R.id.year);
+ wv_year.setAdapter(new ArrayWheelAdapter(ChinaDate.getYears(startYear, endYear)));// 璁剧疆"骞�"鐨勬樉绀烘暟鎹�
+ wv_year.setLabel("");// 娣诲姞鏂囧瓧
+ wv_year.setCurrentItem(year - startYear);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ wv_year.setGravity(gravity);
+
+ // 鏈�
+ wv_month = (WheelView) view.findViewById(R.id.month);
+ wv_month.setAdapter(new ArrayWheelAdapter(ChinaDate.getMonths(year)));
+ wv_month.setLabel("");
+
+ int leapMonth = ChinaDate.leapMonth(year);
+ if (leapMonth != 0 && (month > leapMonth - 1 || isLeap)) { //閫変腑鏈堟槸闂版湀鎴栧ぇ浜庨棸鏈�
+ wv_month.setCurrentItem(month + 1);
+ } else {
+ wv_month.setCurrentItem(month);
+ }
+
+ wv_month.setGravity(gravity);
+
+ // 鏃�
+ wv_day = (WheelView) view.findViewById(R.id.day);
+ // 鍒ゆ柇澶у皬鏈堝強鏄惁闂板勾,鐢ㄦ潵纭畾"鏃�"鐨勬暟鎹�
+ if (ChinaDate.leapMonth(year) == 0) {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year, month))));
+ } else {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year))));
+ }
+ wv_day.setLabel("");
+ wv_day.setCurrentItem(day - 1);
+ wv_day.setGravity(gravity);
+
+ wv_hours = (WheelView) view.findViewById(R.id.hour);
+ wv_hours.setAdapter(new NumericWheelAdapter(0, 23));
+ //wv_hours.setLabel(context.getString(R.string.pickerview_hours));// 娣诲姞鏂囧瓧
+ wv_hours.setCurrentItem(h);
+ wv_hours.setGravity(gravity);
+
+ wv_minutes = (WheelView) view.findViewById(R.id.min);
+ wv_minutes.setAdapter(new NumericWheelAdapter(0, 59));
+ //wv_minutes.setLabel(context.getString(R.string.pickerview_minutes));// 娣诲姞鏂囧瓧
+ wv_minutes.setCurrentItem(m);
+ wv_minutes.setGravity(gravity);
+
+ wv_seconds = (WheelView) view.findViewById(R.id.second);
+ wv_seconds.setAdapter(new NumericWheelAdapter(0, 59));
+ //wv_seconds.setLabel(context.getString(R.string.pickerview_minutes));// 娣诲姞鏂囧瓧
+ wv_seconds.setCurrentItem(m);
+ wv_seconds.setGravity(gravity);
+
+ // 娣诲姞"骞�"鐩戝惉
+ wv_year.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ int year_num = index + startYear;
+ // 鍒ゆ柇鏄笉鏄棸骞�,鏉ョ‘瀹氭湀鍜屾棩鐨勯�夋嫨
+ wv_month.setAdapter(new ArrayWheelAdapter(ChinaDate.getMonths(year_num)));
+ if (ChinaDate.leapMonth(year_num) != 0 && wv_month.getCurrentItem() > ChinaDate.leapMonth(year_num) - 1) {
+ wv_month.setCurrentItem(wv_month.getCurrentItem() + 1);
+ } else {
+ wv_month.setCurrentItem(wv_month.getCurrentItem());
+ }
+
+ int currentIndex = wv_day.getCurrentItem();
+ int maxItem = 29;
+ if (ChinaDate.leapMonth(year_num) != 0 && wv_month.getCurrentItem() > ChinaDate.leapMonth(year_num) - 1) {
+ if (wv_month.getCurrentItem() == ChinaDate.leapMonth(year_num) + 1) {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year_num))));
+ maxItem = ChinaDate.leapDays(year_num);
+ } else {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, wv_month.getCurrentItem()))));
+ maxItem = ChinaDate.monthDays(year_num, wv_month.getCurrentItem());
+ }
+ } else {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, wv_month.getCurrentItem() + 1))));
+ maxItem = ChinaDate.monthDays(year_num, wv_month.getCurrentItem() + 1);
+ }
+
+ if (currentIndex > maxItem - 1) {
+ wv_day.setCurrentItem(maxItem - 1);
+ }
+
+ if (mSelectChangeCallback != null) {
+ mSelectChangeCallback.onTimeSelectChanged();
+ }
+ }
+ });
+
+ // 娣诲姞"鏈�"鐩戝惉
+ wv_month.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ int month_num = index;
+ int year_num = wv_year.getCurrentItem() + startYear;
+ int currentIndex = wv_day.getCurrentItem();
+ int maxItem = 29;
+ if (ChinaDate.leapMonth(year_num) != 0 && month_num > ChinaDate.leapMonth(year_num) - 1) {
+ if (wv_month.getCurrentItem() == ChinaDate.leapMonth(year_num) + 1) {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year_num))));
+ maxItem = ChinaDate.leapDays(year_num);
+ } else {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, month_num))));
+ maxItem = ChinaDate.monthDays(year_num, month_num);
+ }
+ } else {
+ wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, month_num + 1))));
+ maxItem = ChinaDate.monthDays(year_num, month_num + 1);
+ }
+
+ if (currentIndex > maxItem - 1) {
+ wv_day.setCurrentItem(maxItem - 1);
+ }
+
+ if (mSelectChangeCallback != null) {
+ mSelectChangeCallback.onTimeSelectChanged();
+ }
+ }
+ });
+
+ setChangedListener(wv_day);
+ setChangedListener(wv_hours);
+ setChangedListener(wv_minutes);
+ setChangedListener(wv_seconds);
+
+ if (type.length != 6) {
+ throw new RuntimeException("type[] length is not 6");
+ }
+ wv_year.setVisibility(type[0] ? View.VISIBLE : View.GONE);
+ wv_month.setVisibility(type[1] ? View.VISIBLE : View.GONE);
+ wv_day.setVisibility(type[2] ? View.VISIBLE : View.GONE);
+ wv_hours.setVisibility(type[3] ? View.VISIBLE : View.GONE);
+ wv_minutes.setVisibility(type[4] ? View.VISIBLE : View.GONE);
+ wv_seconds.setVisibility(type[5] ? View.VISIBLE : View.GONE);
+ setContentTextSize();
+ }
+
+ /**
+ * 璁剧疆鍏巻
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @param h
+ * @param m
+ * @param s
+ */
+ private void setSolar(int year, final int month, int day, int h, int m, int s) {
+ // 娣诲姞澶у皬鏈堟湀浠藉苟灏嗗叾杞崲涓簂ist,鏂逛究涔嬪悗鐨勫垽鏂�
+ String[] months_big = {"1", "3", "5", "7", "8", "10", "12"};
+ String[] months_little = {"4", "6", "9", "11"};
+
+ final List<String> list_big = Arrays.asList(months_big);
+ final List<String> list_little = Arrays.asList(months_little);
+
+ currentYear = year;
+ // 骞�
+ wv_year = (WheelView) view.findViewById(R.id.year);
+ wv_year.setAdapter(new NumericWheelAdapter(startYear, endYear));// 璁剧疆"骞�"鐨勬樉绀烘暟鎹�
+
+
+ wv_year.setCurrentItem(year - startYear);// 鍒濆鍖栨椂鏄剧ず鐨勬暟鎹�
+ wv_year.setGravity(gravity);
+ // 鏈�
+ wv_month = (WheelView) view.findViewById(R.id.month);
+ if (startYear == endYear) {//寮�濮嬪勾绛変簬缁堟骞�
+ wv_month.setAdapter(new NumericWheelAdapter(startMonth, endMonth));
+ wv_month.setCurrentItem(month + 1 - startMonth);
+ } else if (year == startYear) {
+ //璧峰鏃ユ湡鐨勬湀浠芥帶鍒�
+ wv_month.setAdapter(new NumericWheelAdapter(startMonth, 12));
+ wv_month.setCurrentItem(month + 1 - startMonth);
+ } else if (year == endYear) {
+ //缁堟鏃ユ湡鐨勬湀浠芥帶鍒�
+ wv_month.setAdapter(new NumericWheelAdapter(1, endMonth));
+ wv_month.setCurrentItem(month);
+ } else {
+ wv_month.setAdapter(new NumericWheelAdapter(1, 12));
+ wv_month.setCurrentItem(month);
+ }
+ wv_month.setGravity(gravity);
+ // 鏃�
+ wv_day = (WheelView) view.findViewById(R.id.day);
+
+ if (startYear == endYear && startMonth == endMonth) {
+ if (list_big.contains(String.valueOf(month + 1))) {
+ if (endDay > 31) {
+ endDay = 31;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay));
+ } else if (list_little.contains(String.valueOf(month + 1))) {
+ if (endDay > 30) {
+ endDay = 30;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay));
+ } else {
+ // 闂板勾
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
+ if (endDay > 29) {
+ endDay = 29;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay));
+ } else {
+ if (endDay > 28) {
+ endDay = 28;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay));
+ }
+ }
+ wv_day.setCurrentItem(day - startDay);
+ } else if (year == startYear && month + 1 == startMonth) {
+ // 璧峰鏃ユ湡鐨勫ぉ鏁版帶鍒�
+ if (list_big.contains(String.valueOf(month + 1))) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, 31));
+ } else if (list_little.contains(String.valueOf(month + 1))) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, 30));
+ } else {
+ // 闂板勾
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, 29));
+ } else {
+
+ wv_day.setAdapter(new NumericWheelAdapter(startDay, 28));
+ }
+ }
+ wv_day.setCurrentItem(day - startDay);
+ } else if (year == endYear && month + 1 == endMonth) {
+ // 缁堟鏃ユ湡鐨勫ぉ鏁版帶鍒�
+ if (list_big.contains(String.valueOf(month + 1))) {
+ if (endDay > 31) {
+ endDay = 31;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(1, endDay));
+ } else if (list_little.contains(String.valueOf(month + 1))) {
+ if (endDay > 30) {
+ endDay = 30;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(1, endDay));
+ } else {
+ // 闂板勾
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
+ if (endDay > 29) {
+ endDay = 29;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(1, endDay));
+ } else {
+ if (endDay > 28) {
+ endDay = 28;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(1, endDay));
+ }
+ }
+ wv_day.setCurrentItem(day - 1);
+ } else {
+ // 鍒ゆ柇澶у皬鏈堝強鏄惁闂板勾,鐢ㄦ潵纭畾"鏃�"鐨勬暟鎹�
+ if (list_big.contains(String.valueOf(month + 1))) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(1, 31));
+ } else if (list_little.contains(String.valueOf(month + 1))) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(1, 30));
+ } else {
+ // 闂板勾
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
+
+ wv_day.setAdapter(new NumericWheelAdapter(1, 29));
+ } else {
+
+ wv_day.setAdapter(new NumericWheelAdapter(1, 28));
+ }
+ }
+ wv_day.setCurrentItem(day - 1);
+ }
+
+ wv_day.setGravity(gravity);
+ //鏃�
+ wv_hours = (WheelView) view.findViewById(R.id.hour);
+ wv_hours.setAdapter(new NumericWheelAdapter(0, 23));
+
+ wv_hours.setCurrentItem(h);
+ wv_hours.setGravity(gravity);
+ //鍒�
+ wv_minutes = (WheelView) view.findViewById(R.id.min);
+ wv_minutes.setAdapter(new NumericWheelAdapter(0, 59));
+
+ wv_minutes.setCurrentItem(m);
+ wv_minutes.setGravity(gravity);
+ //绉�
+ wv_seconds = (WheelView) view.findViewById(R.id.second);
+ wv_seconds.setAdapter(new NumericWheelAdapter(0, 59));
+
+ wv_seconds.setCurrentItem(s);
+ wv_seconds.setGravity(gravity);
+
+ // 娣诲姞"骞�"鐩戝惉
+ wv_year.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ int year_num = index + startYear;
+ currentYear = year_num;
+ int currentMonthItem = wv_month.getCurrentItem();//璁板綍涓婁竴娆$殑item浣嶇疆
+ // 鍒ゆ柇澶у皬鏈堝強鏄惁闂板勾,鐢ㄦ潵纭畾"鏃�"鐨勬暟鎹�
+ if (startYear == endYear) {
+ //閲嶆柊璁剧疆鏈堜唤
+ wv_month.setAdapter(new NumericWheelAdapter(startMonth, endMonth));
+
+ if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) {
+ currentMonthItem = wv_month.getAdapter().getItemsCount() - 1;
+ wv_month.setCurrentItem(currentMonthItem);
+ }
+
+ int monthNum = currentMonthItem + startMonth;
+
+ if (startMonth == endMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, monthNum, startDay, endDay, list_big, list_little);
+ } else if (monthNum == startMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, monthNum, startDay, 31, list_big, list_little);
+ } else if (monthNum == endMonth) {
+ setReDay(year_num, monthNum, 1, endDay, list_big, list_little);
+ } else {//閲嶆柊璁剧疆鏃�
+ setReDay(year_num, monthNum, 1, 31, list_big, list_little);
+ }
+ } else if (year_num == startYear) {//绛変簬寮�濮嬬殑骞�
+ //閲嶆柊璁剧疆鏈堜唤
+ wv_month.setAdapter(new NumericWheelAdapter(startMonth, 12));
+
+ if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) {
+ currentMonthItem = wv_month.getAdapter().getItemsCount() - 1;
+ wv_month.setCurrentItem(currentMonthItem);
+ }
+
+ int month = currentMonthItem + startMonth;
+ if (month == startMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, month, startDay, 31, list_big, list_little);
+ } else {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, month, 1, 31, list_big, list_little);
+ }
+
+ } else if (year_num == endYear) {
+ //閲嶆柊璁剧疆鏈堜唤
+ wv_month.setAdapter(new NumericWheelAdapter(1, endMonth));
+ if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) {
+ currentMonthItem = wv_month.getAdapter().getItemsCount() - 1;
+ wv_month.setCurrentItem(currentMonthItem);
+ }
+ int monthNum = currentMonthItem + 1;
+
+ if (monthNum == endMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, monthNum, 1, endDay, list_big, list_little);
+ } else {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, monthNum, 1, 31, list_big, list_little);
+ }
+
+ } else {
+ //閲嶆柊璁剧疆鏈堜唤
+ wv_month.setAdapter(new NumericWheelAdapter(1, 12));
+ //閲嶆柊璁剧疆鏃�
+ setReDay(year_num, wv_month.getCurrentItem() + 1, 1, 31, list_big, list_little);
+ }
+
+ if (mSelectChangeCallback != null) {
+ mSelectChangeCallback.onTimeSelectChanged();
+ }
+ }
+ });
+
+
+ // 娣诲姞"鏈�"鐩戝惉
+ wv_month.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ int month_num = index + 1;
+
+ if (startYear == endYear) {
+ month_num = month_num + startMonth - 1;
+ if (startMonth == endMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, month_num, startDay, endDay, list_big, list_little);
+ } else if (startMonth == month_num) {
+
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, month_num, startDay, 31, list_big, list_little);
+ } else if (endMonth == month_num) {
+ setReDay(currentYear, month_num, 1, endDay, list_big, list_little);
+ } else {
+ setReDay(currentYear, month_num, 1, 31, list_big, list_little);
+ }
+ } else if (currentYear == startYear) {
+ month_num = month_num + startMonth - 1;
+ if (month_num == startMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, month_num, startDay, 31, list_big, list_little);
+ } else {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, month_num, 1, 31, list_big, list_little);
+ }
+
+ } else if (currentYear == endYear) {
+ if (month_num == endMonth) {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, wv_month.getCurrentItem() + 1, 1, endDay, list_big, list_little);
+ } else {
+ setReDay(currentYear, wv_month.getCurrentItem() + 1, 1, 31, list_big, list_little);
+ }
+
+ } else {
+ //閲嶆柊璁剧疆鏃�
+ setReDay(currentYear, month_num, 1, 31, list_big, list_little);
+ }
+
+ if (mSelectChangeCallback != null) {
+ mSelectChangeCallback.onTimeSelectChanged();
+ }
+ }
+ });
+
+ setChangedListener(wv_day);
+ setChangedListener(wv_hours);
+ setChangedListener(wv_minutes);
+ setChangedListener(wv_seconds);
+
+ if (type.length != 6) {
+ throw new IllegalArgumentException("type[] length is not 6");
+ }
+ wv_year.setVisibility(type[0] ? View.VISIBLE : View.GONE);
+ wv_month.setVisibility(type[1] ? View.VISIBLE : View.GONE);
+ wv_day.setVisibility(type[2] ? View.VISIBLE : View.GONE);
+ wv_hours.setVisibility(type[3] ? View.VISIBLE : View.GONE);
+ wv_minutes.setVisibility(type[4] ? View.VISIBLE : View.GONE);
+ wv_seconds.setVisibility(type[5] ? View.VISIBLE : View.GONE);
+ setContentTextSize();
+ }
+
+ private void setChangedListener(WheelView wheelView) {
+ if (mSelectChangeCallback != null) {
+ wheelView.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(int index) {
+ mSelectChangeCallback.onTimeSelectChanged();
+ }
+ });
+ }
+
+ }
+
+
+ private void setReDay(int year_num, int monthNum, int startD, int endD, List<String> list_big, List<String> list_little) {
+ int currentItem = wv_day.getCurrentItem();
+
+// int maxItem;
+ if (list_big.contains(String.valueOf(monthNum))) {
+ if (endD > 31) {
+ endD = 31;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startD, endD));
+// maxItem = endD;
+ } else if (list_little.contains(String.valueOf(monthNum))) {
+ if (endD > 30) {
+ endD = 30;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startD, endD));
+// maxItem = endD;
+ } else {
+ if ((year_num % 4 == 0 && year_num % 100 != 0)
+ || year_num % 400 == 0) {
+ if (endD > 29) {
+ endD = 29;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startD, endD));
+// maxItem = endD;
+ } else {
+ if (endD > 28) {
+ endD = 28;
+ }
+ wv_day.setAdapter(new NumericWheelAdapter(startD, endD));
+// maxItem = endD;
+ }
+ }
+
+ if (currentItem > wv_day.getAdapter().getItemsCount() - 1) {
+ currentItem = wv_day.getAdapter().getItemsCount() - 1;
+ wv_day.setCurrentItem(currentItem);
+ }
+ }
+
+
+ private void setContentTextSize() {
+ wv_day.setTextSize(textSize);
+ wv_month.setTextSize(textSize);
+ wv_year.setTextSize(textSize);
+ wv_hours.setTextSize(textSize);
+ wv_minutes.setTextSize(textSize);
+ wv_seconds.setTextSize(textSize);
+ }
+
+ private void setTextColorOut() {
+ wv_day.setTextColorOut(textColorOut);
+ wv_month.setTextColorOut(textColorOut);
+ wv_year.setTextColorOut(textColorOut);
+ wv_hours.setTextColorOut(textColorOut);
+ wv_minutes.setTextColorOut(textColorOut);
+ wv_seconds.setTextColorOut(textColorOut);
+ }
+
+ private void setTextColorCenter() {
+ wv_day.setTextColorCenter(textColorCenter);
+ wv_month.setTextColorCenter(textColorCenter);
+ wv_year.setTextColorCenter(textColorCenter);
+ wv_hours.setTextColorCenter(textColorCenter);
+ wv_minutes.setTextColorCenter(textColorCenter);
+ wv_seconds.setTextColorCenter(textColorCenter);
+ }
+
+ private void setDividerColor() {
+ wv_day.setDividerColor(dividerColor);
+ wv_month.setDividerColor(dividerColor);
+ wv_year.setDividerColor(dividerColor);
+ wv_hours.setDividerColor(dividerColor);
+ wv_minutes.setDividerColor(dividerColor);
+ wv_seconds.setDividerColor(dividerColor);
+ }
+
+ private void setDividerType() {
+
+ wv_day.setDividerType(dividerType);
+ wv_month.setDividerType(dividerType);
+ wv_year.setDividerType(dividerType);
+ wv_hours.setDividerType(dividerType);
+ wv_minutes.setDividerType(dividerType);
+ wv_seconds.setDividerType(dividerType);
+
+ }
+
+ private void setLineSpacingMultiplier() {
+ wv_day.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_month.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_year.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_hours.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_minutes.setLineSpacingMultiplier(lineSpacingMultiplier);
+ wv_seconds.setLineSpacingMultiplier(lineSpacingMultiplier);
+ }
+
+ public void setLabels(String label_year, String label_month, String label_day, String label_hours, String label_mins, String label_seconds) {
+ if (isLunarCalendar) {
+ return;
+ }
+
+ if (label_year != null) {
+ wv_year.setLabel(label_year);
+ } else {
+ wv_year.setLabel(view.getContext().getString(R.string.pickerview_year));
+ }
+ if (label_month != null) {
+ wv_month.setLabel(label_month);
+ } else {
+ wv_month.setLabel(view.getContext().getString(R.string.pickerview_month));
+ }
+ if (label_day != null) {
+ wv_day.setLabel(label_day);
+ } else {
+ wv_day.setLabel(view.getContext().getString(R.string.pickerview_day));
+ }
+ if (label_hours != null) {
+ wv_hours.setLabel(label_hours);
+ } else {
+ wv_hours.setLabel(view.getContext().getString(R.string.pickerview_hours));
+ }
+ if (label_mins != null) {
+ wv_minutes.setLabel(label_mins);
+ } else {
+ wv_minutes.setLabel(view.getContext().getString(R.string.pickerview_minutes));
+ }
+ if (label_seconds != null) {
+ wv_seconds.setLabel(label_seconds);
+ } else {
+ wv_seconds.setLabel(view.getContext().getString(R.string.pickerview_seconds));
+ }
+
+ }
+
+ public void setTextXOffset(int x_offset_year, int x_offset_month, int x_offset_day,
+ int x_offset_hours, int x_offset_minutes, int x_offset_seconds) {
+ wv_year.setTextXOffset(x_offset_year);
+ wv_month.setTextXOffset(x_offset_month);
+ wv_day.setTextXOffset(x_offset_day);
+ wv_hours.setTextXOffset(x_offset_hours);
+ wv_minutes.setTextXOffset(x_offset_minutes);
+ wv_seconds.setTextXOffset(x_offset_seconds);
+ }
+
+ /**
+ * 璁剧疆鏄惁寰幆婊氬姩
+ *
+ * @param cyclic
+ */
+ public void setCyclic(boolean cyclic) {
+ wv_year.setCyclic(cyclic);
+ wv_month.setCyclic(cyclic);
+ wv_day.setCyclic(cyclic);
+ wv_hours.setCyclic(cyclic);
+ wv_minutes.setCyclic(cyclic);
+ wv_seconds.setCyclic(cyclic);
+ }
+
+ public String getTime() {
+ if (isLunarCalendar) {
+ //濡傛灉鏄啘鍘� 杩斿洖瀵瑰簲鐨勫叕鍘嗘椂闂�
+ return getLunarTime();
+ }
+ StringBuilder sb = new StringBuilder();
+ if (currentYear == startYear) {
+ /* int i = wv_month.getCurrentItem() + startMonth;
+ System.out.println("i:" + i);*/
+ if ((wv_month.getCurrentItem() + startMonth) == startMonth) {
+ sb.append((wv_year.getCurrentItem() + startYear)).append("-")
+ .append((wv_month.getCurrentItem() + startMonth)).append("-")
+ .append((wv_day.getCurrentItem() + startDay)).append(" ")
+ .append(wv_hours.getCurrentItem()).append(":")
+ .append(wv_minutes.getCurrentItem()).append(":")
+ .append(wv_seconds.getCurrentItem());
+ } else {
+ sb.append((wv_year.getCurrentItem() + startYear)).append("-")
+ .append((wv_month.getCurrentItem() + startMonth)).append("-")
+ .append((wv_day.getCurrentItem() + 1)).append(" ")
+ .append(wv_hours.getCurrentItem()).append(":")
+ .append(wv_minutes.getCurrentItem()).append(":")
+ .append(wv_seconds.getCurrentItem());
+ }
+
+ } else {
+ sb.append((wv_year.getCurrentItem() + startYear)).append("-")
+ .append((wv_month.getCurrentItem() + 1)).append("-")
+ .append((wv_day.getCurrentItem() + 1)).append(" ")
+ .append(wv_hours.getCurrentItem()).append(":")
+ .append(wv_minutes.getCurrentItem()).append(":")
+ .append(wv_seconds.getCurrentItem());
+ }
+
+ return sb.toString();
+ }
+
+
+ /**
+ * 鍐滃巻杩斿洖瀵瑰簲鐨勫叕鍘嗘椂闂�
+ *
+ * @return
+ */
+ private String getLunarTime() {
+ StringBuilder sb = new StringBuilder();
+ int year = wv_year.getCurrentItem() + startYear;
+ int month = 1;
+ boolean isLeapMonth = false;
+ if (ChinaDate.leapMonth(year) == 0) {
+ month = wv_month.getCurrentItem() + 1;
+ } else {
+ if ((wv_month.getCurrentItem() + 1) - ChinaDate.leapMonth(year) <= 0) {
+ month = wv_month.getCurrentItem() + 1;
+ } else if ((wv_month.getCurrentItem() + 1) - ChinaDate.leapMonth(year) == 1) {
+ month = wv_month.getCurrentItem();
+ isLeapMonth = true;
+ } else {
+ month = wv_month.getCurrentItem();
+ }
+ }
+ int day = wv_day.getCurrentItem() + 1;
+ int[] solar = LunarCalendar.lunarToSolar(year, month, day, isLeapMonth);
+
+ sb.append(solar[0]).append("-")
+ .append(solar[1]).append("-")
+ .append(solar[2]).append(" ")
+ .append(wv_hours.getCurrentItem()).append(":")
+ .append(wv_minutes.getCurrentItem()).append(":")
+ .append(wv_seconds.getCurrentItem());
+ return sb.toString();
+ }
+
+ public View getView() {
+ return view;
+ }
+
+ public int getStartYear() {
+ return startYear;
+ }
+
+ public void setStartYear(int startYear) {
+ this.startYear = startYear;
+ }
+
+ public int getEndYear() {
+ return endYear;
+ }
+
+ public void setEndYear(int endYear) {
+ this.endYear = endYear;
+ }
+
+
+ public void setRangDate(Calendar startDate, Calendar endDate) {
+
+ if (startDate == null && endDate != null) {
+ int year = endDate.get(Calendar.YEAR);
+ int month = endDate.get(Calendar.MONTH) + 1;
+ int day = endDate.get(Calendar.DAY_OF_MONTH);
+ if (year > startYear) {
+ this.endYear = year;
+ this.endMonth = month;
+ this.endDay = day;
+ } else if (year == startYear) {
+ if (month > startMonth) {
+ this.endYear = year;
+ this.endMonth = month;
+ this.endDay = day;
+ } else if (month == startMonth) {
+ if (day > startDay) {
+ this.endYear = year;
+ this.endMonth = month;
+ this.endDay = day;
+ }
+ }
+ }
+
+ } else if (startDate != null && endDate == null) {
+ int year = startDate.get(Calendar.YEAR);
+ int month = startDate.get(Calendar.MONTH) + 1;
+ int day = startDate.get(Calendar.DAY_OF_MONTH);
+ if (year < endYear) {
+ this.startMonth = month;
+ this.startDay = day;
+ this.startYear = year;
+ } else if (year == endYear) {
+ if (month < endMonth) {
+ this.startMonth = month;
+ this.startDay = day;
+ this.startYear = year;
+ } else if (month == endMonth) {
+ if (day < endDay) {
+ this.startMonth = month;
+ this.startDay = day;
+ this.startYear = year;
+ }
+ }
+ }
+
+ } else if (startDate != null && endDate != null) {
+ this.startYear = startDate.get(Calendar.YEAR);
+ this.endYear = endDate.get(Calendar.YEAR);
+ this.startMonth = startDate.get(Calendar.MONTH) + 1;
+ this.endMonth = endDate.get(Calendar.MONTH) + 1;
+ this.startDay = startDate.get(Calendar.DAY_OF_MONTH);
+ this.endDay = endDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ }
+
+ /**
+ * 璁剧疆闂磋窛鍊嶆暟,浣嗘槸鍙兘鍦�1.0-4.0f涔嬮棿
+ *
+ * @param lineSpacingMultiplier
+ */
+ public void setLineSpacingMultiplier(float lineSpacingMultiplier) {
+ this.lineSpacingMultiplier = lineSpacingMultiplier;
+ setLineSpacingMultiplier();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑棰滆壊
+ *
+ * @param dividerColor
+ */
+ public void setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ setDividerColor();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾跨殑绫诲瀷
+ *
+ * @param dividerType
+ */
+ public void setDividerType(WheelView.DividerType dividerType) {
+ this.dividerType = dividerType;
+ setDividerType();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ *
+ * @param textColorCenter
+ */
+ public void setTextColorCenter(int textColorCenter) {
+ this.textColorCenter = textColorCenter;
+ setTextColorCenter();
+ }
+
+ /**
+ * 璁剧疆鍒嗗壊绾夸互澶栨枃瀛楃殑棰滆壊
+ *
+ * @param textColorOut
+ */
+ public void setTextColorOut(int textColorOut) {
+ this.textColorOut = textColorOut;
+ setTextColorOut();
+ }
+
+ /**
+ * @param isCenterLabel 鏄惁鍙樉绀轰腑闂撮�変腑椤圭殑
+ */
+ public void isCenterLabel(boolean isCenterLabel) {
+ wv_day.isCenterLabel(isCenterLabel);
+ wv_month.isCenterLabel(isCenterLabel);
+ wv_year.isCenterLabel(isCenterLabel);
+ wv_hours.isCenterLabel(isCenterLabel);
+ wv_minutes.isCenterLabel(isCenterLabel);
+ wv_seconds.isCenterLabel(isCenterLabel);
+ }
+
+ public void setSelectChangeCallback(ISelectTimeCallback mSelectChangeCallback) {
+ this.mSelectChangeCallback = mSelectChangeCallback;
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_in.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_in.xml
new file mode 100644
index 0000000..9ab2df6
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_in.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+
+ <alpha
+ android:duration="@integer/animation_default_duration"
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0" />
+
+ <scale
+ android:duration="@integer/animation_default_duration"
+ android:fromXScale="0.0"
+ android:toXScale="1.0"
+ android:fromYScale="0.0"
+ android:toYScale="1.0"
+ android:pivotX="50%"
+ android:pivotY="50%"/>
+
+</set>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_out.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_out.xml
new file mode 100644
index 0000000..3eb1e06
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_dialog_scale_out.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+
+ <alpha
+ android:duration="@integer/animation_default_duration"
+ android:fromAlpha="1.0"
+ android:toAlpha="0.3" />
+
+ <scale
+ android:duration="@integer/animation_default_duration"
+ android:fromXScale="1.0"
+ android:toXScale="0.0"
+ android:fromYScale="1.0"
+ android:toYScale="0.0"
+ android:pivotX="50%"
+ android:pivotY="50%"/>
+</set>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_in_bottom.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_in_bottom.xml
new file mode 100644
index 0000000..212e266
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_in_bottom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <translate
+ android:duration="@integer/animation_default_duration"
+ android:fromXDelta="0%"
+ android:toXDelta="0%"
+ android:fromYDelta="100%"
+ android:toYDelta="0%"/>
+</set>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_out_bottom.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_out_bottom.xml
new file mode 100644
index 0000000..a2d0ce9
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/anim/pickerview_slide_out_bottom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <translate
+ android:duration="@integer/animation_default_duration"
+ android:fromXDelta="0%"
+ android:toXDelta="0%"
+ android:fromYDelta="0%"
+ android:toYDelta="100%"/>
+</set>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_b.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_b.xml
new file mode 100644
index 0000000..78902fc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_b.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+ <solid android:color="#000000" />
+ <corners android:radius="20dp" />
+</shape>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_g.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_g.xml
new file mode 100644
index 0000000..68ff8cb
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_g.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+ <solid android:color="#F0F0F0" />
+ <corners android:radius="5dp" />
+</shape>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_w.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_w.xml
new file mode 100644
index 0000000..2d41afc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_app_w.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle" >
+ <solid android:color="#FFFFFF" />
+ <corners android:radius="5dp" />
+</shape>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_shadow_w.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_shadow_w.xml
new file mode 100644
index 0000000..3591060
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_btn_shape_shadow_w.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <!-- 闃村奖 -->
+
+ <item>
+ <shape android:shape="rectangle" >
+
+ <gradient
+ android:type="linear"
+ android:endColor="#0f000000"
+ android:startColor="#0f000000"
+ />
+
+ <corners
+ android:bottomLeftRadius="5dp"
+ android:bottomRightRadius="5dp"
+ android:topLeftRadius="5dp"
+ android:topRightRadius="5dp" />
+ </shape>
+ </item>
+
+
+ <!-- 鑳屾櫙 -->
+ <!-- 鑳屾櫙鐩栧湪闃村奖涓婇潰锛岀暀鍑鸿竟璺濊闃村奖鏄剧ず鍑烘潵 -->
+ <item
+ android:bottom="3dp"
+ android:right="1dp"
+ android:left="1dp"
+ android:top="0dp"
+ >
+ <shape android:shape="rectangle" >
+
+ <solid android:color="#ffffff"/>
+
+ <corners
+ android:bottomLeftRadius="5dp"
+ android:bottomRightRadius="5dp"
+ android:topLeftRadius="5dp"
+ android:topRightRadius="5dp" />
+ </shape>
+ </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_click_effect_select.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_click_effect_select.xml
new file mode 100644
index 0000000..4450361
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/gd_click_effect_select.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!--瑙︽懜鐘舵�佹椂棰滆壊-->
+ <item android:drawable="@drawable/gd_btn_shape_app_g" android:state_focused="true" />
+ <!--鐐瑰嚮鐘舵�佹槸棰滆壊-->
+ <item android:drawable="@drawable/gd_btn_shape_app_g" android:state_pressed="true" />
+ <!--榛樿棰滆壊-->
+ <item android:drawable="@drawable/gd_btn_shape_app_w" />
+
+</selector>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_add.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_add.png
new file mode 100644
index 0000000..67c9c6b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_add.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_back.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_back.png
new file mode 100644
index 0000000..a6c705b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_back.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_delete.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_delete.png
new file mode 100644
index 0000000..557e0cc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_delete.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_home.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_home.png
new file mode 100644
index 0000000..70adc6e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_home.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_mylocation.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_mylocation.png
new file mode 100644
index 0000000..1a70029
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_mylocation.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_now.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_now.png
new file mode 100644
index 0000000..b3c24de
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_now.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_search.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_search.png
new file mode 100644
index 0000000..e8455ab
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_search.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_zoom_out.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_zoom_out.png
new file mode 100644
index 0000000..0cb1561
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gdmap_zoom_out.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gps_point.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gps_point.png
new file mode 100644
index 0000000..ec4332d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_gps_point.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_arc_scale_bg.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_arc_scale_bg.png
new file mode 100644
index 0000000..a400f1f
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_arc_scale_bg.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_bg_top.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_bg_top.png
new file mode 100644
index 0000000..389b0c3
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_bg_top.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_bg.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_bg.png
new file mode 100644
index 0000000..fa90dab
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_bg.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_open.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_open.png
new file mode 100644
index 0000000..4093bea
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_open.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_progress.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_progress.png
new file mode 100644
index 0000000..2ebc0a1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_progress.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_top.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_top.png
new file mode 100644
index 0000000..5fd6883
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_h_top.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_open.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_open.png
new file mode 100644
index 0000000..24240d0
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_open.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_bg.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_bg.png
new file mode 100644
index 0000000..ba5c502
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_bg.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_progress.png b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_progress.png
new file mode 100644
index 0000000..217760a
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/ic_wd_curtain_roll_progress.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/selector_pickerview_btn.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/selector_pickerview_btn.xml
new file mode 100644
index 0000000..9ebc219
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/drawable/selector_pickerview_btn.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:color="@color/pickerview_timebtn_pre" />
+ <item android:color="@color/pickerview_timebtn_nor" />
+</selector>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_gallery_banner_view_layout.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_gallery_banner_view_layout.xml
new file mode 100644
index 0000000..47af978
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_gallery_banner_view_layout.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/hdl_gallery_rootView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false">
+
+ <!--viewpager-->
+ <android.support.v4.view.ViewPager
+ android:id="@+id/hdl_gallery_viewPager"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:layout_marginLeft="60dp"
+ android:layout_marginRight="60dp"/>
+
+</RelativeLayout>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_crop_image.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_crop_image.xml
new file mode 100644
index 0000000..ab25fb1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_crop_image.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#00000000"
+ tools:context="com.hdl.widget.cropimage.HDLCropImageActivity">
+
+</RelativeLayout>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_geofence_round.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_geofence_round.xml
new file mode 100644
index 0000000..ef06d16
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_activity_geofence_round.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
+ <!--<include layout="@layout/plugin_geofence_option"/>-->
+ <!--<include layout="@layout/plugin_geofence_map"/>-->
+
+
+ <LinearLayout
+ android:id="@+id/gd_rl_topview"
+ android:layout_width="match_parent"
+ android:layout_height="54dp"
+ android:background="@color/gd_top_view">
+
+
+ <RelativeLayout
+ android:id="@+id/gd_btn_back"
+ android:layout_width="44dp"
+ android:layout_height="54dp"
+ >
+
+ <ImageView
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/ic_gdmap_back"/>
+ </RelativeLayout>
+
+ <TextView
+ android:id="@+id/gd_tv_activity_title"
+ android:layout_width="match_parent"
+ android:layout_height="54dp"
+ android:text="@string/gd_activity_title"
+ android:gravity="center|left"
+ android:textColor="@android:color/black"
+ android:textSize="16dp"
+ />
+
+ </LinearLayout>
+
+ <com.amap.api.maps.MapView
+ android:id="@+id/gd_mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@+id/gd_rl_topview">
+ </com.amap.api.maps.MapView>
+
+
+
+ <LinearLayout
+ android:id="@+id/gd_ll_search"
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:layout_below="@+id/gd_rl_topview"
+ android:layout_marginTop="10dp"
+ android:layout_marginLeft="20dp"
+ android:layout_marginRight="80dp"
+ android:background="@drawable/gd_click_effect_select"
+ android:clickable="true"
+ android:visibility="gone"
+ >
+
+ <ImageView
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_gdmap_search"
+ android:layout_marginLeft="10dp"/>
+
+ <TextView
+ android:id="@+id/gd_tv_search_title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textSize="14sp"
+ android:layout_marginLeft="10dp"
+ android:layout_gravity="center"
+ android:text="@string/gd_search_tip"/>
+
+ <ImageView
+ android:id="@+id/gd_img_search_delete"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_gdmap_delete"
+ android:layout_marginLeft="10dp"/>
+
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/gd_tv_radius"
+ android:layout_width="56dp"
+ android:layout_height="40dp"
+ android:layout_below="@+id/gd_rl_topview"
+ android:layout_marginTop="12dp"
+ android:background="@drawable/gd_click_effect_select"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="20dp"
+ android:text="500M"
+ android:gravity="center"
+ android:textColor="@android:color/black"
+ />
+
+
+ <LinearLayout
+ android:id="@+id/gd_ll_myhome"
+ android:layout_width="40dp"
+ android:layout_height="50dp"
+ android:background="@drawable/gd_click_effect_select"
+ android:layout_below="@+id/gd_ll_search"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="12dp"
+ android:orientation="vertical">
+
+ <ImageView
+ android:layout_width="25dp"
+ android:layout_height="23dp"
+ android:layout_gravity="center"
+ android:layout_marginTop="4dp"
+ android:src="@drawable/ic_gdmap_home" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_marginTop="2dp"
+ android:text="@string/gd_myhome"
+ android:textSize="11sp"
+ android:textColor="@android:color/black"
+ android:gravity="center"/>
+
+ </LinearLayout>
+
+
+
+
+
+ <TextView
+ android:id="@+id/gd_btn_save"
+ android:layout_width="match_parent"
+ android:layout_height="44dp"
+ android:layout_marginLeft="30dp"
+ android:layout_marginRight="30dp"
+ android:layout_marginBottom="48dp"
+ android:orientation="vertical"
+ android:layout_alignParentBottom="true"
+ android:textColor="#FFFFFF"
+ android:gravity="center"
+ android:background="@drawable/gd_btn_shape_app_b"
+ android:text="@string/gd_save"
+ />
+
+
+ <RelativeLayout
+ android:id="@+id/gd_btn_myLocation"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginLeft="20dp"
+ android:layout_marginBottom="20dp"
+ android:background="@drawable/gd_click_effect_select"
+ android:layout_above="@+id/gd_btn_save"
+ >
+
+ <ImageView
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/ic_gdmap_mylocation"/>
+ </RelativeLayout>
+
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_air_button.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_air_button.xml
new file mode 100644
index 0000000..af5edcc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_air_button.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp">
+
+ <!--<com.hdl.widget.HDLArcScaleSeekBar-->
+ <!--android:id="@+id/mHDLArcScaleSeekBar"-->
+ <!--android:layout_width="400dp"-->
+ <!--android:layout_height="400dp"-->
+ <!--android:layout_marginTop="20dp"-->
+ <!--android:layout_gravity="center"-->
+ <!--/>-->
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_centerInParent="true"
+ android:padding="30dp"
+ >
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="鍒剁儹"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:src="@drawable/ic_gdmap_zoom_out"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:text="30"/>
+
+ <ImageView
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:src="@drawable/ic_gdmap_add"/>
+
+
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="鈩�"/>
+
+ </LinearLayout>
+
+</LinearLayout>
+
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_include_pickerview_topbar.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_include_pickerview_topbar.xml
new file mode 100644
index 0000000..ccb4083
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_include_pickerview_topbar.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/rv_topbar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/white">
+
+ <Button
+ android:id="@+id/btnCancel"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="@android:color/white"
+ android:gravity="left|center_vertical"
+ android:paddingLeft="@dimen/pickerview_topbar_padding"
+ android:text="@string/pickerview_cancel"
+ android:textColor="@color/pickerview_wheelview_textcolor_out"
+ style="?android:attr/borderlessButtonStyle"
+ android:textSize="@dimen/pickerview_topbar_btn_textsize"
+ />
+
+ <TextView
+ android:id="@+id/tvTitle"
+ android:layout_width="match_parent"
+ android:gravity="center"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:background="@android:color/white"
+ android:layout_toLeftOf="@+id/btnSubmit"
+ android:layout_toRightOf="@+id/btnCancel"
+ android:textColor="@color/pickerview_topbar_title"
+
+ android:textSize="@dimen/pickerview_topbar_title_textsize" />
+
+ <Button
+ android:id="@id/btnSubmit"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:background="@android:color/white"
+ android:gravity="right|center_vertical"
+ android:paddingRight="@dimen/pickerview_topbar_padding"
+ android:text="@string/pickerview_submit"
+ style="?android:attr/borderlessButtonStyle"
+ android:textColor="@drawable/selector_pickerview_btn"
+ android:textSize="@dimen/pickerview_topbar_btn_textsize" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_alignParentBottom="true"
+ android:layout_height="1dp"
+ android:background="@color/pickerview_bg_topbar">
+
+
+ </LinearLayout>
+</RelativeLayout>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_layout_basepickerview.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_layout_basepickerview.xml
new file mode 100644
index 0000000..adbae30
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_layout_basepickerview.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+ android:id="@+id/outmost_container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:background="@color/pickerview_bgColor_overlay">
+
+ <FrameLayout
+ android:id="@+id/content_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ </FrameLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview.xml
new file mode 100644
index 0000000..fff1846
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/hdl_pickerview_ll"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/white"
+ android:orientation="horizontal">
+
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/hdl_options1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/hdl_options2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/hdl_options3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_options.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_options.xml
new file mode 100644
index 0000000..9b078ef
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_options.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include
+ layout="@layout/hdl_widget_include_pickerview_topbar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/pickerview_topbar_height" />
+
+ <LinearLayout
+ android:id="@+id/optionspicker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/white"
+ android:orientation="horizontal">
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/options1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/options2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/options3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_time.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_time.xml
new file mode 100644
index 0000000..6c4e32c
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/layout/hdl_widget_pickerview_time.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include
+ layout="@layout/hdl_widget_include_pickerview_topbar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/pickerview_topbar_height" />
+
+ <LinearLayout
+ android:id="@+id/timepicker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/white"
+ android:orientation="horizontal">
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/year"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.96" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+
+ android:id="@+id/month"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/day"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/hour"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/min"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <com.hdl.widget.pickerview.contrarywind.view.WheelView
+ android:id="@+id/second"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values-zh/strings.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values-zh/strings.xml
new file mode 100644
index 0000000..d2dfe2b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values-zh/strings.xml
@@ -0,0 +1,26 @@
+<resources>
+ <string name="app_name">HDLWidgetXMKit</string>
+
+ <string name="gd_notifyTitle">鎻愮ず</string>
+ <string name="gd_notifyMsg">褰撳墠搴旂敤缂哄皯蹇呰鏉冮檺銆俓n\n璇风偣鍑籠"璁剧疆\"-\"鏉冮檺\"-鎵撳紑鎵�闇�鏉冮檺銆�</string>
+ <string name="gd_setting">璁剧疆</string>
+ <string name="gd_cancel">鍙栨秷</string>
+ <string name="gd_save">淇濆瓨</string>
+ <string name="gd_activity_title">閫夋嫨绂诲紑鍦扮偣</string>
+ <string name="gd_search_tip">鏌ユ壘鍦扮偣</string>
+ <string name="gd_myhome">鎴戝</string>
+ <string name="gd_select_distance">閫夋嫨璺濈</string>
+
+ <string name="pickerview_cancel">鍙栨秷</string>
+ <string name="pickerview_submit">纭畾</string>
+ <string name="pickerview_year">骞�</string>
+ <string name="pickerview_month">鏈�</string>
+ <string name="pickerview_day">鏃�</string>
+ <string name="pickerview_hours">鏃�</string>
+ <string name="pickerview_minutes">鍒�</string>
+ <string name="pickerview_seconds">绉�</string>
+
+ <!--<string name="qrc_title">鎵竴鎵�</string>-->
+ <!--<string name="msg_camera_framework_bug">Sorry, the Android camera encountered a problem. You may need to restart the device.</string>-->
+
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/attrs.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..12982b9
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/attrs.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <declare-styleable name="HDLArcSeekBar">
+ <attr name="arc_width" format="dimension|reference" />
+ <attr name="arc_open_angle" format="float" />
+ <attr name="arc_rotate_angle" format="float" />
+ <attr name="arc_colors" format="reference" />
+ <attr name="arc_border_width" format="dimension|reference" />
+ <attr name="arc_border_color" format="color|reference" />
+ <attr name="arc_max" format="integer|reference" />
+ <attr name="arc_min" format="integer|reference" />
+ <attr name="arc_progress" format="integer|reference" />
+ <attr name="arc_thumb_width" format="dimension|reference" />
+ <attr name="arc_thumb_color" format="color|reference" />
+ <attr name="arc_thumb_radius" format="dimension|reference" />
+ <attr name="arc_thumb_shadow_radius" format="dimension|reference" />
+ <attr name="arc_thumb_shadow_color" format="color|reference" />
+ <attr name="hdl_arc_thumb_mode" format="integer|dimension">
+ <enum name="STROKE" value="0" />
+ <enum name="FILL" value="1" />
+ <enum name="FILL_STROKE" value="2" />
+ </attr>
+ <attr name="arc_shadow_radius" format="dimension|reference" />
+ <attr name="arc_progress_bar_color" format="color|reference" />
+ <attr name="arc_progress_bar_text_unit" format="string|reference" />
+
+ </declare-styleable>
+
+
+ <declare-styleable name="HDLWaveSeekBar">
+ <attr name="wave_color" format="color"></attr>
+ <attr name="second_wave_color" format="color"></attr>
+ <attr name="wave_bg_color" format="color"></attr>
+ <attr name="wave_border_color" format="color"></attr>
+
+ <attr name="wave_width" format="dimension"></attr>
+ <attr name="wave_height" format="dimension"></attr>
+
+
+ </declare-styleable>
+
+ <declare-styleable name="HDLCurtainSeekBar">
+ <attr name="curtain_bar_color" format="color"></attr>
+ <attr name="second_curtain_bar_color" format="color"></attr>
+ <attr name="curtain_bar_bg_color" format="color"></attr>
+ <attr name="curtain_bar_border_color" format="color"></attr>
+
+ <attr name="curtain_bar_width" format="dimension"></attr>
+ <attr name="curtain_bar_height" format="dimension"></attr>
+
+
+ </declare-styleable>
+
+
+
+ <declare-styleable name="pickerview">
+ <attr name="wheelview_gravity">
+ <enum name="center" value="17"/>
+ <enum name="left" value="3"/>
+ <enum name="right" value="5"/>
+ </attr>
+ <attr name="wheelview_textSize" format="dimension"/>
+ <attr name="wheelview_textColorOut" format="color"/>
+ <attr name="wheelview_textColorCenter" format="color"/>
+ <attr name="wheelview_dividerColor" format="color"/>
+ <attr name="wheelview_lineSpacingMultiplier" format="float"/>
+ </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/colors.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/colors.xml
new file mode 100644
index 0000000..d47bccb
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/colors.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <array name="arc_colors_default">
+ <item>#484849</item>
+ <item>#484849</item>
+ <item>#484849</item>
+ </array>
+
+
+ <color name="pickerview_timebtn_nor">#FF5722</color>
+ <color name="pickerview_timebtn_pre">#c2daf5</color>
+ <color name="pickerview_bg_topbar">#f5f5f5</color>
+
+ <color name="pickerview_topbar_title">#000000</color>
+ <color name="pickerview_wheelview_textcolor_out">#a8a8a8</color>
+ <color name="pickerview_wheelview_textcolor_center">#2a2a2a</color>
+ <color name="pickerview_wheelview_textcolor_divider">#d5d5d5</color>
+ <color name="pickerview_bgColor_overlay">#60000000</color>
+ <color name="pickerview_bgColor_default">#FFFFFFFF</color>
+
+ <color name="gd_top_view">#FFF9F9F9</color>
+
+
+</resources>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/dimens.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..0577f5b
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/dimens.xml
@@ -0,0 +1,15 @@
+<resources>
+ <!-- 椤堕儴鎸夐挳鏍忛珮搴� -->
+ <dimen name="pickerview_topbar_height">44dp</dimen>
+
+ <!-- 椤堕儴鎸夐挳padding -->
+ <dimen name="pickerview_topbar_padding">20dp</dimen>
+
+ <!-- 椤堕儴鎸夐挳鏂囧瓧澶у皬 -->
+ <dimen name="pickerview_topbar_btn_textsize">17sp</dimen>
+ <dimen name="pickerview_topbar_title_textsize">18sp</dimen>
+ <!-- 閫夐」鏂囧瓧澶у皬 -->
+ <dimen name="pickerview_textsize">20sp</dimen>
+
+
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/integers.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/integers.xml
new file mode 100644
index 0000000..7e9e0a5
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/integers.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <integer name="animation_default_duration">300</integer>
+</resources>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/strings.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6f74e4d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/strings.xml
@@ -0,0 +1,26 @@
+<resources>
+ <string name="app_name">HDLWidgetXMKit</string>
+
+ <string name="gd_notifyTitle">Tip</string>
+ <string name="gd_notifyMsg">The current application lacks the necessary permissions.\n\nPlease click\"Setting\"-\"Permission\"-Open the required permissions.</string>
+ <string name="gd_setting">Setting</string>
+ <string name="gd_cancel">Cancel</string>
+ <string name="gd_save">Save</string>
+ <string name="gd_activity_title">Select a place to leave</string>
+ <string name="gd_search_tip">Search for a place</string>
+ <string name="gd_myhome">Home</string>
+ <string name="gd_select_distance">Select Distance</string>
+
+
+ <string name="pickerview_cancel">Cancel</string>
+ <string name="pickerview_submit">Confirm</string>
+ <string name="pickerview_year">Year</string>
+ <string name="pickerview_month">Month</string>
+ <string name="pickerview_day">Day</string>
+ <string name="pickerview_hours">H</string>
+ <string name="pickerview_minutes">M</string>
+ <string name="pickerview_seconds">S</string>
+
+ <!--<string name="qrc_title">Scan</string>-->
+ <!--<string name="msg_camera_framework_bug">Sorry, the Android camera encountered a problem. You may need to restart the device.</string>-->
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/styles.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/styles.xml
new file mode 100644
index 0000000..ff2cc10
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/values/styles.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="custom_dialog2" parent="@android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <!-- Dialog鐨剋indowFrame妗嗕负鏃� -->
+ <item name="android:windowIsFloating">true</item>
+ <!-- 鏄惁婕傜幇鍦╝ctivity涓� -->
+ <item name="android:windowIsTranslucent">true</item>
+ <!-- 鏄惁鍗婇�忔槑 -->
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:background">@null</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <!-- 鍘婚櫎榛戣壊杈规鐨勫叧閿缃」 -->
+ <item name="android:backgroundDimEnabled">true</item>
+ <!-- 灞忓箷鑳屾櫙鏄惁鍙樻殫 -->
+ <item name="android:backgroundDimAmount">0.3</item>
+ </style>
+
+ <style name="picker_view_scale_anim" mce_bogus="1" parent="android:Animation">
+ <item name="android:windowEnterAnimation">@anim/pickerview_dialog_scale_in</item>
+ <item name="android:windowExitAnimation">@anim/pickerview_dialog_scale_out</item>
+ </style>
+
+
+ <style name="picker_view_slide_anim" mce_bogus="1" parent="android:Animation">
+ <item name="android:windowEnterAnimation">@anim/pickerview_slide_in_bottom</item>
+ <item name="android:windowExitAnimation">@anim/pickerview_slide_out_bottom</item>
+ </style>
+
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/xml/hdl_filepaths.xml b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/xml/hdl_filepaths.xml
new file mode 100644
index 0000000..2feeb8e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/HDLWidgetXM/src/main/res/xml/hdl_filepaths.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths>
+ <external-path path="." name="image" />
+</paths>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/README.md b/HDL_Widget_XM/HDLWidget_Android/README.md
new file mode 100644
index 0000000..a0d023e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/README.md
@@ -0,0 +1,11 @@
+## HDLWidgetXM(鑷畾涔夋帶浠跺簱)
+
+### *****V1.0.3*****
+### 1.HDLArcSeekbar(鍦嗗姬鎷栧姩鏉�)
+### 2.HDLWaveSeekBar(娉㈡氮鏁堟灉鎷栧姩鏉�)
+### 3.HDLPickerView
+### 4.GDMapKit 楂樺痉鍦板浘
+### 5.HDLCoverFlowViewPager
+### 6.閲嶅惎APP 鏂规硶鎺ュ彛
+
+
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/.gitignore b/HDL_Widget_XM/HDLWidget_Android/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/build.gradle b/HDL_Widget_XM/HDLWidget_Android/app/build.gradle
new file mode 100644
index 0000000..157f5a0
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ applicationId "com.hdl.widget"
+ minSdkVersion 14
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+// repositories {
+// flatDir {
+// dirs '../HDLWidgetXM/libs', 'libs'
+// }
+// }
+}
+
+dependencies {
+// implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation project(':HDLWidgetXM')
+// implementation project(':GDMapKit')
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/libs/HDLWidgetXM-release.aar b/HDL_Widget_XM/HDLWidget_Android/app/libs/HDLWidgetXM-release.aar
new file mode 100644
index 0000000..5c4e657
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/libs/HDLWidgetXM-release.aar
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/proguard-rules.pro b/HDL_Widget_XM/HDLWidget_Android/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/AndroidManifest.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..16ce1be
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.hdl.widget">
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name=".DiyImageSeekBarActivity"></activity>
+ <activity android:name=".CoverFlowViewActivity" />
+ <activity android:name=".ArcScaleSeekBarActivity" />
+ <activity android:name=".GestureLockActivity" />
+ <activity android:name=".MainActivity" />
+ <activity android:name=".CurtainSeekBarActivity" />
+ <activity android:name=".QRCodeActivity" />
+ <activity android:name=".PickerViewActivity" />
+ <activity android:name=".WaveSeekBarActivity" />
+ <activity android:name=".HDLWIdgetListActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <meta-data
+ android:name="com.amap.api.v2.apikey"
+ android:value="eac56f8589d66ad20b3c90a737ffd5e7" />
+
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.hdl.widget.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/hdl_filepaths" />
+ </provider>
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/ArcScaleSeekBarActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/ArcScaleSeekBarActivity.java
new file mode 100644
index 0000000..765ff40
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/ArcScaleSeekBarActivity.java
@@ -0,0 +1,73 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+public class ArcScaleSeekBarActivity extends Activity {
+ private TextView mProgressText;
+ private HDLArcScaleSeekBar mHDLArcScaleSeekBar;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_arc_scale_seek_bar);
+
+
+ mProgressText = findViewById(R.id.txt_progress);
+
+ mHDLArcScaleSeekBar = findViewById(R.id.mHDLArcScaleSeekBar);
+
+ mHDLArcScaleSeekBar.setMaxValue(32);
+ mHDLArcScaleSeekBar.setMinValue(18);
+ mHDLArcScaleSeekBar.setProgressBarUnitSring("鈩�");
+// mHDLArcScaleSeekBar.setProgressTextShow(false);
+ mHDLArcScaleSeekBar.setProgress(26);
+ mHDLArcScaleSeekBar.setOnProgressChangeListener(new HDLArcScaleSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLArcScaleSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(HDLArcScaleSeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(HDLArcScaleSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ }
+ });
+
+
+
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLArcScaleSeekBar.setProgress(18);
+ mHDLArcScaleSeekBar.setOffline(true);
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLArcScaleSeekBar.setProgress(30);
+ mHDLArcScaleSeekBar.setOffline(false);
+
+ }
+ });
+ }
+
+
+ private void setEngry(int progress) {
+ mProgressText.setText( progress + "%");
+
+ }
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CoverFlowViewActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CoverFlowViewActivity.java
new file mode 100644
index 0000000..1c1385e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CoverFlowViewActivity.java
@@ -0,0 +1,84 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.hdl.widget.CoverFlowViewPager.HDLCoverFlowViewPager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CoverFlowViewActivity extends Activity {
+
+ private HDLCoverFlowViewPager mHDLGalleryViewPager;
+ private List<View> mViewList;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_cover_flow_view);
+
+ initHDLBannerViewPager();
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLGalleryViewPager.setCurrentItem(7);
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mViewList.size() == 0) return;
+
+ mViewList.remove(0);
+ mHDLGalleryViewPager.updateViewsList(mViewList);
+
+ }
+ });
+
+ }
+
+ private void initHDLBannerViewPager() {
+ mViewList = new ArrayList<>();
+ for (int i = 0; i < 15; i++) {
+ LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 100);
+ TextView mTextView = new TextView(this);
+ mTextView.setTextSize(18);
+ mTextView.setText("TextView " + i);
+ mTextView.setBackgroundColor(HDLUtlis.getColor(this, R.color.colorPrimary));
+ mTextView.setLayoutParams(mLayoutParams);
+ mViewList.add(mTextView);
+
+ }
+
+ mHDLGalleryViewPager = findViewById(R.id.hdl_galleryViewPager);
+ mHDLGalleryViewPager.initBanner(mViewList, true, 5f)//寮�鍚�3D鐢诲粖鏁堟灉
+ .addPageMargin(0, 80)//鍙傛暟1page涔嬮棿鐨勯棿璺�,鍙傛暟2涓棿item璺濈杈圭晫鐨勯棿璺�
+ .finishConfig()//杩欏彞蹇呴』鍔�
+ .addGalleryListener(new HDLCoverFlowViewPager.OnClickGalleryListener() {
+ @Override
+ public void onGalleryClick(int position) {
+ //鐐瑰嚮item
+ showToast("鏁堟灉1鐐瑰嚮" + position);
+ }
+
+ @Override
+ public void onGalleryPositionChange(int position) {
+ Log.i("HDLCoverFlowViewPager", "--------------onGalleryPositionChange锛�" + position);
+ }
+ });
+ }
+
+
+ public void showToast(String text) {
+ Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CurtainSeekBarActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CurtainSeekBarActivity.java
new file mode 100644
index 0000000..25659a5
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/CurtainSeekBarActivity.java
@@ -0,0 +1,92 @@
+package com.hdl.widget;
+
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+public class CurtainSeekBarActivity extends AppCompatActivity {
+
+ private TextView mProgressText;
+ private HDLRollCurtainSeekBar mHDLRollCurtainSeekBar;
+ private HDLOACCurtainSeekBar mHDLOACCurtainSeekBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_curtain_seek_bar);
+
+ mProgressText = findViewById(R.id.txt_progress);
+
+ mHDLRollCurtainSeekBar = findViewById(R.id.mHDLRollCurtainSeekBar);
+
+ mHDLOACCurtainSeekBar = findViewById(R.id.mHDLOACCurtainSeekBar);
+// mHDLRollCurtainSeekBar.setCurtainPadding(30);
+// mHDLWaveSeekBar.setMaxValue(35);
+// mHDLWaveSeekBar.setMinValue(16);
+// mHDLWaveSeekBar.setProgressBarUnitSring("鈩�");
+
+ mHDLRollCurtainSeekBar.setOnProgressChangeListener(new HDLRollCurtainSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLRollCurtainSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(HDLRollCurtainSeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(HDLRollCurtainSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ }
+ });
+
+
+
+ mHDLOACCurtainSeekBar.setOnProgressChangeListener(new HDLOACCurtainSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLOACCurtainSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(HDLOACCurtainSeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(HDLOACCurtainSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ }
+ });
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLRollCurtainSeekBar.setProgress(20);
+ mHDLOACCurtainSeekBar.setProgress(20);
+ mHDLOACCurtainSeekBar.setOffline(true);
+ mHDLRollCurtainSeekBar.setOffline(true);
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLRollCurtainSeekBar.setProgress(90);
+ mHDLOACCurtainSeekBar.setProgress(90);
+ mHDLOACCurtainSeekBar.setOffline(false);
+ mHDLRollCurtainSeekBar.setOffline(false);
+ }
+ });
+ }
+
+
+ private void setEngry(int progress) {
+ mProgressText.setText(progress + "%");
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/DiyImageSeekBarActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/DiyImageSeekBarActivity.java
new file mode 100644
index 0000000..61060de
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/DiyImageSeekBarActivity.java
@@ -0,0 +1,90 @@
+package com.hdl.widget;
+
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+public class DiyImageSeekBarActivity extends AppCompatActivity {
+ private TextView mProgressText;
+
+ private HDLDiyImageSeekBar mHDLDiyImageHorizontalSeekBar;
+ private HDLDiyImageVerticalSeekBar mHDLDiyImageVerticalSeekBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_diy_image_horizontal_seek_bar);
+
+
+ mProgressText = findViewById(R.id.txt_progress);
+
+ mHDLDiyImageVerticalSeekBar = findViewById(R.id.mHDLDiyImageVerticalSeekBar);
+
+ mHDLDiyImageHorizontalSeekBar = findViewById(R.id.mHDLDiyImageHorizontalSeekBar);
+// mHDLDiyImageHorizontalSeekBar.setDiySeekBarViewHeight(120);
+ mHDLDiyImageHorizontalSeekBar.setProgressBarColor(Color.RED);
+ mHDLDiyImageHorizontalSeekBar.setBgBitmapButton(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
+// mHDLWaveSeekBar.setMaxValue(35);
+// mHDLWaveSeekBar.setMinValue(16);
+// mHDLWaveSeekBar.setProgressBarUnitSring("鈩�");
+
+ mHDLDiyImageHorizontalSeekBar.setOnProgressChangeListener(new HDLDiyImageSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLDiyImageSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(HDLDiyImageSeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(HDLDiyImageSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ }
+ });
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLDiyImageHorizontalSeekBar.setOffline(true);
+ mHDLDiyImageHorizontalSeekBar.setProgress(20);
+
+ mHDLDiyImageVerticalSeekBar.setOffline(true);
+ mHDLDiyImageVerticalSeekBar.setProgress(20);
+
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLDiyImageHorizontalSeekBar.setProgress(90);
+ mHDLDiyImageHorizontalSeekBar.setOffline(false);
+
+ mHDLDiyImageVerticalSeekBar.setProgress(90);
+ mHDLDiyImageVerticalSeekBar.setOffline(false);
+// startActivity(CurtainSeekBarActivity.class);
+ }
+ });
+ }
+
+
+ private void setEngry(int progress) {
+ mProgressText.setText( progress + "%");
+
+ }
+
+ public void startActivity(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+
+ startActivity(intent);
+// overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/GestureLockActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/GestureLockActivity.java
new file mode 100644
index 0000000..b4d75da
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/GestureLockActivity.java
@@ -0,0 +1,41 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.hdl.widget.gesturelock.GestureLockView;
+
+public class GestureLockActivity extends Activity {
+
+ private GestureLockView mGestureLockView;
+ private String password = "1235789";
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_gesture_lock);
+
+ mGestureLockView = findViewById(R.id.mGestureLockView);
+
+ mGestureLockView.setOnLockVerifyListener(new GestureLockView.OnLockVerifyListener() {
+ @Override
+ public void onGestureSelected(int id) {
+ Log.i("selectPassword","selectPassword id: " + id);
+ }
+
+ @Override
+ public void onGestureFinished(String selectPassword, int selectCount) {
+ Log.i("selectPassword","selectPassword: " + selectPassword + " selectCount:"+selectCount);
+
+ if(selectPassword.equals(password)){
+ mGestureLockView.setLockViewMatchedState(true);
+ }else {
+ mGestureLockView.setLockViewMatchedState(false);
+ }
+ }
+
+
+ });
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLUtlis.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLUtlis.java
new file mode 100644
index 0000000..67036fb
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLUtlis.java
@@ -0,0 +1,51 @@
+package com.hdl.widget;
+
+import android.content.Context;
+import android.os.Build;
+
+import java.math.BigDecimal;
+
+/**
+ * Created by JLChen on 2019/7/4
+ */
+public class HDLUtlis {
+
+ /**
+ * 灏唎bject杞负Integer绫诲瀷
+ * @param object
+ * @return
+ */
+ public static Integer getIntegerByObject(Object object){
+ Integer in = null;
+ if(object!=null){
+ if(object instanceof Integer){
+ in = (Integer)object;
+ }else if(object instanceof String){
+ in = Integer.parseInt((String)object);
+ }else if(object instanceof Double){
+ in = (int)((double)object);
+ }else if(object instanceof Float){
+ in = (int)((float)object);
+ }else if(object instanceof BigDecimal){
+ in = ((BigDecimal)object).intValue();
+ }else if(object instanceof Long){
+ in = ((Long)object).intValue();
+ }
+ }
+ return in;
+ }
+
+ /**
+ * getColor
+ * @param context
+ * @param color
+ * @return
+ */
+ public static int getColor(Context context, int color) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return context.getColor(color);
+ } else {
+ return context.getResources().getColor(color);
+ }
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLWIdgetListActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLWIdgetListActivity.java
new file mode 100644
index 0000000..eed44f7
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/HDLWIdgetListActivity.java
@@ -0,0 +1,110 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.hdl.widget.gdmapkit.GDConst;
+import com.hdl.widget.gdmapkit.GDGeoFenceRoundActivity;
+import com.hdl.widget.gdmapkit.OnGeofenceCallback;
+
+import java.util.ArrayList;
+
+public class HDLWIdgetListActivity extends Activity implements AdapterView.OnItemClickListener {
+
+ private ListView mListView;
+
+ private ArrayList<String> dataList = new ArrayList();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_hdlwidget_list);
+
+ mListView = findViewById(R.id.listview);
+
+
+ dataList.add("MainActivity");
+ dataList.add("PickerView");
+ dataList.add("CoverFlowView");
+ dataList.add("WaveSeekBarActivity");
+ dataList.add("CorpImageActivity");
+ dataList.add("CurtainSeekBarActivity");
+ dataList.add("GestureLockActivity");
+ dataList.add("HDLArcScaleSeekBar");
+ dataList.add("GDGeoFenceRoundActivity");
+ dataList.add("DiyImageSeekBarActivity");
+
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, dataList);//鏂板缓骞堕厤缃瓵rrayAapeter
+ mListView.setAdapter(adapter);
+ mListView.setOnItemClickListener(this);
+
+
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if(position == 0){
+
+ startActivity(MainActivity.class);
+ }else if(position == 1){
+ startActivity(PickerViewActivity.class);
+ }else if(position == 2){
+ startActivity(CoverFlowViewActivity.class);
+ }else if(position == 3){
+ startActivity(WaveSeekBarActivity.class);
+ }else if(position == 4){
+ startActivity(QRCodeActivity.class);
+ }else if(position == 5){
+ startActivity(CurtainSeekBarActivity.class);
+ }else if(position == 6){
+ startActivity(GestureLockActivity.class);
+ }else if(position == 7){
+ startActivity(ArcScaleSeekBarActivity.class);
+ }else if(position == 8){
+ gotoGDGeoFenceRoundActivity();
+ }else if(position == 9){
+ startActivity(DiyImageSeekBarActivity.class);
+ }
+
+
+
+
+ }
+
+ private double jj,ww;
+ private float fenceRadius;
+ private void gotoGDGeoFenceRoundActivity(){
+
+ if(ww != 0) {
+ GDConst.bMyHomeSet = true;
+ GDConst.myHomeLatitude = ww;
+ GDConst.myHomeLongitude = jj;
+ GDConst.myHomeRadiusRange = fenceRadius;
+ }
+
+ startActivity(GDGeoFenceRoundActivity.class);
+ GDGeoFenceRoundActivity.mOnGeofenceCallback = new OnGeofenceCallback() {
+ @Override
+ public void OnSaveCallback(double mLatitude, double mLongitude, float mFenceRadius, String mAddress) {
+ Log.i("OnSaveCallback","mLatitude:"+ mLatitude + "-" + mLongitude + "-" + mFenceRadius + "-" + mAddress);
+ ww=mLatitude;
+ jj=mLongitude;
+ fenceRadius = mFenceRadius;
+ }
+ };
+ }
+
+ public void startActivity(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+ startActivity(intent);
+
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/MainActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/MainActivity.java
new file mode 100644
index 0000000..aca24dc
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/MainActivity.java
@@ -0,0 +1,247 @@
+package com.hdl.widget;
+
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+//import com.hdl.widget.GalleryViewPager.HDLGalleryViewPager;
+
+
+import com.hdl.widget.CoverFlowViewPager.HDLCoverFlowViewPager;
+import com.hdl.widget.cropimage.HDLCropImageActivity;
+import com.hdl.widget.gdmapkit.GDConst;
+import com.hdl.widget.gdmapkit.GDGeoFenceRoundActivity;
+import com.hdl.widget.gdmapkit.OnGeofenceCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends AppCompatActivity {
+ private TextView mProgressText;
+ private HDLArcSeekBar mHDLArcSeekBar;
+ private HDLArcSeekBar mHDLArcSeekBar_2;
+ private HDLCoverFlowViewPager mHDLGalleryViewPager;
+ private List<View> mViewList;
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mProgressText = findViewById(R.id.txt_progress);
+ mHDLArcSeekBar_2 = findViewById(R.id.arc_seek_bar_2);
+ mHDLArcSeekBar_2.setIsClickable(false);
+
+ mHDLArcSeekBar = findViewById(R.id.arc_seek_bar);
+// mHDLArcSeekBar.setArcColors(R.array.arc_colors_custom);
+ mHDLArcSeekBar.setMaxValue(35);
+ mHDLArcSeekBar.setMinValue(16);
+// mHDLArcSeekBar.setThumbMode(HDLArcSeekBar.THUMB_MODE_STROKE);
+// mHDLArcSeekBar.setArcWidthDefaultStyle(30);
+ mHDLArcSeekBar.setProgressBarUnitSring("鈩�");
+// mHDLArcSeekBar.setOpenAngle(120);
+// mHDLArcSeekBar.setTextDefaultDistance(40);
+// mHDLArcSeekBar.setTextPaintStyle(HDLUtlis.getColor(this, R.color.colorPrimary),18);
+// mHDLArcSeekBar.setProgressTextColor(HDLUtlis.getColor(this, R.color.black));
+// mHDLArcSeekBar.setProgressTextSize(28);
+// mHDLArcSeekBar.setThumbMode(HDLArcSeekBar.THUMB_MODE_FILL);
+ mHDLArcSeekBar.setThumbColor(HDLUtlis.getColor(this, R.color.white));
+ mHDLArcSeekBar.setThumbRadius(10);
+ mHDLArcSeekBar.setTextDefaultDistance(30);
+ int[] colors = new int[]{
+ HDLUtlis.getColor(this, R.color.arc_bar_start),
+ HDLUtlis.getColor(this, R.color.arc_bar_end),
+// HDLUtlis.getColor(this, R.color.white)
+ };
+ mHDLArcSeekBar.setProgressBarColors(colors);
+ setEngry(mHDLArcSeekBar.getProgress());
+ mHDLArcSeekBar.setOnProgressChangeListener(new HDLArcSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLArcSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(seekBar.getProgress());
+ }
+ @Override
+ public void onStartTrackingTouch(HDLArcSeekBar seekBar) {
+ Log.i("KKonStopTrackingTouch","鎵嬫寚鎸変笅");
+ }
+ @Override
+ public void onStopTrackingTouch(HDLArcSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ Log.i("KKonStopTrackingTouch","鍋滄");
+ }
+ });
+
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLArcSeekBar_2.setProgress(20);
+ updateV1();
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLArcSeekBar_2.setProgress(90);
+ updateV2();
+
+ }
+ });
+
+ findViewById(R.id.btn_go).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(WaveSeekBarActivity.class);
+
+ }
+ });
+
+ findViewById(R.id.btn_go_2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ if(ww != 0) {
+ GDConst.bMyHomeSet = true;
+ GDConst.myHomeLatitude = ww;
+ GDConst.myHomeLongitude = jj;
+ GDConst.myHomeRadiusRange = fenceRadius;
+ }
+
+ startActivity(GDGeoFenceRoundActivity.class);
+ GDGeoFenceRoundActivity.mOnGeofenceCallback = new OnGeofenceCallback() {
+ @Override
+ public void OnSaveCallback(double mLatitude, double mLongitude, float mFenceRadius, String mAddress) {
+ Log.i("OnSaveCallback","mLatitude:"+ mLatitude + "-" + mLongitude + "-" + mFenceRadius + "-" + mAddress);
+ ww=mLatitude;
+ jj=mLongitude;
+ fenceRadius = mFenceRadius;
+ }
+ };
+ }
+ });
+
+ findViewById(R.id.btn_go_3).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+// startActivity(HDLCropImageActivity.class);
+ startActivity(QRCodeActivity.class);
+// Intent intent = new Intent(this, HDLCropImageActivity.class);
+// startActivity(intent);
+
+ }
+ });
+
+ initHDLBannerViewPager();
+
+ }
+
+
+ private double jj,ww;
+
+ private float fenceRadius;
+
+
+ private void setEngry(int progress) {
+ mProgressText.setText( progress + "鈩�");
+ }
+
+
+
+
+ private void initHDLBannerViewPager(){
+ mViewList = new ArrayList<>();
+ for (int i = 0;i<15;i++){
+ LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,100);
+
+
+ TextView mTextView = new TextView(this);
+ mTextView.setTextSize(18);
+ mTextView.setText("TextView " + i);
+ mTextView.setBackgroundColor(HDLUtlis.getColor(this,R.color.colorPrimary));
+ mTextView.setLayoutParams(mLayoutParams);
+ mViewList.add(mTextView);
+
+ }
+ mHDLGalleryViewPager = findViewById(R.id.hdl_galleryViewPager);
+
+ mHDLGalleryViewPager.initBanner(mViewList, true,15f )//寮�鍚�3D鐢诲粖鏁堟灉
+ .addPageMargin(0, 80)//鍙傛暟1page涔嬮棿鐨勯棿璺�,鍙傛暟2涓棿item璺濈杈圭晫鐨勯棿璺�
+// .addRoundCorners(12)//鍦嗚
+ .finishConfig()//杩欏彞蹇呴』鍔�
+// .addStartTimer(5)
+ .addGalleryListener(new HDLCoverFlowViewPager.OnClickGalleryListener() {
+ @Override
+ public void onGalleryClick(int position) {
+ //鐐瑰嚮item
+ showToast("鏁堟灉1鐐瑰嚮"+position);
+ Log.i("test","--------------00x1");
+ }
+
+ @Override
+ public void onGalleryPositionChange(int position) {
+ Log.i("test","--------------onGalleryPositionChange锛�"+position);
+ }
+ });
+
+
+ }
+
+ public void showToast(String text) {
+ Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
+ }
+
+ private void updateV1(){
+ mViewList.clear();
+ for (int i = 0;i<8;i++){
+ LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,100);
+
+
+ TextView mTextView = new TextView(this);
+ mTextView.setTextSize(28);
+ mTextView.setText("TextView RED" + i);
+ mTextView.setBackgroundColor(HDLUtlis.getColor(this,R.color.colorAccent));
+ mTextView.setLayoutParams(mLayoutParams);
+ mViewList.add(mTextView);
+ }
+ mHDLGalleryViewPager.updateViewsList(mViewList);
+ }
+
+ private void updateV2(){
+ mHDLGalleryViewPager.setCurrentItem(5);
+
+
+// mViewList.clear();
+// for (int i = 0;i<25;i++){
+// LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,100);
+//
+//
+// TextView mTextView = new TextView(this);
+// mTextView.setTextSize(25);
+// mTextView.setText("TextView Y" + i);
+// mTextView.setBackgroundColor(HDLUtlis.getColor(this,R.color.app_background));
+// mTextView.setLayoutParams(mLayoutParams);
+// mViewList.add(mTextView);
+// }
+// mHDLGalleryViewPager.updateViewsList(mViewList);
+ }
+
+
+ public void startActivity(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+//
+// intent.putExtra(HDLUtlisXM.CROP_TYPE_KEY,0xFF0001);
+// intent.putExtra(HDLUtlisXM.CROP_RATIO_X_KEY,2);
+// intent.putExtra(HDLUtlisXM.CROP_RATIO_Y_KEY,1);
+
+ startActivity(intent);
+// overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/PickerViewActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/PickerViewActivity.java
new file mode 100644
index 0000000..d1563ee
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/PickerViewActivity.java
@@ -0,0 +1,84 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import com.hdl.widget.pickerview.builder.OptionsPickerBuilder;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectChangeListener;
+import com.hdl.widget.pickerview.listener.OnOptionsSelectListener;
+import com.hdl.widget.pickerview.view.HDLPickerView;
+import com.hdl.widget.pickerview.view.OptionsPickerView;
+
+import java.util.ArrayList;
+
+public class PickerViewActivity extends Activity {
+ private ArrayList<String> options1Items = new ArrayList<>();
+ private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
+ private HDLPickerView mHDLPickerView;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_picker_view);
+
+
+ mHDLPickerView = findViewById(R.id.mHDLPickerView);
+ mHDLPickerView.setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {
+ @Override
+ public void onOptionsSelectChanged(int options1, int options2, int options3) {
+ Log.i("onOptionsSelectChanged","options1:"+options1+"-"+options2+"-"+options3);
+ }
+ });
+
+
+ //閫夐」1
+ options1Items.add("骞夸笢");
+ options1Items.add( "婀栧崡");
+ options1Items.add( "骞胯タ");
+
+ //閫夐」2
+ ArrayList<String> options2Items_01 = new ArrayList<>();
+ options2Items_01.add("骞垮窞");
+ options2Items_01.add("浣涘北");
+ options2Items_01.add("涓滆帪");
+ options2Items_01.add("鐝犳捣");
+ ArrayList<String> options2Items_02 = new ArrayList<>();
+ options2Items_02.add("闀挎矙");
+ options2Items_02.add("宀抽槼");
+ options2Items_02.add("鏍床");
+ options2Items_02.add("琛¢槼");
+ ArrayList<String> options2Items_03 = new ArrayList<>();
+ options2Items_03.add("妗傛灄");
+ options2Items_03.add("鐜夋灄");
+ options2Items.add(options2Items_01);
+ options2Items.add(options2Items_02);
+ options2Items.add(options2Items_03);
+
+ mHDLPickerView.setPicker(options1Items,options2Items,null);
+
+ findViewById(R.id.hdl_pickerview_btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showPickerView();
+
+ }
+ });
+ }
+ private void showPickerView(){
+ OptionsPickerView pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
+ @Override
+ public void onOptionsSelect(int options1, int option2, int options3 ,View v) {
+
+ }
+ }).build();
+ pvOptions.setPicker(options1Items);
+
+ pvOptions.show();
+
+ }
+
+
+
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/QRCodeActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/QRCodeActivity.java
new file mode 100644
index 0000000..1003512
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/QRCodeActivity.java
@@ -0,0 +1,146 @@
+package com.hdl.widget;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.hdl.widget.cropimage.HDLCropImageActivity;
+
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+public class QRCodeActivity extends Activity {
+
+ private ImageView mQRC_image;
+ private TextView mQRC_textView;
+ private static final String DECODED_CONTENT_KEY = "codedContent";
+ private static final String DECODED_BITMAP_KEY = "codedBitmap";
+ private static final int REQUEST_CODE_SCAN = 0x0000;
+
+ private DrawerLayout mDrawerLayout;
+ private ImageView mImageView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_qrcode);
+
+ mQRC_image = findViewById(R.id.mQRC_image);
+ mQRC_textView = findViewById(R.id.mQRC_textView);
+
+
+ findViewById(R.id.hdl_btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+// createQRCode();
+ }
+ });
+
+ findViewById(R.id.hdl_btn_1).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+// startActivity( QrcCaptureActivity.class);
+ }
+ });
+ findViewById(R.id.hdl_btn_2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity2( HDLCropImageActivity.class);
+ HDLUtlisXM.MAuthority_NAME = "com.hdl.widget.fileprovider";
+ HDLCropImageActivity.mOnCropImageeCallback = new HDLCropImageActivity.OnCropImageeCallback() {
+ @Override
+ public void OnSaveCallback(String picturePath) {
+
+ if(picturePath == null){
+ return ;
+ }
+ Bitmap bitmap = getLoacalBitmap(picturePath); //浠庢湰鍦板彇鍥剧墖(鍦╟dcard涓幏鍙�) //
+ mQRC_image.setImageBitmap(bitmap);
+ }
+ };
+ }
+ });
+
+
+ }
+ /**
+ * 鍔犺浇鏈湴鍥剧墖
+ * @param url
+ * @return
+ */
+ public static Bitmap getLoacalBitmap(String url) {
+ try {
+ FileInputStream fis = new FileInputStream(url);
+ return BitmapFactory.decodeStream(fis); ///鎶婃祦杞寲涓築itmap鍥剧墖
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private void startActivity(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+
+ startActivityForResult(intent, REQUEST_CODE_SCAN);
+// overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
+
+ }
+
+// private void createQRCode(){
+//
+// Bitmap bitmap = HDLUtlisXM.createQRCode("18888888888", 500);//涓嶉渶瑕乴ogo锛屼紶鍏ュ垎浜摼鎺ュ拰浜岀淮鐮佸浘鐗囧ぇ灏�
+////闇�瑕乴ogo锛屼紶鍏ュ垎浜摼鎺ワ紝浜岀淮鐮佸ぇ灏忎互鍙妉ogo鍥剧墖
+////Bitmap bitmap = QRCode.createQRCodeWithLogo(mShareUrl, 500, BitmapFactory.decodeResource(getResources(),R.drawable.logo_icon));
+//
+// mQRC_image.setImageBitmap(bitmap);
+//
+// }
+//
+//
+// @Override
+//
+//
+//
+//
+// protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+// super.onActivityResult(requestCode, resultCode, data);
+// // 鎵弿浜岀淮鐮�/鏉$爜鍥炰紶
+// if (requestCode == REQUEST_CODE_SCAN && resultCode == RESULT_OK) {
+// if (data != null) {
+// //杩斿洖鐨勬枃鏈唴瀹�
+// String content = data.getStringExtra(DECODED_CONTENT_KEY);
+// //杩斿洖鐨凚itMap鍥惧儚
+// Bitmap bitmap = data.getParcelableExtra(DECODED_BITMAP_KEY);
+//
+// mQRC_textView.setText("浣犳壂鎻忓埌鐨勫唴瀹规槸锛�" + content);
+// }
+// }
+// }
+
+
+
+ public void startActivity2(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+
+ intent.putExtra(HDLUtlisXM.CROP_TYPE_KEY,102);
+ intent.putExtra(HDLUtlisXM.CROP_NAME_KEY, "HDL_IMAGE");
+ intent.putExtra(HDLUtlisXM.CROP_RATIO_X_KEY,11);
+ intent.putExtra(HDLUtlisXM.CROP_RATIO_Y_KEY,9);
+// intent.putExtra(HDLUtlisXM.CROP_OUTPUT_Y_KEY,300);
+
+
+ startActivity(intent);
+// overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/WaveSeekBarActivity.java b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/WaveSeekBarActivity.java
new file mode 100644
index 0000000..93fad27
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/java/com/hdl/widget/WaveSeekBarActivity.java
@@ -0,0 +1,77 @@
+package com.hdl.widget;
+
+import android.content.Intent;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+
+public class WaveSeekBarActivity extends AppCompatActivity {
+
+ private TextView mProgressText;
+ private HDLWaveSeekBar mHDLWaveSeekBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_wave_seek_bar);
+
+ mProgressText = findViewById(R.id.txt_progress);
+
+ mHDLWaveSeekBar = findViewById(R.id.mHDLWaveSeekBar);
+
+// mHDLWaveSeekBar.setMaxValue(35);
+// mHDLWaveSeekBar.setMinValue(16);
+// mHDLWaveSeekBar.setProgressBarUnitSring("鈩�");
+
+ mHDLWaveSeekBar.setOnProgressChangeListener(new HDLWaveSeekBar.OnProgressChangeListener() {
+ @Override
+ public void onProgressChanged(HDLWaveSeekBar seekBar, int progress, boolean isUser) {
+ setEngry(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(HDLWaveSeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(HDLWaveSeekBar seekBar) {
+ setEngry(seekBar.getProgress());
+ }
+ });
+
+
+
+
+ findViewById(R.id.btn_0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHDLWaveSeekBar.setProgress(20);
+ }
+ });
+
+ findViewById(R.id.btn_90).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+// mHDLWaveSeekBar.setProgress(90);
+
+ startActivity(CurtainSeekBarActivity.class);
+ }
+ });
+ }
+
+
+ private void setEngry(int progress) {
+ mProgressText.setText( progress + "%");
+
+ }
+
+ public void startActivity(Class<?> clazz) {
+ Intent intent = new Intent(this, clazz);
+
+ startActivity(intent);
+// overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
+
+ }
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/bg.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/bg.xml
new file mode 100644
index 0000000..bdfb728
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/bg.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:angle="135"
+ android:endColor="#3C3C3D"
+ android:startColor="#3C3C3D" />
+
+</shape>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/hdl_seekbar_thumb.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/hdl_seekbar_thumb.xml
new file mode 100644
index 0000000..7996363
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/hdl_seekbar_thumb.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
+
+ <size
+ android:width="45dp"
+ android:height="45dp"
+ />
+ <solid android:color="#F8AF68"/>
+
+</shape>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/ic_launcher.png b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/ic_launcher.png
new file mode 100644
index 0000000..6e9edb1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/drawable/ic_launcher.png
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_arc_scale_seek_bar.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_arc_scale_seek_bar.xml
new file mode 100644
index 0000000..10de013
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_arc_scale_seek_bar.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-ArcScaleSeekBar"
+ android:textColor="@color/black"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.HDLArcScaleSeekBar
+ android:id="@+id/mHDLArcScaleSeekBar"
+ android:layout_width="250dp"
+ android:layout_height="250dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"
+ />
+
+
+ <!--<RelativeLayout-->
+ <!--android:layout_width="300dp"-->
+ <!--android:layout_height="300dp"-->
+ <!--android:layout_gravity="center"-->
+ <!-->-->
+
+ <!--<com.hdl.widget.HDLArcScaleSeekBar-->
+ <!--android:id="@+id/mHDLArcScaleSeekBar"-->
+ <!--android:layout_width="300dp"-->
+ <!--android:layout_height="300dp"-->
+ <!--android:layout_centerInParent="true"-->
+ <!--/>-->
+
+ <!--<LinearLayout-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:orientation="vertical"-->
+ <!--android:layout_centerInParent="true"-->
+ <!--android:layout_marginLeft="50dp"-->
+ <!--android:layout_marginRight="50dp"-->
+ <!--android:clickable="true"-->
+ <!-->-->
+ <!--<LinearLayout-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="0dp"-->
+ <!--android:layout_weight="1">-->
+
+ <!--<TextView-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:gravity="center"-->
+ <!--android:text="鍒剁儹"/>-->
+ <!--</LinearLayout>-->
+
+ <!--<LinearLayout-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="0dp"-->
+ <!--android:layout_weight="1"-->
+ <!--android:orientation="horizontal">-->
+
+ <!--<ImageView-->
+ <!--android:layout_width="25dp"-->
+ <!--android:layout_height="match_parent"-->
+
+ <!--android:src="@drawable/ic_gdmap_zoom_out" />-->
+
+ <!--<TextView-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="match_parent"-->
+ <!--android:layout_weight="1"-->
+ <!--android:gravity="center"-->
+ <!--android:textSize="20sp"-->
+ <!--android:text="30"/>-->
+
+ <!--<ImageView-->
+ <!--android:layout_width="20dp"-->
+ <!--android:layout_height="20dp"-->
+ <!--android:src="@drawable/ic_gdmap_add"/>-->
+
+
+ <!--</LinearLayout>-->
+ <!--<LinearLayout-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="0dp"-->
+ <!--android:layout_weight="1">-->
+ <!--<TextView-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:gravity="center"-->
+ <!--android:text="鈩�"/>-->
+
+ <!--</LinearLayout>-->
+
+ <!--</LinearLayout>-->
+
+
+ <!--</RelativeLayout>-->
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 18"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+ <TextView
+ android:id="@+id/txt_progress"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Progress"
+
+ android:textSize="25sp"
+ android:textStyle="bold"
+ />
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 30"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_cover_flow_view.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_cover_flow_view.xml
new file mode 100644
index 0000000..3c436db
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_cover_flow_view.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@drawable/bg">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-CoverFlowView"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.CoverFlowViewPager.HDLCoverFlowViewPager
+ android:id="@+id/hdl_galleryViewPager"
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:layout_marginTop="38dp"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="閫変腑7"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+ <TextView
+ android:id="@+id/txt_progress"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text=""
+ android:textColor="#fff"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ />
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="鍒犻櫎"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_curtain_seek_bar.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_curtain_seek_bar.xml
new file mode 100644
index 0000000..2b0467d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_curtain_seek_bar.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@color/white">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-CurtainSeekBar"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+ <LinearLayout
+ android:layout_width="208dp"
+ android:layout_height="294dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ >
+
+ <!--<ImageView-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="20dp"-->
+ <!--android:background="@drawable/ic_wd_curtain_bg_top"/>-->
+
+ <com.hdl.widget.HDLRollCurtainSeekBar
+ android:id="@+id/mHDLRollCurtainSeekBar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+
+ />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="248dp"
+ android:layout_height="227dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ >
+
+ <!--<ImageView-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="20dp"-->
+ <!--android:background="@drawable/ic_wd_curtain_bg_top"/>-->
+
+ <com.hdl.widget.HDLOACCurtainSeekBar
+ android:id="@+id/mHDLOACCurtainSeekBar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ />
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+ <TextView
+ android:id="@+id/txt_progress"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Progress"
+ android:textColor="#fff"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ />
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_diy_image_horizontal_seek_bar.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_diy_image_horizontal_seek_bar.xml
new file mode 100644
index 0000000..cf8cc88
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_diy_image_horizontal_seek_bar.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-DiyImageSeekBar"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.HDLDiyImageSeekBar
+ android:id="@+id/mHDLDiyImageHorizontalSeekBar"
+ android:layout_width="250dp"
+ android:layout_height="100dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"/>
+
+ <com.hdl.widget.HDLDiyImageVerticalSeekBar
+ android:id="@+id/mHDLDiyImageVerticalSeekBar"
+ android:layout_width="100dp"
+ android:layout_height="400dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"/>
+
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+ <EditText
+ android:id="@+id/txt_progress"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Progress"
+ android:textColor="#fff"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ android:inputType="textPassword"
+ />
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_gesture_lock.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_gesture_lock.xml
new file mode 100644
index 0000000..733a193
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_gesture_lock.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-GestureLock"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+ <com.hdl.widget.gesturelock.GestureLockView
+ android:id="@+id/mGestureLockView"
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="center" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_hdlwidget_list.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_hdlwidget_list.xml
new file mode 100644
index 0000000..932415c
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_hdlwidget_list.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@drawable/bg">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="48dp"
+ android:text="HDL-ArcSeekBar"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ android:background="@android:color/black"
+ android:gravity="center" />
+
+ <ListView
+ android:id="@+id/listview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/white">
+
+ </ListView>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_main.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..00c99fd
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg"
+ tools:context="com.hdl.widget.MainActivity">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="68dp"
+ android:text="HDL-ArcSeekBar"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.CoverFlowViewPager.HDLCoverFlowViewPager
+ android:id="@+id/hdl_galleryViewPager"
+ android:layout_width="match_parent"
+ android:layout_height="120dp"
+ android:layout_marginTop="38dp"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+
+
+
+ <FrameLayout
+ android:id="@+id/arc_seek_bar_wrap"
+ android:layout_width="400dp"
+ android:layout_height="400dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+ <!--<com.gcssloop.widget.ArcSeekBar-->
+ <!--android:id="@+id/arc_seek_bar"-->
+ <!--android:layout_width="380dp"-->
+ <!--android:layout_height="380dp"-->
+ <!--android:padding="20dp"-->
+ <!--app:arc_border_color="#fff"-->
+ <!--app:arc_border_width="1dp"-->
+ <!--app:arc_colors="@array/arc_colors_custom"-->
+ <!--app:arc_max="100"-->
+ <!--app:arc_min="0"-->
+ <!--app:arc_open_angle="30"-->
+ <!--app:arc_progress="-0"-->
+ <!--app:arc_rotate_angle="90"-->
+ <!--app:arc_shadow_radius="5dp"-->
+ <!--app:arc_thumb_color="#fff"-->
+ <!--app:arc_thumb_mode="FILL"-->
+ <!--app:arc_thumb_radius="7dp"-->
+ <!--app:arc_thumb_shadow_color="#000000"-->
+ <!--app:arc_thumb_shadow_radius="3dp"-->
+ <!--app:arc_thumb_width="8dp"-->
+ <!--app:arc_progress_bar_color="@color/app_background_blue"-->
+ <!--app:arc_width="15dp" />-->
+
+ <com.hdl.widget.HDLArcSeekBar
+ android:id="@+id/arc_seek_bar_2"
+ android:layout_width="400dp"
+ android:layout_height="400dp"
+ app:arc_border_color="#fff"
+ app:arc_colors="@array/arc_colors_custom"
+ app:hdl_arc_thumb_mode="FILL"
+ app:arc_progress_bar_color="@color/app_background_blue"
+ />
+
+ <com.hdl.widget.HDLArcSeekBar
+ android:id="@+id/arc_seek_bar"
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_marginTop="50dp"
+ android:layout_marginLeft="50dp"
+ app:arc_colors="@array/arc_colors_custom"
+ app:arc_progress_bar_color="@color/app_background" />
+ </FrameLayout>
+
+
+
+
+ <TextView
+ android:id="@+id/txt_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="Progress"
+ android:textColor="#fff"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ app:layout_constraintBottom_toBottomOf="@id/arc_seek_bar_wrap"
+ app:layout_constraintLeft_toLeftOf="@id/arc_seek_bar_wrap"
+ app:layout_constraintRight_toRightOf="@id/arc_seek_bar_wrap"
+ app:layout_constraintTop_toTopOf="@id/arc_seek_bar_wrap" />
+
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ android:layout_marginBottom="5dp"/>
+
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ android:layout_marginBottom="5dp"/>
+
+ <Button
+ android:id="@+id/btn_go"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璺宠浆"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toRightOf="@+id/btn_0"
+ android:layout_marginBottom="5dp"/>
+
+ <Button
+ android:id="@+id/btn_go_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="楂樺痉鍦板浘"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toRightOf="@+id/btn_go"
+ android:layout_marginBottom="5dp"/>
+
+ <Button
+ android:id="@+id/btn_go_3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璺宠浆3"
+ android:visibility="gone"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toRightOf="@+id/btn_go"
+ android:layout_marginBottom="5dp"/>
+
+
+</android.support.constraint.ConstraintLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_picker_view.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_picker_view.xml
new file mode 100644
index 0000000..729b24e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_picker_view.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@drawable/bg">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-PickerView"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.pickerview.view.HDLPickerView
+ android:id="@+id/mHDLPickerView"
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"/>
+
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/hdl_pickerview_btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+ <Button
+ android:id="@+id/hdl_pickerview_btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_qrcode.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_qrcode.xml
new file mode 100644
index 0000000..8b2d6e1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_qrcode.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@drawable/bg">
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="60dp" />
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@color/white">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="2"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/> <TextView
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:gravity="center"
+ android:text="1"/>
+
+ </LinearLayout>
+ </LinearLayout>
+
+ </ScrollView>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-瑁佸壀"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <ImageView
+ android:id="@+id/mQRC_image"
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"/>
+
+
+<TextView
+ android:id="@+id/mQRC_textView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/white"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/hdl_btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="鐢熸垚浜岀淮鐮�"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"
+ android:visibility="gone"/>
+
+
+ <Button
+ android:id="@+id/hdl_btn_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="鎵弿"
+ android:layout_gravity="bottom"
+ android:visibility="gone"
+ android:layout_marginBottom="5dp"/>
+ <Button
+ android:id="@+id/hdl_btn_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="瑁佸壀澶村儚"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+ </LinearLayout>
+
+
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_wave_seek_bar.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_wave_seek_bar.xml
new file mode 100644
index 0000000..a509847
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/layout/activity_wave_seek_bar.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="@drawable/bg">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="HDL-WaveSeekBar"
+ android:textColor="#fff"
+ android:textSize="32sp"
+ android:textStyle="bold"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.hdl.widget.HDLWaveSeekBar
+ android:id="@+id/mHDLWaveSeekBar"
+ android:layout_width="120dp"
+ android:layout_height="240dp"
+ android:layout_marginTop="20dp"
+ android:layout_gravity="center"
+ app:wave_color="@color/app_background_blue2"
+ app:wave_border_color="@color/app_background_blue3"
+ android:background="@color/white"/>
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@+id/btn_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 20"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+ <TextView
+ android:id="@+id/txt_progress"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Progress"
+ android:textColor="#fff"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ />
+ <Button
+ android:id="@+id/btn_90"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="璁剧疆 90"
+ android:layout_gravity="bottom"
+ android:layout_marginBottom="5dp"/>
+
+
+
+ </LinearLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/colors.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..7ede6d0
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/colors.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+
+ <color name="arc_b">#484849</color>
+ <color name="arc_p">#484849</color>
+
+ <color name="arc_bar_start">#FBE7C2</color>
+ <color name="arc_bar_end">#FFEB3B</color>
+ <!--涓婚棰滆壊-->
+ <color name="app_background">#ECA955</color>
+ <color name="app_background_blue">#3D68D4</color>
+ <!--榛樿鑳屾櫙棰滆壊-->
+ <color name="backgroundColor">#F0F0F0</color>
+ <color name="default_bg">#F0F0F0</color>
+ <color name="default_bg_2">#DCDCDC</color>
+
+
+ <color name="transparent">#00000000</color>
+ <color name="transparent02">#30000000</color>
+ <color name="black">#ff000000</color>
+ <color name="white">#ffffffff</color>
+ <color name="gray_85">#D9adb1b6</color>
+ <color name="gray_c">#c1c1c2</color>
+
+ <color name="app_background_blue2">#CBCEE5</color>
+ <color name="app_background_blue3">#495780</color>
+ <color name="app_background_blue4">#E9E9EC</color>
+
+ <color name="app_background_1">#495AF4</color>
+ <color name="app_background_2">#AE50A8</color>
+ <color name="app_background_3">#EAEAEB</color>
+ <color name="app_background_4">#FD692E</color>
+ <color name="app_background_5">#FB3140</color>
+ <array name="arc_colors_custom">
+ <item>#484849</item>
+ <item>#484849</item>
+ <item>#484849</item>
+ </array>
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/strings.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..c1a4724
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">HDLWidget_Android</string>
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/styles.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..60b1364
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/values/styles.xml
@@ -0,0 +1,13 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ <item name="windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ </style>
+
+</resources>
diff --git a/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/xml/hdl_filepaths.xml b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/xml/hdl_filepaths.xml
new file mode 100644
index 0000000..2e36ae1
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/app/src/main/res/xml/hdl_filepaths.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths>
+ <external-path path="" name="download"/>
+</paths>
\ No newline at end of file
diff --git a/HDL_Widget_XM/HDLWidget_Android/build.gradle b/HDL_Widget_XM/HDLWidget_Android/build.gradle
new file mode 100644
index 0000000..9cbfcc6
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/build.gradle
@@ -0,0 +1,31 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.0'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+
+
+}
+
+
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/HDL_Widget_XM/HDLWidget_Android/gradle.properties b/HDL_Widget_XM/HDLWidget_Android/gradle.properties
new file mode 100644
index 0000000..adc5a4a
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/gradle.properties
@@ -0,0 +1,14 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+#android.enableAapt2=false
diff --git a/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.jar b/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7a3265e
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.properties b/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..aa27d08
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Sep 01 22:45:47 CST 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/HDL_Widget_XM/HDLWidget_Android/gradlew b/HDL_Widget_XM/HDLWidget_Android/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/HDL_Widget_XM/HDLWidget_Android/gradlew.bat b/HDL_Widget_XM/HDLWidget_Android/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/HDL_Widget_XM/HDLWidget_Android/settings.gradle b/HDL_Widget_XM/HDLWidget_Android/settings.gradle
new file mode 100644
index 0000000..33843f7
--- /dev/null
+++ b/HDL_Widget_XM/HDLWidget_Android/settings.gradle
@@ -0,0 +1,2 @@
+include ':app', ':HDLWidgetXM'
+//, ':pickerview', ':wheelview'
\ No newline at end of file
diff --git a/HDL_Widget_XM/README.md b/HDL_Widget_XM/README.md
new file mode 100644
index 0000000..a0d023e
--- /dev/null
+++ b/HDL_Widget_XM/README.md
@@ -0,0 +1,11 @@
+## HDLWidgetXM(鑷畾涔夋帶浠跺簱)
+
+### *****V1.0.3*****
+### 1.HDLArcSeekbar(鍦嗗姬鎷栧姩鏉�)
+### 2.HDLWaveSeekBar(娉㈡氮鏁堟灉鎷栧姩鏉�)
+### 3.HDLPickerView
+### 4.GDMapKit 楂樺痉鍦板浘
+### 5.HDLCoverFlowViewPager
+### 6.閲嶅惎APP 鏂规硶鎺ュ彛
+
+
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.pbxproj b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..909c3d4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.pbxproj
@@ -0,0 +1,668 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 50;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 4B231B62233C9C650018B9C8 /* HDLPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B231B60233C9C650018B9C8 /* HDLPickerView.m */; };
+ 4B65C7E8237BB5D800E0DC16 /* ScalePointData.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B65C7E6237BB5D800E0DC16 /* ScalePointData.m */; };
+ 4B65C7E9237BB5D800E0DC16 /* HDLArcScaleSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B65C7E7237BB5D800E0DC16 /* HDLArcScaleSeekBar.m */; };
+ 4B74CA112320B29E00C4EC2F /* HDLArcSeekbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74C9FF2320B29E00C4EC2F /* HDLArcSeekbar.m */; };
+ 4B74CA122320B29E00C4EC2F /* HDLCoverFlowCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA022320B29E00C4EC2F /* HDLCoverFlowCell.m */; };
+ 4B74CA132320B29E00C4EC2F /* HDLCoverFlow.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA032320B29E00C4EC2F /* HDLCoverFlow.m */; };
+ 4B74CA142320B29E00C4EC2F /* HDLCoverFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA042320B29E00C4EC2F /* HDLCoverFlowLayout.m */; };
+ 4B74CA152320B29E00C4EC2F /* HDLWaveSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA092320B29E00C4EC2F /* HDLWaveSeekBar.m */; };
+ 4B74CA172320B29E00C4EC2F /* HDLTouchID.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA102320B29E00C4EC2F /* HDLTouchID.m */; };
+ 4B74CA1B2320B4C800C4EC2F /* ZJPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B74CA192320B4C800C4EC2F /* ZJPickerView.m */; };
+ 4B8890B5239E225500B83519 /* HDLDiyImageSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8890B3239E225500B83519 /* HDLDiyImageSeekBar.m */; };
+ 4B9B13BB23741BE500088244 /* HDLOACCurtainSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9B13B123741BE400088244 /* HDLOACCurtainSeekBar.m */; };
+ 4B9B13BC23741BE500088244 /* HDLRollCurtainSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9B13B623741BE400088244 /* HDLRollCurtainSeekBar.m */; };
+ 4B9B13BF2374220D00088244 /* SeekBarDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9B13BE2374220D00088244 /* SeekBarDelegate.m */; };
+ 4BCCD7FF2369AE1D000EF33F /* HDLGestureLockView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BCCD7FE2369AE1D000EF33F /* HDLGestureLockView.m */; };
+ 4BCCD8022369AE96000EF33F /* HDLUtlisXM.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BCCD8012369AE96000EF33F /* HDLUtlisXM.m */; };
+ B93ACB1724ED1F0300F310DE /* CropImageUtlis.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAE824ED1F0300F310DE /* CropImageUtlis.m */; };
+ B93ACB1824ED1F0300F310DE /* HQImageEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAEA24ED1F0300F310DE /* HQImageEditViewController.m */; };
+ B93ACB1924ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAED24ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.m */; };
+ B93ACB1A24ED1F0300F310DE /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAF624ED1F0300F310DE /* ViewController+MASAdditions.m */; };
+ B93ACB1B24ED1F0300F310DE /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAFA24ED1F0300F310DE /* MASCompositeConstraint.m */; };
+ B93ACB1C24ED1F0300F310DE /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAFB24ED1F0300F310DE /* MASConstraintMaker.m */; };
+ B93ACB1D24ED1F0300F310DE /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAFC24ED1F0300F310DE /* MASLayoutConstraint.m */; };
+ B93ACB1E24ED1F0300F310DE /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAFD24ED1F0300F310DE /* NSArray+MASAdditions.m */; };
+ B93ACB1F24ED1F0300F310DE /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACAFE24ED1F0300F310DE /* View+MASAdditions.m */; };
+ B93ACB2024ED1F0300F310DE /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0124ED1F0300F310DE /* MASConstraint.m */; };
+ B93ACB2124ED1F0300F310DE /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0324ED1F0300F310DE /* MASViewConstraint.m */; };
+ B93ACB2224ED1F0300F310DE /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0424ED1F0300F310DE /* MASViewAttribute.m */; };
+ B93ACB2324ED1F0300F310DE /* HQEditImageActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0624ED1F0300F310DE /* HQEditImageActionView.m */; };
+ B93ACB2424ED1F0300F310DE /* HQEditImageEditView.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0824ED1F0300F310DE /* HQEditImageEditView.m */; };
+ B93ACB2524ED1F0300F310DE /* HQEditImageCaptureView.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB0A24ED1F0300F310DE /* HQEditImageCaptureView.m */; };
+ B93ACB2A24ED1F0300F310DE /* UIImageCrop.m in Sources */ = {isa = PBXBuildFile; fileRef = B93ACB1324ED1F0300F310DE /* UIImageCrop.m */; };
+ B94D9DA22499C5F3008A7B96 /* HDLDiyArcSeekbar.m in Sources */ = {isa = PBXBuildFile; fileRef = B94D9DA12499C5F2008A7B96 /* HDLDiyArcSeekbar.m */; };
+ B94D9DB42499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = B94D9DA82499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.m */; };
+ B94D9DB52499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = B94D9DAC2499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.m */; };
+ B95B009324AEC2DD0049A516 /* HDLOnWaveSeekbar.m in Sources */ = {isa = PBXBuildFile; fileRef = B95B009124AEC2DD0049A516 /* HDLOnWaveSeekbar.m */; };
+ B9A22FE7241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.m in Sources */ = {isa = PBXBuildFile; fileRef = B9A22FE6241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 4B74C9C92320B13D00C4EC2F /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "include/$(PRODUCT_NAME)";
+ dstSubfolderSpec = 16;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 4B231B60233C9C650018B9C8 /* HDLPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLPickerView.m; sourceTree = "<group>"; };
+ 4B231B61233C9C650018B9C8 /* HDLPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLPickerView.h; sourceTree = "<group>"; };
+ 4B65C7E4237BB5D800E0DC16 /* HDLArcScaleSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLArcScaleSeekBar.h; sourceTree = "<group>"; };
+ 4B65C7E5237BB5D800E0DC16 /* ScalePointData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScalePointData.h; sourceTree = "<group>"; };
+ 4B65C7E6237BB5D800E0DC16 /* ScalePointData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScalePointData.m; sourceTree = "<group>"; };
+ 4B65C7E7237BB5D800E0DC16 /* HDLArcScaleSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLArcScaleSeekBar.m; sourceTree = "<group>"; };
+ 4B74C9CB2320B13D00C4EC2F /* libHDLWidgetLibrary.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHDLWidgetLibrary.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B74C9FF2320B29E00C4EC2F /* HDLArcSeekbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLArcSeekbar.m; sourceTree = "<group>"; };
+ 4B74CA002320B29E00C4EC2F /* HDLArcSeekbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLArcSeekbar.h; sourceTree = "<group>"; };
+ 4B74CA022320B29E00C4EC2F /* HDLCoverFlowCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLCoverFlowCell.m; sourceTree = "<group>"; };
+ 4B74CA032320B29E00C4EC2F /* HDLCoverFlow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLCoverFlow.m; sourceTree = "<group>"; };
+ 4B74CA042320B29E00C4EC2F /* HDLCoverFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLCoverFlowLayout.m; sourceTree = "<group>"; };
+ 4B74CA052320B29E00C4EC2F /* HDLCoverFlow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLCoverFlow.h; sourceTree = "<group>"; };
+ 4B74CA062320B29E00C4EC2F /* HDLCoverFlowCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLCoverFlowCell.h; sourceTree = "<group>"; };
+ 4B74CA072320B29E00C4EC2F /* HDLCoverFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLCoverFlowLayout.h; sourceTree = "<group>"; };
+ 4B74CA092320B29E00C4EC2F /* HDLWaveSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLWaveSeekBar.m; sourceTree = "<group>"; };
+ 4B74CA0A2320B29E00C4EC2F /* HDLWaveSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLWaveSeekBar.h; sourceTree = "<group>"; };
+ 4B74CA0F2320B29E00C4EC2F /* HDLTouchID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLTouchID.h; sourceTree = "<group>"; };
+ 4B74CA102320B29E00C4EC2F /* HDLTouchID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLTouchID.m; sourceTree = "<group>"; };
+ 4B74CA192320B4C800C4EC2F /* ZJPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZJPickerView.m; sourceTree = "<group>"; };
+ 4B74CA1A2320B4C800C4EC2F /* ZJPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZJPickerView.h; sourceTree = "<group>"; };
+ 4B8890B3239E225500B83519 /* HDLDiyImageSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLDiyImageSeekBar.m; sourceTree = "<group>"; };
+ 4B8890B4239E225500B83519 /* HDLDiyImageSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLDiyImageSeekBar.h; sourceTree = "<group>"; };
+ 4B9B13AE23741BE400088244 /* ic_wd_curtain_roll_progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_roll_progress.png; sourceTree = "<group>"; };
+ 4B9B13AF23741BE400088244 /* HDLRollCurtainSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLRollCurtainSeekBar.h; sourceTree = "<group>"; };
+ 4B9B13B023741BE400088244 /* ic_wd_curtain_h_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_h_bg.png; sourceTree = "<group>"; };
+ 4B9B13B123741BE400088244 /* HDLOACCurtainSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLOACCurtainSeekBar.m; sourceTree = "<group>"; };
+ 4B9B13B223741BE400088244 /* ic_wd_curtain_h_open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_h_open.png; sourceTree = "<group>"; };
+ 4B9B13B323741BE400088244 /* ic_wd_curtain_open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_open.png; sourceTree = "<group>"; };
+ 4B9B13B523741BE400088244 /* ic_wd_curtain_roll_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_roll_bg.png; sourceTree = "<group>"; };
+ 4B9B13B623741BE400088244 /* HDLRollCurtainSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLRollCurtainSeekBar.m; sourceTree = "<group>"; };
+ 4B9B13B723741BE400088244 /* HDLOACCurtainSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLOACCurtainSeekBar.h; sourceTree = "<group>"; };
+ 4B9B13B823741BE400088244 /* ic_wd_curtain_bg_top.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_bg_top.png; sourceTree = "<group>"; };
+ 4B9B13B923741BE400088244 /* ic_wd_curtain_h_progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_h_progress.png; sourceTree = "<group>"; };
+ 4B9B13BD2374220C00088244 /* SeekBarDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SeekBarDelegate.h; sourceTree = "<group>"; };
+ 4B9B13BE2374220D00088244 /* SeekBarDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SeekBarDelegate.m; sourceTree = "<group>"; };
+ 4BCCD7FD2369AE1D000EF33F /* HDLGestureLockView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLGestureLockView.h; sourceTree = "<group>"; };
+ 4BCCD7FE2369AE1D000EF33F /* HDLGestureLockView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLGestureLockView.m; sourceTree = "<group>"; };
+ 4BCCD8002369AE96000EF33F /* HDLUtlisXM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HDLUtlisXM.h; sourceTree = "<group>"; };
+ 4BCCD8012369AE96000EF33F /* HDLUtlisXM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HDLUtlisXM.m; sourceTree = "<group>"; };
+ B93ACAE524ED1F0300F310DE /* UIImageCrop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIImageCrop.h; sourceTree = "<group>"; };
+ B93ACAE824ED1F0300F310DE /* CropImageUtlis.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CropImageUtlis.m; sourceTree = "<group>"; };
+ B93ACAEA24ED1F0300F310DE /* HQImageEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HQImageEditViewController.m; sourceTree = "<group>"; };
+ B93ACAEC24ED1F0300F310DE /* MASCompositeConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASCompositeConstraint.h; sourceTree = "<group>"; };
+ B93ACAED24ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = "<group>"; };
+ B93ACAEE24ED1F0300F310DE /* MASConstraint+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MASConstraint+Private.h"; sourceTree = "<group>"; };
+ B93ACAEF24ED1F0300F310DE /* MASLayoutConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASLayoutConstraint.h; sourceTree = "<group>"; };
+ B93ACAF024ED1F0300F310DE /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MASShorthandAdditions.h"; sourceTree = "<group>"; };
+ B93ACAF124ED1F0300F310DE /* MASConstraintMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASConstraintMaker.h; sourceTree = "<group>"; };
+ B93ACAF224ED1F0300F310DE /* View+MASAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "View+MASAdditions.h"; sourceTree = "<group>"; };
+ B93ACAF324ED1F0300F310DE /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MASAdditions.h"; sourceTree = "<group>"; };
+ B93ACAF424ED1F0300F310DE /* MASUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASUtilities.h; sourceTree = "<group>"; };
+ B93ACAF524ED1F0300F310DE /* MASViewAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASViewAttribute.h; sourceTree = "<group>"; };
+ B93ACAF624ED1F0300F310DE /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ViewController+MASAdditions.m"; sourceTree = "<group>"; };
+ B93ACAF724ED1F0300F310DE /* MASViewConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASViewConstraint.h; sourceTree = "<group>"; };
+ B93ACAF824ED1F0300F310DE /* MASConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASConstraint.h; sourceTree = "<group>"; };
+ B93ACAF924ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = "<group>"; };
+ B93ACAFA24ED1F0300F310DE /* MASCompositeConstraint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASCompositeConstraint.m; sourceTree = "<group>"; };
+ B93ACAFB24ED1F0300F310DE /* MASConstraintMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASConstraintMaker.m; sourceTree = "<group>"; };
+ B93ACAFC24ED1F0300F310DE /* MASLayoutConstraint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASLayoutConstraint.m; sourceTree = "<group>"; };
+ B93ACAFD24ED1F0300F310DE /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+MASAdditions.m"; sourceTree = "<group>"; };
+ B93ACAFE24ED1F0300F310DE /* View+MASAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "View+MASAdditions.m"; sourceTree = "<group>"; };
+ B93ACAFF24ED1F0300F310DE /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "View+MASShorthandAdditions.h"; sourceTree = "<group>"; };
+ B93ACB0024ED1F0300F310DE /* Masonry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Masonry.h; sourceTree = "<group>"; };
+ B93ACB0124ED1F0300F310DE /* MASConstraint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASConstraint.m; sourceTree = "<group>"; };
+ B93ACB0224ED1F0300F310DE /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ViewController+MASAdditions.h"; sourceTree = "<group>"; };
+ B93ACB0324ED1F0300F310DE /* MASViewConstraint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASViewConstraint.m; sourceTree = "<group>"; };
+ B93ACB0424ED1F0300F310DE /* MASViewAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASViewAttribute.m; sourceTree = "<group>"; };
+ B93ACB0624ED1F0300F310DE /* HQEditImageActionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HQEditImageActionView.m; sourceTree = "<group>"; };
+ B93ACB0724ED1F0300F310DE /* HQEditImageCaptureView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HQEditImageCaptureView.h; sourceTree = "<group>"; };
+ B93ACB0824ED1F0300F310DE /* HQEditImageEditView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HQEditImageEditView.m; sourceTree = "<group>"; };
+ B93ACB0924ED1F0300F310DE /* HQEditImageActionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HQEditImageActionView.h; sourceTree = "<group>"; };
+ B93ACB0A24ED1F0300F310DE /* HQEditImageCaptureView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HQEditImageCaptureView.m; sourceTree = "<group>"; };
+ B93ACB0B24ED1F0300F310DE /* HQEditImageEditView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HQEditImageEditView.h; sourceTree = "<group>"; };
+ B93ACB0C24ED1F0300F310DE /* HQImageEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HQImageEditViewController.h; sourceTree = "<group>"; };
+ B93ACB1024ED1F0300F310DE /* CropImageUtlis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CropImageUtlis.h; sourceTree = "<group>"; };
+ B93ACB1324ED1F0300F310DE /* UIImageCrop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIImageCrop.m; sourceTree = "<group>"; };
+ B94D9DA02499C5F2008A7B96 /* HDLDiyArcSeekbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLDiyArcSeekbar.h; sourceTree = "<group>"; };
+ B94D9DA12499C5F2008A7B96 /* HDLDiyArcSeekbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLDiyArcSeekbar.m; sourceTree = "<group>"; };
+ B94D9DA42499C5FD008A7B96 /* ic_wd_on_curtain_roll_progress_close.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_roll_progress_close.png; sourceTree = "<group>"; };
+ B94D9DA52499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLOnRollCurtainSeekBar.h; sourceTree = "<group>"; };
+ B94D9DA62499C5FD008A7B96 /* ic_wd_on_curtain_h_open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_h_open.png; sourceTree = "<group>"; };
+ B94D9DA72499C5FD008A7B96 /* ic_wd_on_curtain_open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_open.png; sourceTree = "<group>"; };
+ B94D9DA82499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLOnOACCurtainSeekBar.m; sourceTree = "<group>"; };
+ B94D9DA92499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress_close2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_blinds_progress_close2.png; sourceTree = "<group>"; };
+ B94D9DAA2499C5FD008A7B96 /* ic_wd_on_curtain_roll_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_roll_bg.png; sourceTree = "<group>"; };
+ B94D9DAB2499C5FD008A7B96 /* ic_wd_on_curtain_h_progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_h_progress.png; sourceTree = "<group>"; };
+ B94D9DAC2499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLOnRollCurtainSeekBar.m; sourceTree = "<group>"; };
+ B94D9DAD2499C5FD008A7B96 /* ic_wd_on_curtain_roll_progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_roll_progress.png; sourceTree = "<group>"; };
+ B94D9DAE2499C5FD008A7B96 /* ic_wd_on_curtain_h_progress_close.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_h_progress_close.png; sourceTree = "<group>"; };
+ B94D9DAF2499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_blinds_progress2.png; sourceTree = "<group>"; };
+ B94D9DB02499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress_close.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_blinds_progress_close.png; sourceTree = "<group>"; };
+ B94D9DB12499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLOnOACCurtainSeekBar.h; sourceTree = "<group>"; };
+ B94D9DB22499C5FD008A7B96 /* ic_wd_on_curtain_h_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_h_bg.png; sourceTree = "<group>"; };
+ B94D9DB32499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_on_curtain_blinds_progress.png; sourceTree = "<group>"; };
+ B95B009124AEC2DD0049A516 /* HDLOnWaveSeekbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLOnWaveSeekbar.m; sourceTree = "<group>"; };
+ B95B009224AEC2DD0049A516 /* HDLOnWaveSeekbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLOnWaveSeekbar.h; sourceTree = "<group>"; };
+ B9A22FE5241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLDiyImageVerticalSeekBar.h; sourceTree = "<group>"; };
+ B9A22FE6241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLDiyImageVerticalSeekBar.m; sourceTree = "<group>"; };
+ B9DFB658242B679C009F8CA7 /* ic_wd_curtain_h_top.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_wd_curtain_h_top.png; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4B74C9C82320B13D00C4EC2F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4B65C7E3237BB5D800E0DC16 /* HDLArcScaleSeekBar */ = {
+ isa = PBXGroup;
+ children = (
+ 4B65C7E5237BB5D800E0DC16 /* ScalePointData.h */,
+ 4B65C7E6237BB5D800E0DC16 /* ScalePointData.m */,
+ 4B65C7E4237BB5D800E0DC16 /* HDLArcScaleSeekBar.h */,
+ 4B65C7E7237BB5D800E0DC16 /* HDLArcScaleSeekBar.m */,
+ );
+ path = HDLArcScaleSeekBar;
+ sourceTree = "<group>";
+ };
+ 4B74C9C22320B13D00C4EC2F = {
+ isa = PBXGroup;
+ children = (
+ 4B74C9CD2320B13D00C4EC2F /* HDLWidgetLibrary */,
+ 4B74C9CC2320B13D00C4EC2F /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 4B74C9CC2320B13D00C4EC2F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4B74C9CB2320B13D00C4EC2F /* libHDLWidgetLibrary.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4B74C9CD2320B13D00C4EC2F /* HDLWidgetLibrary */ = {
+ isa = PBXGroup;
+ children = (
+ B93ACAE324ED1F0300F310DE /* CropImage */,
+ 4B8890B2239E220500B83519 /* HDLDiyImageSeekBar */,
+ 4B65C7E3237BB5D800E0DC16 /* HDLArcScaleSeekBar */,
+ 4B9B13AC23741BE400088244 /* HDLCurtainSeekBar */,
+ B94D9DA32499C5FD008A7B96 /* HDLONCurtainSeekBar */,
+ 4BCCD7FC2369AE1D000EF33F /* GestureLockView */,
+ 4B74CA182320B4C800C4EC2F /* ZJPickerView */,
+ 4B74C9FE2320B29E00C4EC2F /* HDLArcSeekbar */,
+ 4B74CA012320B29E00C4EC2F /* HDLCoverFlow */,
+ 4B74CA0E2320B29E00C4EC2F /* HDLTouchID */,
+ 4B74CA082320B29E00C4EC2F /* HDLWaveSeekbar */,
+ 4BCCD8002369AE96000EF33F /* HDLUtlisXM.h */,
+ 4BCCD8012369AE96000EF33F /* HDLUtlisXM.m */,
+ );
+ path = HDLWidgetLibrary;
+ sourceTree = "<group>";
+ };
+ 4B74C9FE2320B29E00C4EC2F /* HDLArcSeekbar */ = {
+ isa = PBXGroup;
+ children = (
+ B94D9DA02499C5F2008A7B96 /* HDLDiyArcSeekbar.h */,
+ B94D9DA12499C5F2008A7B96 /* HDLDiyArcSeekbar.m */,
+ 4B74CA002320B29E00C4EC2F /* HDLArcSeekbar.h */,
+ 4B74C9FF2320B29E00C4EC2F /* HDLArcSeekbar.m */,
+ );
+ path = HDLArcSeekbar;
+ sourceTree = "<group>";
+ };
+ 4B74CA012320B29E00C4EC2F /* HDLCoverFlow */ = {
+ isa = PBXGroup;
+ children = (
+ 4B74CA022320B29E00C4EC2F /* HDLCoverFlowCell.m */,
+ 4B74CA032320B29E00C4EC2F /* HDLCoverFlow.m */,
+ 4B74CA042320B29E00C4EC2F /* HDLCoverFlowLayout.m */,
+ 4B74CA052320B29E00C4EC2F /* HDLCoverFlow.h */,
+ 4B74CA062320B29E00C4EC2F /* HDLCoverFlowCell.h */,
+ 4B74CA072320B29E00C4EC2F /* HDLCoverFlowLayout.h */,
+ );
+ path = HDLCoverFlow;
+ sourceTree = "<group>";
+ };
+ 4B74CA082320B29E00C4EC2F /* HDLWaveSeekbar */ = {
+ isa = PBXGroup;
+ children = (
+ B95B009224AEC2DD0049A516 /* HDLOnWaveSeekbar.h */,
+ B95B009124AEC2DD0049A516 /* HDLOnWaveSeekbar.m */,
+ 4B74CA0A2320B29E00C4EC2F /* HDLWaveSeekBar.h */,
+ 4B74CA092320B29E00C4EC2F /* HDLWaveSeekBar.m */,
+ );
+ path = HDLWaveSeekbar;
+ sourceTree = "<group>";
+ };
+ 4B74CA0E2320B29E00C4EC2F /* HDLTouchID */ = {
+ isa = PBXGroup;
+ children = (
+ 4B74CA0F2320B29E00C4EC2F /* HDLTouchID.h */,
+ 4B74CA102320B29E00C4EC2F /* HDLTouchID.m */,
+ );
+ path = HDLTouchID;
+ sourceTree = "<group>";
+ };
+ 4B74CA182320B4C800C4EC2F /* ZJPickerView */ = {
+ isa = PBXGroup;
+ children = (
+ 4B231B61233C9C650018B9C8 /* HDLPickerView.h */,
+ 4B231B60233C9C650018B9C8 /* HDLPickerView.m */,
+ 4B74CA1A2320B4C800C4EC2F /* ZJPickerView.h */,
+ 4B74CA192320B4C800C4EC2F /* ZJPickerView.m */,
+ );
+ path = ZJPickerView;
+ sourceTree = "<group>";
+ };
+ 4B8890B2239E220500B83519 /* HDLDiyImageSeekBar */ = {
+ isa = PBXGroup;
+ children = (
+ B9A22FE5241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.h */,
+ B9A22FE6241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.m */,
+ 4B8890B4239E225500B83519 /* HDLDiyImageSeekBar.h */,
+ 4B8890B3239E225500B83519 /* HDLDiyImageSeekBar.m */,
+ );
+ path = HDLDiyImageSeekBar;
+ sourceTree = "<group>";
+ };
+ 4B9B13AC23741BE400088244 /* HDLCurtainSeekBar */ = {
+ isa = PBXGroup;
+ children = (
+ B9DFB658242B679C009F8CA7 /* ic_wd_curtain_h_top.png */,
+ 4B9B13BD2374220C00088244 /* SeekBarDelegate.h */,
+ 4B9B13BE2374220D00088244 /* SeekBarDelegate.m */,
+ 4B9B13AE23741BE400088244 /* ic_wd_curtain_roll_progress.png */,
+ 4B9B13B023741BE400088244 /* ic_wd_curtain_h_bg.png */,
+ 4B9B13B223741BE400088244 /* ic_wd_curtain_h_open.png */,
+ 4B9B13B323741BE400088244 /* ic_wd_curtain_open.png */,
+ 4B9B13B523741BE400088244 /* ic_wd_curtain_roll_bg.png */,
+ 4B9B13B823741BE400088244 /* ic_wd_curtain_bg_top.png */,
+ 4B9B13B923741BE400088244 /* ic_wd_curtain_h_progress.png */,
+ 4B9B13B723741BE400088244 /* HDLOACCurtainSeekBar.h */,
+ 4B9B13B123741BE400088244 /* HDLOACCurtainSeekBar.m */,
+ 4B9B13AF23741BE400088244 /* HDLRollCurtainSeekBar.h */,
+ 4B9B13B623741BE400088244 /* HDLRollCurtainSeekBar.m */,
+ );
+ path = HDLCurtainSeekBar;
+ sourceTree = "<group>";
+ };
+ 4BCCD7FC2369AE1D000EF33F /* GestureLockView */ = {
+ isa = PBXGroup;
+ children = (
+ 4BCCD7FD2369AE1D000EF33F /* HDLGestureLockView.h */,
+ 4BCCD7FE2369AE1D000EF33F /* HDLGestureLockView.m */,
+ );
+ path = GestureLockView;
+ sourceTree = "<group>";
+ };
+ B93ACAE324ED1F0300F310DE /* CropImage */ = {
+ isa = PBXGroup;
+ children = (
+ B93ACB1024ED1F0300F310DE /* CropImageUtlis.h */,
+ B93ACAE824ED1F0300F310DE /* CropImageUtlis.m */,
+ B93ACAE524ED1F0300F310DE /* UIImageCrop.h */,
+ B93ACB1324ED1F0300F310DE /* UIImageCrop.m */,
+ B93ACAE924ED1F0300F310DE /* HQImageEditViewController */,
+ );
+ path = CropImage;
+ sourceTree = "<group>";
+ };
+ B93ACAE924ED1F0300F310DE /* HQImageEditViewController */ = {
+ isa = PBXGroup;
+ children = (
+ B93ACB0C24ED1F0300F310DE /* HQImageEditViewController.h */,
+ B93ACAEA24ED1F0300F310DE /* HQImageEditViewController.m */,
+ B93ACAEB24ED1F0300F310DE /* Masonry */,
+ B93ACB0524ED1F0300F310DE /* View */,
+ );
+ path = HQImageEditViewController;
+ sourceTree = "<group>";
+ };
+ B93ACAEB24ED1F0300F310DE /* Masonry */ = {
+ isa = PBXGroup;
+ children = (
+ B93ACAEC24ED1F0300F310DE /* MASCompositeConstraint.h */,
+ B93ACAED24ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.m */,
+ B93ACAEE24ED1F0300F310DE /* MASConstraint+Private.h */,
+ B93ACAEF24ED1F0300F310DE /* MASLayoutConstraint.h */,
+ B93ACAF024ED1F0300F310DE /* NSArray+MASShorthandAdditions.h */,
+ B93ACAF124ED1F0300F310DE /* MASConstraintMaker.h */,
+ B93ACAF224ED1F0300F310DE /* View+MASAdditions.h */,
+ B93ACAF324ED1F0300F310DE /* NSArray+MASAdditions.h */,
+ B93ACAF424ED1F0300F310DE /* MASUtilities.h */,
+ B93ACAF524ED1F0300F310DE /* MASViewAttribute.h */,
+ B93ACAF624ED1F0300F310DE /* ViewController+MASAdditions.m */,
+ B93ACAF724ED1F0300F310DE /* MASViewConstraint.h */,
+ B93ACAF824ED1F0300F310DE /* MASConstraint.h */,
+ B93ACAF924ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.h */,
+ B93ACAFA24ED1F0300F310DE /* MASCompositeConstraint.m */,
+ B93ACAFB24ED1F0300F310DE /* MASConstraintMaker.m */,
+ B93ACAFC24ED1F0300F310DE /* MASLayoutConstraint.m */,
+ B93ACAFD24ED1F0300F310DE /* NSArray+MASAdditions.m */,
+ B93ACAFE24ED1F0300F310DE /* View+MASAdditions.m */,
+ B93ACAFF24ED1F0300F310DE /* View+MASShorthandAdditions.h */,
+ B93ACB0024ED1F0300F310DE /* Masonry.h */,
+ B93ACB0124ED1F0300F310DE /* MASConstraint.m */,
+ B93ACB0224ED1F0300F310DE /* ViewController+MASAdditions.h */,
+ B93ACB0324ED1F0300F310DE /* MASViewConstraint.m */,
+ B93ACB0424ED1F0300F310DE /* MASViewAttribute.m */,
+ );
+ path = Masonry;
+ sourceTree = "<group>";
+ };
+ B93ACB0524ED1F0300F310DE /* View */ = {
+ isa = PBXGroup;
+ children = (
+ B93ACB0624ED1F0300F310DE /* HQEditImageActionView.m */,
+ B93ACB0724ED1F0300F310DE /* HQEditImageCaptureView.h */,
+ B93ACB0824ED1F0300F310DE /* HQEditImageEditView.m */,
+ B93ACB0924ED1F0300F310DE /* HQEditImageActionView.h */,
+ B93ACB0A24ED1F0300F310DE /* HQEditImageCaptureView.m */,
+ B93ACB0B24ED1F0300F310DE /* HQEditImageEditView.h */,
+ );
+ path = View;
+ sourceTree = "<group>";
+ };
+ B94D9DA32499C5FD008A7B96 /* HDLONCurtainSeekBar */ = {
+ isa = PBXGroup;
+ children = (
+ B94D9DA52499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.h */,
+ B94D9DAC2499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.m */,
+ B94D9DB12499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.h */,
+ B94D9DA82499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.m */,
+ B94D9DA42499C5FD008A7B96 /* ic_wd_on_curtain_roll_progress_close.png */,
+ B94D9DA62499C5FD008A7B96 /* ic_wd_on_curtain_h_open.png */,
+ B94D9DA72499C5FD008A7B96 /* ic_wd_on_curtain_open.png */,
+ B94D9DA92499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress_close2.png */,
+ B94D9DAA2499C5FD008A7B96 /* ic_wd_on_curtain_roll_bg.png */,
+ B94D9DAB2499C5FD008A7B96 /* ic_wd_on_curtain_h_progress.png */,
+ B94D9DAD2499C5FD008A7B96 /* ic_wd_on_curtain_roll_progress.png */,
+ B94D9DAE2499C5FD008A7B96 /* ic_wd_on_curtain_h_progress_close.png */,
+ B94D9DAF2499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress2.png */,
+ B94D9DB02499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress_close.png */,
+ B94D9DB22499C5FD008A7B96 /* ic_wd_on_curtain_h_bg.png */,
+ B94D9DB32499C5FD008A7B96 /* ic_wd_on_curtain_blinds_progress.png */,
+ );
+ path = HDLONCurtainSeekBar;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 4B74C9CA2320B13D00C4EC2F /* HDLWidgetLibrary */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4B74C9D42320B13D00C4EC2F /* Build configuration list for PBXNativeTarget "HDLWidgetLibrary" */;
+ buildPhases = (
+ 4B74C9C72320B13D00C4EC2F /* Sources */,
+ 4B74C9C82320B13D00C4EC2F /* Frameworks */,
+ 4B74C9C92320B13D00C4EC2F /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = HDLWidgetLibrary;
+ productName = HDLWidgetLibrary;
+ productReference = 4B74C9CB2320B13D00C4EC2F /* libHDLWidgetLibrary.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 4B74C9C32320B13D00C4EC2F /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1020;
+ ORGANIZATIONNAME = JLChen;
+ TargetAttributes = {
+ 4B74C9CA2320B13D00C4EC2F = {
+ CreatedOnToolsVersion = 10.2.1;
+ };
+ };
+ };
+ buildConfigurationList = 4B74C9C62320B13D00C4EC2F /* Build configuration list for PBXProject "HDLWidgetLibrary" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 4B74C9C22320B13D00C4EC2F;
+ productRefGroup = 4B74C9CC2320B13D00C4EC2F /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4B74C9CA2320B13D00C4EC2F /* HDLWidgetLibrary */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4B74C9C72320B13D00C4EC2F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4B74CA142320B29E00C4EC2F /* HDLCoverFlowLayout.m in Sources */,
+ 4B65C7E8237BB5D800E0DC16 /* ScalePointData.m in Sources */,
+ B93ACB1F24ED1F0300F310DE /* View+MASAdditions.m in Sources */,
+ B93ACB2A24ED1F0300F310DE /* UIImageCrop.m in Sources */,
+ B93ACB1E24ED1F0300F310DE /* NSArray+MASAdditions.m in Sources */,
+ 4B9B13BC23741BE500088244 /* HDLRollCurtainSeekBar.m in Sources */,
+ B95B009324AEC2DD0049A516 /* HDLOnWaveSeekbar.m in Sources */,
+ B93ACB1724ED1F0300F310DE /* CropImageUtlis.m in Sources */,
+ 4B74CA122320B29E00C4EC2F /* HDLCoverFlowCell.m in Sources */,
+ 4B74CA172320B29E00C4EC2F /* HDLTouchID.m in Sources */,
+ B93ACB1824ED1F0300F310DE /* HQImageEditViewController.m in Sources */,
+ B93ACB2324ED1F0300F310DE /* HQEditImageActionView.m in Sources */,
+ B93ACB2424ED1F0300F310DE /* HQEditImageEditView.m in Sources */,
+ B93ACB1A24ED1F0300F310DE /* ViewController+MASAdditions.m in Sources */,
+ 4B231B62233C9C650018B9C8 /* HDLPickerView.m in Sources */,
+ B93ACB2124ED1F0300F310DE /* MASViewConstraint.m in Sources */,
+ 4BCCD8022369AE96000EF33F /* HDLUtlisXM.m in Sources */,
+ B93ACB1D24ED1F0300F310DE /* MASLayoutConstraint.m in Sources */,
+ 4BCCD7FF2369AE1D000EF33F /* HDLGestureLockView.m in Sources */,
+ B93ACB2024ED1F0300F310DE /* MASConstraint.m in Sources */,
+ B94D9DB52499C5FD008A7B96 /* HDLOnRollCurtainSeekBar.m in Sources */,
+ B94D9DB42499C5FD008A7B96 /* HDLOnOACCurtainSeekBar.m in Sources */,
+ 4B8890B5239E225500B83519 /* HDLDiyImageSeekBar.m in Sources */,
+ B93ACB2224ED1F0300F310DE /* MASViewAttribute.m in Sources */,
+ B93ACB2524ED1F0300F310DE /* HQEditImageCaptureView.m in Sources */,
+ 4B74CA132320B29E00C4EC2F /* HDLCoverFlow.m in Sources */,
+ 4B74CA112320B29E00C4EC2F /* HDLArcSeekbar.m in Sources */,
+ 4B9B13BB23741BE500088244 /* HDLOACCurtainSeekBar.m in Sources */,
+ B93ACB1924ED1F0300F310DE /* NSLayoutConstraint+MASDebugAdditions.m in Sources */,
+ 4B74CA1B2320B4C800C4EC2F /* ZJPickerView.m in Sources */,
+ B93ACB1C24ED1F0300F310DE /* MASConstraintMaker.m in Sources */,
+ B94D9DA22499C5F3008A7B96 /* HDLDiyArcSeekbar.m in Sources */,
+ B93ACB1B24ED1F0300F310DE /* MASCompositeConstraint.m in Sources */,
+ 4B9B13BF2374220D00088244 /* SeekBarDelegate.m in Sources */,
+ 4B74CA152320B29E00C4EC2F /* HDLWaveSeekBar.m in Sources */,
+ B9A22FE7241CD88200F79DA1 /* HDLDiyImageVerticalSeekBar.m in Sources */,
+ 4B65C7E9237BB5D800E0DC16 /* HDLArcScaleSeekBar.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 4B74C9D22320B13D00C4EC2F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 4B74C9D32320B13D00C4EC2F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 4B74C9D52320B13D00C4EC2F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 259RU5K4MU;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4B74C9D62320B13D00C4EC2F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 259RU5K4MU;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4B74C9C62320B13D00C4EC2F /* Build configuration list for PBXProject "HDLWidgetLibrary" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4B74C9D22320B13D00C4EC2F /* Debug */,
+ 4B74C9D32320B13D00C4EC2F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4B74C9D42320B13D00C4EC2F /* Build configuration list for PBXNativeTarget "HDLWidgetLibrary" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4B74C9D52320B13D00C4EC2F /* Debug */,
+ 4B74C9D62320B13D00C4EC2F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 4B74C9C32320B13D00C4EC2F /* Project object */;
+}
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..156abbc
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:HDLWidgetLibrary.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.h
new file mode 100644
index 0000000..3889e13
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.h
@@ -0,0 +1,29 @@
+//
+// CYAnyCornerRadiusUtil.h
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/12/3.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+NS_ASSUME_NONNULL_BEGIN
+
+typedef struct {
+ CGFloat topLeft;
+ CGFloat topRight;
+ CGFloat bottomLeft;
+ CGFloat bottomRight;
+} CornerRadii;
+@interface CYAnyCornerRadiusUtil : NSObject
+CornerRadii CornerRadiiMake(CGFloat topLeft,CGFloat topRight,CGFloat bottomLeft,CGFloat bottomRight);
+//鍒囧渾瑙掑嚱鏁�
+CGPathRef CYPathCreateWithRoundedRect(CGRect bounds,
+ CornerRadii cornerRadii);
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.m
new file mode 100644
index 0000000..a3a08bb
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CYAnyCornerRadiusUtil/CYAnyCornerRadiusUtil.m
@@ -0,0 +1,68 @@
+//
+// CYAnyCornerRadiusUtil.m
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/12/3.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "CYAnyCornerRadiusUtil.h"
+
+@implementation CYAnyCornerRadiusUtil
+CornerRadii CornerRadiiMake(CGFloat topLeft,CGFloat topRight,CGFloat bottomLeft,CGFloat bottomRight){
+ return (CornerRadii){
+ topLeft,
+ topRight,
+ bottomLeft,
+ bottomRight,
+ };
+}
+//鍒囧渾瑙掑嚱鏁�
+CGPathRef CYPathCreateWithRoundedRect(CGRect bounds,
+ CornerRadii cornerRadii)
+{
+ const CGFloat minX = CGRectGetMinX(bounds);
+ const CGFloat minY = CGRectGetMinY(bounds);
+ const CGFloat maxX = CGRectGetMaxX(bounds);
+ const CGFloat maxY = CGRectGetMaxY(bounds);
+
+ const CGFloat topLeftCenterX = minX + cornerRadii.topLeft;
+ const CGFloat topLeftCenterY = minY + cornerRadii.topLeft;
+
+ const CGFloat topRightCenterX = maxX - cornerRadii.topRight;
+ const CGFloat topRightCenterY = minY + cornerRadii.topRight;
+
+ const CGFloat bottomLeftCenterX = minX + cornerRadii.bottomLeft;
+ const CGFloat bottomLeftCenterY = maxY - cornerRadii.bottomLeft;
+
+ const CGFloat bottomRightCenterX = maxX - cornerRadii.bottomRight;
+ const CGFloat bottomRightCenterY = maxY - cornerRadii.bottomRight;
+ /*
+ path : 璺緞
+ m : 鍙樻崲
+ x y : 鐢诲渾鐨勫渾蹇冪偣
+ radius : 鍦嗙殑鍗婂緞
+ startAngle : 璧峰瑙掑害
+ endAngle 锛� 缁撴潫瑙掑害
+ clockwise : 鏄惁鏄『鏃堕拡
+ void CGPathAddArc(CGMutablePathRef cg_nullable path,
+ const CGAffineTransform * __nullable m,
+ CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle,
+ bool clockwise)
+ */
+ //铏界劧椤烘椂閽堝弬鏁版槸YES锛屽湪iOS涓殑UIView涓紝杩欓噷瀹為檯鏄�嗘椂閽�
+
+ CGMutablePathRef path = CGPathCreateMutable();
+ //椤� 宸�
+ CGPathAddArc(path, NULL, topLeftCenterX, topLeftCenterY,cornerRadii.topLeft, M_PI, 3 * M_PI_2, NO);
+ //椤� 鍙�
+ CGPathAddArc(path, NULL, topRightCenterX , topRightCenterY, cornerRadii.topRight, 3 * M_PI_2, 0, NO);
+ //搴� 鍙�
+ CGPathAddArc(path, NULL, bottomRightCenterX, bottomRightCenterY, cornerRadii.bottomRight,0, M_PI_2, NO);
+ //搴� 宸�
+ CGPathAddArc(path, NULL, bottomLeftCenterX, bottomLeftCenterY, cornerRadii.bottomLeft, M_PI_2,M_PI, NO);
+ CGPathCloseSubpath(path);
+ return path;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.h
new file mode 100755
index 0000000..8203102
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.h
@@ -0,0 +1,58 @@
+//
+// CYAnyCornerRadiusUtil.h
+// ProjectComponentDemo
+//
+// Created by Mr.GCY on 2018/4/23.
+// Copyright 漏 2018骞� Mr.GCY. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+typedef struct {
+ CGFloat topLeft;
+ CGFloat topRight;
+ CGFloat bottomLeft;
+ CGFloat bottomRight;
+} CornerRadii;
+@interface CYAnyCornerRadiusUtil : NSObject
+CornerRadii CornerRadiiMake(CGFloat topLeft,CGFloat topRight,CGFloat bottomLeft,CGFloat bottomRight);
+//鍒囧渾瑙掑嚱鏁�
+CGPathRef CYPathCreateWithRoundedRect(CGRect bounds,
+ CornerRadii cornerRadii);
+/**
+ 鐢绘笎鍙樼嚎
+
+ @param context 涓婁笅鏂�
+ @param components 娓愬彉棰滆壊鏁扮粍
+ @param componentCount 鏁扮粍澶у皬
+ @param width 绾垮
+ @param startPoint 璧峰浣嶇疆
+ @param endPoint 缁撴潫浣嶇疆
+ */
+void drawLinearGradient(CGContextRef cg_nullable context,const CGFloat * cg_nullable components,int componentCount,CGFloat width,CGPoint startPoint,CGPoint endPoint,CGGradientDrawingOptions options);
+/**
+ 鐢荤嚎
+
+ @param context 涓婁笅鏂�
+ @param color 绾块鑹�
+ @param width 绾垮
+ @param startPoint 璧峰浣嶇疆
+ @param endPoint 缁撴潫浣嶇疆
+ */
+void drawLine(CGContextRef cg_nullable context,CGColorRef color,CGFloat width,CGPoint startPoint,CGPoint endPoint);
+
+/**
+ 鐢诲姬绾�
+
+ @param context 涓婁笅鏂�
+ @param color 绾块鑹�
+ @param width 绾垮
+ @param centerPoint 鍦嗗績浣嶇疆
+ @param radius 鍗婂緞
+ @param startAngle 璧峰瑙掑害
+ @param endAngle 缁撴潫瑙掑害
+ @param clockwise 鏄惁闂悎
+ */
+void drawLineArc(CGContextRef cg_nullable context,CGColorRef color,CGFloat width,CGPoint centerPoint,CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise);
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.m
new file mode 100755
index 0000000..07b3c72
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CYAnyCornerRadiusUtil.m
@@ -0,0 +1,108 @@
+//
+// CYAnyCornerRadiusUtil.m
+// ProjectComponentDemo
+//
+// Created by Mr.GCY on 2018/4/23.
+// Copyright 漏 2018骞� Mr.GCY. All rights reserved.
+//
+
+#import "CYAnyCornerRadiusUtil.h"
+
+@implementation CYAnyCornerRadiusUtil
+CornerRadii CornerRadiiMake(CGFloat topLeft,CGFloat topRight,CGFloat bottomLeft,CGFloat bottomRight){
+ return (CornerRadii){
+ topLeft,
+ topRight,
+ bottomLeft,
+ bottomRight,
+ };
+}
+//鍒囧渾瑙掑嚱鏁�
+CGPathRef CYPathCreateWithRoundedRect(CGRect bounds,
+ CornerRadii cornerRadii)
+{
+ const CGFloat minX = CGRectGetMinX(bounds);
+ const CGFloat minY = CGRectGetMinY(bounds);
+ const CGFloat maxX = CGRectGetMaxX(bounds);
+ const CGFloat maxY = CGRectGetMaxY(bounds);
+
+ const CGFloat topLeftCenterX = minX + cornerRadii.topLeft;
+ const CGFloat topLeftCenterY = minY + cornerRadii.topLeft;
+
+ const CGFloat topRightCenterX = maxX - cornerRadii.topRight;
+ const CGFloat topRightCenterY = minY + cornerRadii.topRight;
+
+ const CGFloat bottomLeftCenterX = minX + cornerRadii.bottomLeft;
+ const CGFloat bottomLeftCenterY = maxY - cornerRadii.bottomLeft;
+
+ const CGFloat bottomRightCenterX = maxX - cornerRadii.bottomRight;
+ const CGFloat bottomRightCenterY = maxY - cornerRadii.bottomRight;
+ /*
+ path : 璺緞
+ m : 鍙樻崲
+ x y : 鐢诲渾鐨勫渾蹇冪偣
+ radius : 鍦嗙殑鍗婂緞
+ startAngle : 璧峰瑙掑害
+ endAngle 锛� 缁撴潫瑙掑害
+ clockwise : 鏄惁鏄『鏃堕拡
+ void CGPathAddArc(CGMutablePathRef cg_nullable path,
+ const CGAffineTransform * __nullable m,
+ CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle,
+ bool clockwise)
+ */
+ //铏界劧椤烘椂閽堝弬鏁版槸YES锛屽湪iOS涓殑UIView涓紝杩欓噷瀹為檯鏄�嗘椂閽�
+
+ CGMutablePathRef path = CGPathCreateMutable();
+ //椤� 宸�
+ CGPathAddArc(path, NULL, topLeftCenterX, topLeftCenterY,cornerRadii.topLeft, M_PI, 3 * M_PI_2, NO);
+ //椤� 鍙�
+ CGPathAddArc(path, NULL, topRightCenterX , topRightCenterY, cornerRadii.topRight, 3 * M_PI_2, 0, NO);
+ //搴� 鍙�
+ CGPathAddArc(path, NULL, bottomRightCenterX, bottomRightCenterY, cornerRadii.bottomRight,0, M_PI_2, NO);
+ //搴� 宸�
+ CGPathAddArc(path, NULL, bottomLeftCenterX, bottomLeftCenterY, cornerRadii.bottomLeft, M_PI_2,M_PI, NO);
+ CGPathCloseSubpath(path);
+ return path;
+}
+//鐢绘笎鍙樼嚎
+void drawLinearGradient(CGContextRef cg_nullable context,const CGFloat * cg_nullable components,int componentCount,CGFloat width,CGPoint startPoint,CGPoint endPoint,CGGradientDrawingOptions options){
+ CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+ CGFloat colors[componentCount];
+ for (int i = 0; i < componentCount; i++) {
+ colors[i] = components[i];
+ }
+ CGGradientRef gradient = CGGradientCreateWithColorComponents
+ (rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));//褰㈡垚姊舰锛屾笎鍙樼殑鏁堟灉
+ CGColorSpaceRelease(rgb);
+ CGContextSaveGState(context);
+
+ CGContextMoveToPoint(context, startPoint.x, startPoint.y);
+ CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
+ CGContextSetLineWidth(context, width);
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+
+ //gradient娓愬彉棰滆壊,startPoint寮�濮嬫笎鍙樼殑璧峰浣嶇疆,endPoint缁撴潫鍧愭爣,options寮�濮嬪潗鏍囦箣鍓峯r寮�濮嬩箣鍚庡紑濮嬫笎鍙�
+ CGContextDrawLinearGradient(context, gradient,startPoint ,endPoint,options);
+ CGContextRestoreGState(context);// 鎭㈠鍒颁箣鍓嶇殑context
+
+ CGGradientRelease(gradient);
+}
+//鐢荤嚎
+void drawLine(CGContextRef cg_nullable context,CGColorRef color,CGFloat width,CGPoint startPoint,CGPoint endPoint){
+ CGContextMoveToPoint(context, startPoint.x , startPoint.y);
+ CGContextAddLineToPoint(context, endPoint.x,endPoint.y);
+ CGContextSetLineWidth(context, width);
+ CGContextSetStrokeColorWithColor(context, color);
+ CGContextDrawPath(context, kCGPathStroke);
+}
+//鐢诲姬绾�
+void drawLineArc(CGContextRef cg_nullable context,CGColorRef color,CGFloat width,CGPoint centerPoint,CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise){
+ CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, startAngle, endAngle, clockwise);
+ //鍒掔嚎瀹藉害
+ CGContextSetLineWidth(context, width);
+ //鍒掔嚎棰滆壊
+ CGContextSetStrokeColorWithColor(context, color);
+ CGContextDrawPath(context, kCGPathStroke);
+}
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.h
new file mode 100755
index 0000000..c956890
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.h
@@ -0,0 +1,33 @@
+//
+// CropImageController.h
+// CropImage
+//
+// Created by limuyun on 2017/1/10.
+// Copyright 漏 2017骞� biiway. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@protocol CropImageDelegate <NSObject>
+
+//- (void)cropImageDidFinishedWithImage:(UIImage *)image bSuccess:(BOOL)bSuccess;
+
+- (void)cropImageDidFinishedWithImage:(NSString *)imageName bSuccess:(BOOL)bSuccess;
+
+//- (void)cropImageDidFinishedWithImage:(NSString *)image;
+
+@end
+
+@interface CropImageController : UIViewController
+
+@property (nonatomic, weak) id <CropImageDelegate> delegate;
+//鍦嗗舰瑁佸壀锛岄粯璁O;
+@property (nonatomic, assign) BOOL ovalClip;
+@property (nonatomic, strong) NSString* mCropFileName;
+
+@property (nonatomic, assign) int mRATIO_X;
+@property (nonatomic, assign) int mRATIO_Y;
+
+
+- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate;
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.m
new file mode 100755
index 0000000..b13909b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageController.m
@@ -0,0 +1,312 @@
+//
+// CropImageController.m
+// CropImage
+//
+// Created by limuyun on 2017/1/10.
+// Copyright 漏 2017骞� biiway. All rights reserved.
+//
+
+#import "CropImageController.h"
+//#import "UIImage+Crop.h"
+#import "GlobalUtlis.h"
+#import "UIImageCrop.h"
+
+#define ScreenWidth [UIScreen mainScreen].bounds.size.width
+#define ScreenHeight [UIScreen mainScreen].bounds.size.height
+@interface CropImageController ()<UIScrollViewDelegate>
+@property (nonatomic, strong) UIScrollView * scrollView;
+@property (nonatomic, strong) UIImageView * imageView;
+@property (nonatomic, strong) UIImage * originalImage;
+@property (nonatomic, strong) NSString* mCropPicturePath;
+
+//extern int Widget_LanguageID;
+
+@end
+
+@implementation CropImageController{
+
+ NSString * textCancel;
+ NSString * textSelect;
+}
+- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate {
+ self = [super init];
+ if (self) {
+ _delegate = delegate;
+ _originalImage = originalImage;
+ }
+ return self;
+}
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+ self.view.backgroundColor = [UIColor blackColor];
+ self.automaticallyAdjustsScrollViewInsets = NO;
+ [self initLlanguage];
+
+ if(_mRATIO_X <= 0){
+ _mRATIO_X = 1;
+ }
+ if(_mRATIO_Y <= 0){
+ _mRATIO_Y = 1;
+ }
+
+ CGFloat heightN = ScreenWidth*_mRATIO_Y/_mRATIO_X;
+
+ CGFloat height = (ScreenHeight - heightN)/2.0;
+ _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, height ,ScreenWidth, heightN)];
+ _scrollView.bouncesZoom = YES;
+ _scrollView.minimumZoomScale = 1;
+ _scrollView.maximumZoomScale = 3;
+ _scrollView.zoomScale = 1;
+ _scrollView.delegate = self;
+ _scrollView.layer.masksToBounds = NO;
+ _scrollView.showsHorizontalScrollIndicator = NO;
+ _scrollView.showsVerticalScrollIndicator = NO;
+ _scrollView.layer.borderWidth = 1.5;
+ _scrollView.layer.borderColor = [UIColor whiteColor].CGColor;
+ if (_ovalClip) {
+ _scrollView.layer.cornerRadius = ScreenWidth/2.0;
+ }
+ self.view.layer.masksToBounds = YES;
+ if (_originalImage) {
+ _imageView = [[UIImageView alloc] initWithImage:_originalImage];
+ CGFloat img_width = ScreenWidth;
+ CGFloat img_height = _originalImage.size.height * (img_width/_originalImage.size.width);
+ CGFloat img_y= (img_height - self.view.bounds.size.width)/2.0;
+ _imageView.frame = CGRectMake(0,0, img_width, img_height);
+ _imageView.userInteractionEnabled = YES;
+ [_scrollView addSubview:_imageView];
+
+
+ _scrollView.contentSize = CGSizeMake(img_width, img_height);
+ _scrollView.contentOffset = CGPointMake(0, img_y);
+ [self.view addSubview:_scrollView];
+ }
+
+ if(_mCropFileName == nil || _mCropFileName.length == 0 ){
+ _mCropFileName = @"hdl_headPicture";
+ }
+
+
+ [self userInterface];
+}
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [self.navigationController setNavigationBarHidden:YES];
+}
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [self.navigationController setNavigationBarHidden:NO];
+}
+- (void)userInterface {
+
+ CGRect cropframe = _scrollView.frame;
+ UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds cornerRadius:0];
+ UIBezierPath * cropPath = [UIBezierPath bezierPathWithRoundedRect:cropframe cornerRadius:0];
+ if (_ovalClip) {
+ cropPath = [UIBezierPath bezierPathWithOvalInRect:cropframe];
+ }
+ [path appendPath:cropPath];
+
+ CAShapeLayer * layer = [[CAShapeLayer alloc] init];
+ layer.fillColor = [UIColor colorWithRed:.0 green:.0 blue:.0 alpha:0.5].CGColor;
+ layer.fillRule=kCAFillRuleEvenOdd;
+ layer.path = path.CGPath;
+ [self.view.layer addSublayer:layer];
+
+ UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height - 46, self.view.bounds.size.width, 46)];
+ view.backgroundColor = [UIColor colorWithRed:30/255.0 green:30/255.0 blue:30/255.0 alpha:0.7];
+ [self.view addSubview:view];
+
+ UIButton * canncelBtn = [UIButton buttonWithType:UIButtonTypeSystem];
+ // [canncelBtn setBackgroundImage:[UIImage imageNamed:@"ic_widget_cancel"] forState:UIControlStateNormal];
+ canncelBtn.frame = CGRectMake(0, 0, 60, 44);
+ canncelBtn.titleLabel.font = [UIFont systemFontOfSize:16];
+ // [canncelBtn setTitle: NSLocalizedString(@"action_cancel", @"") forState:UIControlStateNormal];
+ [canncelBtn setTitle:textCancel forState:UIControlStateNormal];
+ [canncelBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
+ [canncelBtn addTarget:self action:@selector(cancelBtnClick) forControlEvents:UIControlEventTouchUpInside];
+
+
+
+ [view addSubview:canncelBtn];
+
+ UIButton * doneBtn = [UIButton buttonWithType:UIButtonTypeSystem];
+ doneBtn.frame = CGRectMake([UIScreen mainScreen].bounds.size.width - 60, 0, 60, 44);
+ // [doneBtn setBackgroundImage:[UIImage imageNamed:@"ic_widget_cancel"] forState:UIControlStateNormal];
+ doneBtn.titleLabel.font = [UIFont systemFontOfSize:16];
+ [doneBtn setTitle:textSelect forState:UIControlStateNormal];
+ [doneBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
+ [doneBtn addTarget:self action:@selector(doneBtnClick) forControlEvents:UIControlEventTouchUpInside];
+ [view addSubview:doneBtn];
+
+
+ // if(Widget_LanguageID == 1){
+ // [canncelBtn setTitle: @"Cancel" forState:UIControlStateNormal];
+ // [doneBtn setTitle: @"Save" forState:UIControlStateNormal];
+ // }else{
+ // [canncelBtn setTitle: @"鍙栨秷" forState:UIControlStateNormal];
+ // [doneBtn setTitle: @"淇濆瓨" forState:UIControlStateNormal];
+ // }
+}
+
+-(void)initLlanguage{
+ NSString *languageName = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0];
+ // 绠�浣撲腑鏂�
+ if ([languageName rangeOfString:@"zh-Hans"].location != NSNotFound) {
+ textCancel = @"鍙栨秷";
+ textSelect = @"閫夊彇";
+ }else{
+ textCancel = @"Cancel";
+ textSelect = @"Select";
+ }
+}
+
+#pragma mark -- UIScrollViewDelegate
+- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
+ return self.imageView;
+}
+- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
+ //璋冩暣浣嶇疆
+ [self centerContent];
+}
+- (void)centerContent {
+ CGRect imageViewFrame = _imageView.frame;
+
+ CGRect scrollBounds = CGRectMake(0, 0, ScreenWidth, ScreenWidth);
+ if (imageViewFrame.size.height > scrollBounds.size.height) {
+ imageViewFrame.origin.y = 0.0f;
+ }else {
+ imageViewFrame.origin.y = (scrollBounds.size.height - imageViewFrame.size.height) / 2.0;
+ }
+ if (imageViewFrame.size.width < scrollBounds.size.width) {
+ imageViewFrame.origin.x = (scrollBounds.size.width - imageViewFrame.size.width) /2.0;
+ }else {
+ imageViewFrame.origin.x = 0.0f;
+ }
+ _imageView.frame = imageViewFrame;
+}
+- (void)cancelBtnClick{
+ if (_delegate && [_delegate respondsToSelector:@selector(cropImageDidFinishedWithImage:bSuccess:)]) {
+ [_delegate cropImageDidFinishedWithImage:nil bSuccess:NO];
+ }
+ // [self.navigationController popViewControllerAnimated:YES];
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+- (UIImage *)cropImage {
+ CGPoint offset = _scrollView.contentOffset;
+ //鍥剧墖缂╂斁姣斾緥
+ CGFloat zoom = _imageView.frame.size.width/_originalImage.size.width;
+ //瑙嗙綉鑶滃睆骞曞�嶆暟鐩稿叧
+ zoom = zoom / [UIScreen mainScreen].scale;
+
+ CGFloat width = _scrollView.frame.size.width;
+ CGFloat height = _scrollView.frame.size.height;
+ if (_imageView.frame.size.height < _scrollView.frame.size.height) {//澶儢浜�,鍙栦腑闂撮儴鍒�
+ offset = CGPointMake(offset.x + (width - _imageView.frame.size.height)/2.0, 0);
+ width = height = _imageView.frame.size.height;
+ }
+
+ CGRect rec = CGRectMake(offset.x/zoom, offset.y/zoom,width/zoom,height/zoom);
+ CGImageRef imageRef =CGImageCreateWithImageInRect([_originalImage CGImage],rec);
+ UIImage * image = [[UIImage alloc]initWithCGImage:imageRef];
+
+ CGImageRelease(imageRef);
+ if (_ovalClip) {
+ image = [UIImageCrop ovalClip:image];
+
+ // image = zipNSDataWithImage
+ }
+ image = [self compressImageSize:image toByte:200*1024];
+
+ return image;
+}
+
+-(NSString*)saveImage{
+ NSString* _mCropPicturePath = @"";
+ NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
+
+ NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:
+ [NSString stringWithFormat:@"%@%@", _mCropFileName,@".Png"]]; // 淇濆瓨鏂囦欢鐨勫悕绉�
+
+ BOOL result = [UIImagePNGRepresentation([self cropImage])writeToFile:filePath atomically:YES]; // 淇濆瓨鎴愬姛浼氳繑鍥瀁ES
+ if (result == YES) {
+ _mCropPicturePath = filePath;
+ NSLog(@"淇濆瓨鎴愬姛");
+ }else{
+ _mCropPicturePath = @"";
+ }
+ return _mCropPicturePath;
+}
+
+- (void)doneBtnClick{
+ NSString* saveSuccessath = [self saveImage];
+ BOOL saveSuccess = NO;
+ if(![saveSuccessath isEqualToString:@""]){
+ saveSuccess = YES;
+ }
+
+ if (_delegate && [_delegate respondsToSelector:@selector(cropImageDidFinishedWithImage:bSuccess:)]) {
+
+ [_delegate cropImageDidFinishedWithImage:saveSuccessath bSuccess:saveSuccess];
+ }
+ // [self.navigationController popViewControllerAnimated:YES];
+
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+
+
+
+#pragma mark - UIStatusBarStyle
+- (UIStatusBarStyle)preferredStatusBarStyle {
+ return UIStatusBarStyleLightContent;
+}
+
+- (BOOL)prefersStatusBarHidden {
+ return NO;
+}
+
+//-(NSData *)zipNSDataWithImage:(UIImage *)sourceImage{
+// //杩涜鍥惧儚鐨勭敾闈㈣川閲忓帇缂�
+// NSData *data=UIImageJPEGRepresentation(sourceImage, 1.0);
+// if (data.length>100*1024) {
+// if (data.length>1024*1024) {//1M浠ュ強浠ヤ笂
+// data=UIImageJPEGRepresentation(sourceImage, 0.5);
+// if (data.length>1024*1024) {//1M浠ュ強浠ヤ笂
+// data=UIImageJPEGRepresentation(sourceImage, 0.5);
+// }
+// }else if (data.length>512*1024) {//0.5M-1M
+// data=UIImageJPEGRepresentation(sourceImage, 0.6);
+// }else if (data.length>200*1024) {
+// //0.25M-0.5M
+// data=UIImageJPEGRepresentation(sourceImage, 0.7);
+// }
+// }
+// return data;
+//}
+
+//鍥剧墖鍘嬬缉
+- (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength {
+ UIImage *resultImage = image;
+ NSData *data = UIImageJPEGRepresentation(resultImage, 1);
+ NSUInteger lastDataLength = 0;
+ while (data.length > maxLength && data.length != lastDataLength) {
+ lastDataLength = data.length;
+ CGFloat ratio = (CGFloat)maxLength / data.length;
+ CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
+ (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
+ UIGraphicsBeginImageContext(size);
+ // Use image to draw (drawInRect:), image is larger but more compression time
+ // Use result image to draw, image is smaller but less compression time
+ [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
+ resultImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ data = UIImageJPEGRepresentation(resultImage, 1);
+ }
+ return resultImage;
+}
+
+
+@end
+
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.h
new file mode 100644
index 0000000..cab25c4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.h
@@ -0,0 +1,33 @@
+//
+// CropImageUtlis.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/18.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+//@protocol SaveImageCallBackDelegate <NSObject>
+//
+//-(void)SaveImageCallBackUtlis:(NSString *)imagePathName;
+//
+//@end
+
+@interface CropImageUtlis : NSObject
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int openType;
+
+//@property (nonatomic,weak) id<SaveImageCallBackDelegate> mSaveImageCallBackDelegate;
+
+
+- (instancetype)initWithController:(UIViewController*)mUIViewController openType:(int)openType fileName:(NSString*)fileName mRATIO_X:(int)mRATIO_X mRATIO_Y:(int)mRATIO_Y callBackBlock:(void (^)(NSString *))callBackBlock;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.m
new file mode 100644
index 0000000..e53ed31
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/CropImageUtlis.m
@@ -0,0 +1,165 @@
+//
+// CropImageUtlis.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/18.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "CropImageUtlis.h"
+//#import "UIImage+Crop.h"
+//#import "CropImageController.h"
+#import "UIImageCrop.h"
+#import "HQImageEditViewController.h"
+
+#define WEAKSELF_AT __weak __typeof(&*self)weakSelf_AT = self;
+
+@interface CropImageUtlis ()<HQImageEditViewControllerDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
+
+@property (nonatomic, strong) UIViewController * rootViewController;
+@property (nonatomic, strong) NSString *mCropPicturePath; //鍥剧墖璺緞
+@property (nonatomic, strong) NSString *mCropFileName; //鍥剧墖鍛藉悕
+
+
+@property (nonatomic, assign) int mRATIO_X;
+@property (nonatomic, assign) int mRATIO_Y;
+
+@property(nonatomic, copy) void (^didSaveImageCallBackBlock)(NSString *);
+
+@end
+
+@implementation CropImageUtlis
+
+
+
+- (instancetype)initWithController:(UIViewController*)mUIViewController openType:(int)openType fileName:(NSString*)fileName mRATIO_X:(int)mRATIO_X mRATIO_Y:(int)mRATIO_Y callBackBlock:(void (^)(NSString *))callBackBlock{
+ self = [super init];
+ if(self){
+ _rootViewController = mUIViewController;
+ _openType = openType;
+ _didSaveImageCallBackBlock = callBackBlock;
+ if(fileName == nil || fileName.length == 0 ){
+ _mCropFileName = @"hdl_headPicture";
+ }else{
+ _mCropFileName = fileName;
+ }
+
+ _mRATIO_X = mRATIO_X;
+ _mRATIO_Y = mRATIO_Y;
+
+ if(_openType == 101){
+ [self openTypeCamera];
+ }else{
+ [self openTypePhotoLibrary];
+ }
+ }
+ return self;
+
+
+}
+
+#pragma mark - 涓婁紶澶村儚
+-(void)openTypeCamera{
+ // WEAKSELF_AT
+ UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
+ imagePickerController.delegate = self;
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
+ if(@available(iOS 13.0, *)) {
+ imagePickerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
+ }
+ [_rootViewController presentViewController:imagePickerController animated:YES completion:nil];
+
+
+ // _mUIImagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
+ //
+ // [_rootViewController presentViewController:_mUIImagePickerController animated:YES completion:nil];
+}
+
+-(void)openTypePhotoLibrary;{
+ // WEAKSELF_AT
+ UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
+ imagePickerController.delegate = self;
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+ if(@available(iOS 13.0, *)) {
+ imagePickerController.modalPresentationStyle = UIModalPresentationOverFullScreen;
+ }
+ [_rootViewController presentViewController:imagePickerController animated:YES completion:nil];
+ //
+ // _mUIImagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+ //
+ // [_rootViewController presentViewController:_mUIImagePickerController animated:YES completion:nil];
+
+}
+
+#pragma mark -- UIImagePickerControllerDelegate
+- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
+ [picker dismissViewControllerAnimated:YES completion:nil];
+ // [picker dismissViewControllerAnimated:YES completion:^{
+ //
+ // }];
+ // [picker dismissViewControllerAnimated:YES completion:^{
+ // UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
+ // CropImageController * con = [[CropImageController alloc] initWithImage:image delegate:self];
+ // [self.navigationController pushViewController:con animated:YES];
+ // }];
+
+ UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
+ CGFloat width = [UIScreen mainScreen].bounds.size.width;
+ CGFloat height = image.size.height * (width/image.size.width);
+// UIImage * orImage = [image resizeImageWithSize:CGSizeMake(width, height)];
+
+ UIImage * orImage = [UIImageCrop resizeImageWithSize:image newSize:CGSizeMake(width, height)];
+
+ HQImageEditViewController * mCropImageController = [[HQImageEditViewController alloc] initWithImage:orImage delegate:self];
+ mCropImageController.mCropFileName = _mCropFileName;
+ mCropImageController.mRATIO_X = _mRATIO_X;
+ mCropImageController.mRATIO_Y = _mRATIO_Y;
+ mCropImageController.maskViewAnimation = YES;
+
+// [_rootViewController.navigationController pushViewController:mCropImageController animated:YES];
+ if(@available(iOS 13.0, *)) {
+ mCropImageController.modalPresentationStyle = UIModalPresentationOverFullScreen;
+ }
+
+ [_rootViewController presentViewController:mCropImageController animated:YES completion:nil];
+}
+
+// 鍙栨秷鍥剧墖閫夋嫨璋冪敤姝ゆ柟娉�
+- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
+ [picker dismissViewControllerAnimated:YES completion:nil];
+ [self backAction:NO];
+}
+
+
+
+-(void)backAction:(BOOL)bSuccess{
+ if(bSuccess){
+ // if(self.mSaveImageCallBackDelegate != NULL){
+ // [self.mSaveImageCallBackDelegate SaveImageCallBackUtlis:_mCropPicturePath];
+ //// NSLog(@"鍏抽棴椤甸潰");
+ // }
+ if(_didSaveImageCallBackBlock){
+ _didSaveImageCallBackBlock(_mCropPicturePath);
+ }
+ }else{
+ if(_didSaveImageCallBackBlock){
+ _didSaveImageCallBackBlock(nil);
+ }
+ }
+ // [_rootViewController.navigationController popViewControllerAnimated:YES];
+}
+
+
+#pragma mark -- CropImageDelegate
+- (void)cropImageDidFinishedWithImage:(NSString *)imageName bSuccess:(BOOL)bSuccess{
+
+ if(bSuccess){
+ _mCropPicturePath = imageName;
+ [self backAction:bSuccess];
+ }else{
+ [self backAction:bSuccess];
+ }
+
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.h
new file mode 100644
index 0000000..2c87d58
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.h
@@ -0,0 +1,25 @@
+//
+// GlobalUtlis.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/21.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+/**
+ 璇█ID
+ */
+//int Widget_LanguageID;
+
+@interface GlobalUtlis : NSObject
+
+//+ (void)setLanguageID:(int )LanguageID;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.m
new file mode 100644
index 0000000..eecedce
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/GlobalUtlis.m
@@ -0,0 +1,17 @@
+//
+// GlobalUtlis.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/21.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "GlobalUtlis.h"
+
+@implementation GlobalUtlis
+
+
+//+ (void)setLanguageID:(int )mLanguageID{
+//// _LanguageID = mLanguageID;
+//}
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.h
new file mode 100755
index 0000000..0a60241
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.h
@@ -0,0 +1,42 @@
+//
+// HQImageEditViewController.h
+// CivilAviation
+//
+// Created by iOS on 2019/3/29.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class HQImageEditViewController;
+@protocol HQImageEditViewControllerDelegate <NSObject>
+- (void)cropImageDidFinishedWithImage:(NSString *)imageName bSuccess:(BOOL)bSuccess;
+@end
+
+@interface HQImageEditViewController : UIViewController
+@property (nonatomic, weak) id <HQImageEditViewControllerDelegate> delegate;
+@property (nonatomic, strong) NSString* mCropFileName;
+
+@property (nonatomic, assign) int mRATIO_X;
+@property (nonatomic, assign) int mRATIO_Y;
+
+/**
+ 鎴彇鍘熷浘
+ */
+@property (nonatomic, strong) UIImage *originImage;
+/**
+ 閫夊彇妗唖ize
+ */
+@property (nonatomic, assign) CGSize editViewSize;
+/**
+ 钂欏眰鍔ㄧ敾 榛樿no
+ */
+@property (nonatomic, assign) BOOL maskViewAnimation;
+
+- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.m
new file mode 100755
index 0000000..1e652ae
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/HQImageEditViewController.m
@@ -0,0 +1,426 @@
+//
+// HQImageEditViewController.m
+// CivilAviation
+//
+// Created by iOS on 2019/3/29.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import "HQImageEditViewController.h"
+#import "HQEditImageActionView.h"
+#import "HQEditImageCaptureView.h"
+#import "HQEditImageEditView.h"
+#import "Masonry.h"
+
+static inline UIEdgeInsets hq_safeAreaInset() {
+ if (@available(iOS 11.0, *)) {
+ return [UIApplication sharedApplication].keyWindow.safeAreaInsets;
+ }
+ return UIEdgeInsetsZero;
+}
+
+@interface HQImageEditViewController () <UIScrollViewDelegate, HQEditImageActionViewDelegate, HQEditImageEditViewDelegate>
+
+@property (nonatomic, strong) HQEditImageCaptureView *captureView;
+
+@property (nonatomic, strong) UIScrollView *scrollView;
+@property (nonatomic, strong) UIImageView *imageView;
+
+@property (nonatomic, strong) HQEditImageActionView *actionView;
+@property (nonatomic, strong) HQEditImageEditView *editView;
+
+@property (nonatomic, assign) NSInteger rotateTimes;
+@property (nonatomic, assign) CGSize imageViewOriginSize;
+
+@property (nonatomic, assign) BOOL showNavigationBarWhenPop;
+//@property (nonatomic, strong) UIImage * originalImage;
+@property (nonatomic, strong) NSString* mCropPicturePath;
+
+
+@end
+
+@implementation HQImageEditViewController{
+ NSString * textCancel;
+ NSString * textSelect;
+}
+
+- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate {
+ self = [super init];
+ if (self) {
+ _delegate = delegate;
+ _originImage = originalImage;
+ }
+ return self;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // self.hq_navigationBarHide = YES;
+ self.view.backgroundColor = UIColor.blackColor;
+ self.view.layer.masksToBounds = YES;
+
+ [self initLlanguage];
+ [self initData];
+
+ [self.view addSubview:self.captureView];
+ [self.captureView addSubview:self.scrollView];
+ [self.scrollView addSubview:self.imageView];
+ [self.view addSubview:self.actionView];
+ [self.view addSubview:self.editView];
+
+ [self.actionView.cancelButton setTitle:textCancel forState:UIControlStateNormal];
+ [self.actionView.finishButton setTitle:textSelect forState:UIControlStateNormal];
+
+}
+
+-(void)initData{
+ if(_mRATIO_X <= 0){
+ _mRATIO_X = 1;
+ }
+ if(_mRATIO_Y <= 0){
+ _mRATIO_Y = 1;
+ }
+ if(_mCropFileName == nil || _mCropFileName.length == 0 ){
+ _mCropFileName = @"hdl_headPicture";
+ }
+ CGFloat height = self.view.bounds.size.width*_mRATIO_Y/_mRATIO_X;
+ _editViewSize = CGSizeMake(self.view.bounds.size.width, height);
+
+}
+
+-(void)initLlanguage{
+ NSString *languageName = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0];
+ // 绠�浣撲腑鏂�
+ if ([languageName rangeOfString:@"zh-Hans"].location != NSNotFound) {
+ textCancel = @"鍙栨秷";
+ textSelect = @"閫夊彇";
+ }else{
+ textCancel = @"Cancel";
+ textSelect = @"Select";
+ }
+}
+
+- (void)viewDidLayoutSubviews {
+ [super viewDidLayoutSubviews];
+
+ [self.captureView mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.width.equalTo(@(self.editViewSize.width));
+ make.height.equalTo(@(self.editViewSize.height));
+ make.top.equalTo(@((CGFloat)(hq_safeAreaInset().top + self.topSpace)));
+ make.centerX.equalTo(@0);
+ }];
+
+ [self.actionView mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.left.right.bottom.equalTo(@0);
+ make.height.equalTo(@(49*2 + hq_safeAreaInset().bottom));
+ }];
+
+ [self.editView mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.width.equalTo(@(self.editViewSize.width));
+ make.height.equalTo(@(self.editViewSize.height));
+ make.top.equalTo(@((CGFloat)(hq_safeAreaInset().top + self.topSpace)));
+ make.centerX.equalTo(@0);
+ }];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+
+ // if (self.navigationController.isNavigationBarHidden == NO) {
+ // [self.navigationController setNavigationBarHidden:YES animated:YES];
+ // self.showNavigationBarWhenPop = YES;
+ // }
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+
+ // if (self.showNavigationBarWhenPop) {
+ // [self.navigationController setNavigationBarHidden:NO animated:YES];
+ // }
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+
+ [self.editView maskViewShowWithDuration:.2f];
+// self.navigationController.interactivePopGestureRecognizer.enabled = NO;
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+
+// self.navigationController.interactivePopGestureRecognizer.enabled = YES;
+}
+
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+ return UIInterfaceOrientationMaskPortrait;
+}
+
+#pragma mark - UIScrollViewDelegate
+- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
+ [self.editView maskViewHideWithDuration:.2f];
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+ [self.editView maskViewShowWithDuration:.2f];
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+ if (!decelerate) {
+ [self.editView maskViewShowWithDuration:.2f];
+ }
+}
+
+- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
+ [self.editView maskViewHideWithDuration:.2f];
+}
+
+- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
+ return self.imageView;
+}
+
+- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
+ [self.scrollView setZoomScale:scale animated:NO];
+ [self.editView maskViewShowWithDuration:.2f];
+}
+
+#pragma mark - HQEditImageActionViewDelegate
+- (void)action:(HQEditImageActionView *)action didClickButton:(UIButton *)button atIndex:(NSInteger)index {
+ if (index == 0) { // 鏃嬭浆
+ self.rotateTimes ++;
+ self.captureView.rotateTimes = self.rotateTimes;
+ [self rotateScrollView:self.rotateTimes];
+ } else if (index == 1) { // 鍙栨秷
+ // if ([self.delegate respondsToSelector:@selector(editControllerDidClickCancel:)]) {
+ // [self.delegate editControllerDidClickCancel:self];
+ // }
+ //
+ if (_delegate && [_delegate respondsToSelector:@selector(cropImageDidFinishedWithImage:bSuccess:)]) {
+ [_delegate cropImageDidFinishedWithImage:nil bSuccess:NO];
+ }
+ // [self.navigationController popViewControllerAnimated:YES];
+ [self dismissViewControllerAnimated:YES completion:nil];
+ } else if (index == 2) { // 杩樺師
+ [self originAll];
+ } else if (index == 3) { // 瀹屾垚
+ if (self.scrollView.isDragging || self.scrollView.isDecelerating || self.scrollView.isZoomBouncing) {
+ return;
+ }
+ //
+ UIImage *image = [self.captureView captureImage];
+ // UIImage *originImage = [self.captureView captureOriginalImage];
+ UIImage *originImage2 = [self compressImageSize:image toByte:200*1024];
+ NSString* saveSuccessath = [self saveImage:originImage2];
+ BOOL saveSuccess = NO;
+ if(![saveSuccessath isEqualToString:@""]){
+ saveSuccess = YES;
+ }
+
+
+ if (_delegate && [_delegate respondsToSelector:@selector(cropImageDidFinishedWithImage:bSuccess:)]) {
+ [_delegate cropImageDidFinishedWithImage:saveSuccessath bSuccess:saveSuccess];
+ }
+
+ [self dismissViewControllerAnimated:YES completion:nil];
+ }
+}
+
+
+
+//鍥剧墖鍘嬬缉
+- (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength {
+ UIImage *resultImage = image;
+ NSData *data = UIImageJPEGRepresentation(resultImage, 1);
+ NSUInteger lastDataLength = 0;
+ while (data.length > maxLength && data.length != lastDataLength) {
+ lastDataLength = data.length;
+ CGFloat ratio = (CGFloat)maxLength / data.length;
+ CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
+ (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
+ UIGraphicsBeginImageContext(size);
+ // Use image to draw (drawInRect:), image is larger but more compression time
+ // Use result image to draw, image is smaller but less compression time
+ [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
+ resultImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ data = UIImageJPEGRepresentation(resultImage, 1);
+ }
+ return resultImage;
+}
+
+
+
+
+-(NSString*)saveImage:(UIImage*)mImage{
+ NSString* _mCropPicturePath = @"";
+ NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
+
+ NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:
+ [NSString stringWithFormat:@"%@%@", _mCropFileName, @".Png"]]; // 淇濆瓨鏂囦欢鐨勫悕绉�
+
+ BOOL result = [UIImagePNGRepresentation(mImage)writeToFile:filePath atomically:YES]; // 淇濆瓨鎴愬姛浼氳繑鍥瀁ES
+ if (result == YES) {
+ _mCropPicturePath = filePath;
+ NSLog(@"淇濆瓨鎴愬姛");
+ }else{
+ _mCropPicturePath = @"";
+ }
+ return _mCropPicturePath;
+}
+
+
+
+#pragma mark - HQEditImageEditViewDelegate
+- (void)editView:(HQEditImageEditView *)editView anchorPointIndex:(NSInteger)anchorPointIndex rect:(CGRect)rect {
+ CGRect imageEditRect = [self.captureView convertRect:rect toView:self.imageView];
+ [self.scrollView zoomToRect:imageEditRect animated:YES];
+}
+
+#pragma mark - private method
+- (void)rotateScrollView:(NSInteger)times {
+ self.view.userInteractionEnabled = NO;
+ [UIView animateWithDuration:.3f animations:^{
+ self.scrollView.transform = CGAffineTransformRotate(self.scrollView.transform, -M_PI_2);
+ } completion:^(BOOL finished) {
+ if (self.editViewSize.width != self.editViewSize.height) {
+ [self.scrollView setZoomScale:1.f animated:YES];
+ [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
+ [UIView animateWithDuration:.3f animations:^{
+ self.scrollView.frame = CGRectMake(0, 0, self.editViewSize.width, self.editViewSize.height);
+ if (times % 2 == 1) {
+ if (self.editViewSize.width * (self.imageViewOriginSize.width/self.imageViewOriginSize.height) >= self.editViewSize.height) {
+ self.imageView.frame = CGRectMake(0, 0, self.editViewSize.width * (self.imageViewOriginSize.width/self.imageViewOriginSize.height), self.editViewSize.width); //瀹芥媺婊�
+ } else {
+ self.imageView.frame = CGRectMake(0, 0, self.editViewSize.height, self.editViewSize.height * (self.imageViewOriginSize.height/self.imageViewOriginSize.width)); //楂樻媺婊�
+ }
+ } else {
+ self.imageView.frame = CGRectMake(0, 0, self.imageViewOriginSize.width, self.imageViewOriginSize.height);
+ }
+ } completion:^(BOOL finished) {
+ self.scrollView.contentSize = self.imageView.frame.size;
+ self.view.userInteractionEnabled = YES;
+ }];
+ } else {
+ self.view.userInteractionEnabled = YES;
+ }
+ }];
+
+}
+
+- (void)originAll {
+ self.rotateTimes = 0;
+ self.captureView.rotateTimes = 0;
+ [self.scrollView setZoomScale:1];
+ self.scrollView.transform = CGAffineTransformIdentity;
+ self.scrollView.frame = CGRectMake(0, 0, self.editViewSize.width, self.editViewSize.height);
+ self.imageView.frame = CGRectMake(0, 0, self.imageViewOriginSize.width, self.imageViewOriginSize.height);
+ self.scrollView.contentSize = self.imageView.frame.size;
+ self.scrollView.contentOffset = CGPointMake(0, 0);
+}
+
+#pragma mark - override
+- (BOOL)prefersStatusBarHidden {
+ return YES;
+}
+
+#pragma mark - getter & setter
+- (CGFloat)topSpace {
+ return (([[UIScreen mainScreen] bounds].size.height) - hq_safeAreaInset().top - hq_safeAreaInset().bottom - 49*2 - self.editViewSize.height)/2.f;
+}
+
+- (CGFloat)leftSpace {
+ return (([[UIScreen mainScreen] bounds].size.width) - self.editViewSize.width)/2.f;
+}
+
+- (CGFloat)rightSpace {
+ return (([[UIScreen mainScreen] bounds].size.width) - self.editViewSize.width)/2.f;
+}
+
+- (CGFloat)bottomSpace {
+ return (([[UIScreen mainScreen] bounds].size.height) - hq_safeAreaInset().top - hq_safeAreaInset().bottom - 49*2 - self.editViewSize.height)/2.f;
+}
+
+- (CGSize)editViewSize {
+ if (_editViewSize.width == 0 && _editViewSize.height == 0) {
+ return CGSizeMake((CGFloat)(([[UIScreen mainScreen] bounds].size.width) - 20*2), (CGFloat)(([[UIScreen mainScreen] bounds].size.width) - 20*2));
+ } else {
+ return _editViewSize;
+ }
+}
+
+- (CGSize)imageViewOriginSize {
+ if (self.editViewSize.width/self.originImage.size.width > self.editViewSize.height/self.originImage.size.height) {
+ return CGSizeMake(self.editViewSize.width, (CGFloat)((self.originImage.size.height/self.originImage.size.width)*self.editViewSize.width)); //瀹�
+ } else {
+ return CGSizeMake((CGFloat)((self.originImage.size.width/self.originImage.size.height)*self.editViewSize.height), self.editViewSize.height); //楂�
+ }
+}
+
+- (HQEditImageCaptureView *)captureView {
+ if (!_captureView) {
+ _captureView = [[HQEditImageCaptureView alloc] init];
+ _captureView.captureView = self.scrollView;
+ _captureView.imageView = self.imageView;
+ }
+ return _captureView;
+}
+
+- (UIScrollView *)scrollView {
+ if (!_scrollView) {
+ _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.editViewSize.width, self.editViewSize.height)];
+
+ _scrollView.delegate = self;
+ _scrollView.layer.masksToBounds = NO;
+
+ _scrollView.minimumZoomScale = 1.f;
+ _scrollView.maximumZoomScale = 10.f;
+ _scrollView.zoomScale = 1.f;
+
+ _scrollView.showsVerticalScrollIndicator = NO;
+ _scrollView.showsHorizontalScrollIndicator = NO;
+
+ _scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
+
+ _scrollView.contentInset = UIEdgeInsetsZero;
+ _scrollView.contentSize = CGSizeMake(self.imageViewOriginSize.width, self.imageViewOriginSize.height);
+ if (@available(iOS 11.0, *)) {
+ _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+ } else {
+ // Fallback on earlier versions
+ }
+ }
+ return _scrollView;
+}
+
+- (UIImageView *)imageView {
+ if (!_imageView) {
+ _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.imageViewOriginSize.width, self.imageViewOriginSize.height)];
+ _imageView.image = self.originImage;
+ _imageView.contentMode = UIViewContentModeScaleAspectFill;
+ }
+ return _imageView;
+}
+
+- (HQEditImageActionView *)actionView {
+ if (!_actionView) {
+ _actionView = [[HQEditImageActionView alloc] init];
+ _actionView.delegate = self;
+ }
+ return _actionView;
+}
+
+- (HQEditImageEditView *)editView {
+ if (!_editView) {
+ _editView = [[HQEditImageEditView alloc] initWithMargin:UIEdgeInsetsMake(self.topSpace + hq_safeAreaInset().top, self.leftSpace, self.bottomSpace, self.rightSpace) size:CGSizeMake(self.editViewSize.width, self.editViewSize.height)];
+
+ _editView.delegate = self;
+ _editView.maskViewAnimation = self.maskViewAnimation;
+ }
+ return _editView;
+}
+
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.h
new file mode 100755
index 0000000..934c6f1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.h
@@ -0,0 +1,26 @@
+//
+// MASCompositeConstraint.h
+// Masonry
+//
+// Created by Jonas Budelmann on 21/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASConstraint.h"
+#import "MASUtilities.h"
+
+/**
+ * A group of MASConstraint objects
+ */
+@interface MASCompositeConstraint : MASConstraint
+
+/**
+ * Creates a composite with a predefined array of children
+ *
+ * @param children child MASConstraints
+ *
+ * @return a composite constraint
+ */
+- (id)initWithChildren:(NSArray *)children;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.m
new file mode 100755
index 0000000..2002a40
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASCompositeConstraint.m
@@ -0,0 +1,183 @@
+//
+// MASCompositeConstraint.m
+// Masonry
+//
+// Created by Jonas Budelmann on 21/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASCompositeConstraint.h"
+#import "MASConstraint+Private.h"
+
+@interface MASCompositeConstraint () <MASConstraintDelegate>
+
+@property (nonatomic, strong) id mas_key;
+@property (nonatomic, strong) NSMutableArray *childConstraints;
+
+@end
+
+@implementation MASCompositeConstraint
+
+- (id)initWithChildren:(NSArray *)children {
+ self = [super init];
+ if (!self) return nil;
+
+ _childConstraints = [children mutableCopy];
+ for (MASConstraint *constraint in _childConstraints) {
+ constraint.delegate = self;
+ }
+
+ return self;
+}
+
+#pragma mark - MASConstraintDelegate
+
+- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint {
+ NSUInteger index = [self.childConstraints indexOfObject:constraint];
+ NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint);
+ [self.childConstraints replaceObjectAtIndex:index withObject:replacementConstraint];
+}
+
+- (MASConstraint *)constraint:(MASConstraint __unused *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ id<MASConstraintDelegate> strongDelegate = self.delegate;
+ MASConstraint *newConstraint = [strongDelegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
+ newConstraint.delegate = self;
+ [self.childConstraints addObject:newConstraint];
+ return newConstraint;
+}
+
+#pragma mark - NSLayoutConstraint multiplier proxies
+
+- (MASConstraint * (^)(CGFloat))multipliedBy {
+ return ^id(CGFloat multiplier) {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.multipliedBy(multiplier);
+ }
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(CGFloat))dividedBy {
+ return ^id(CGFloat divider) {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.dividedBy(divider);
+ }
+ return self;
+ };
+}
+
+#pragma mark - MASLayoutPriority proxy
+
+- (MASConstraint * (^)(MASLayoutPriority))priority {
+ return ^id(MASLayoutPriority priority) {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.priority(priority);
+ }
+ return self;
+ };
+}
+
+#pragma mark - NSLayoutRelation proxy
+
+- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
+ return ^id(id attr, NSLayoutRelation relation) {
+ for (MASConstraint *constraint in self.childConstraints.copy) {
+ constraint.equalToWithRelation(attr, relation);
+ }
+ return self;
+ };
+}
+
+#pragma mark - attribute chaining
+
+- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ [self constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
+ return self;
+}
+
+#pragma mark - Animator proxy
+
+#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
+
+- (MASConstraint *)animator {
+ for (MASConstraint *constraint in self.childConstraints) {
+ [constraint animator];
+ }
+ return self;
+}
+
+#endif
+
+#pragma mark - debug helpers
+
+- (MASConstraint * (^)(id))key {
+ return ^id(id key) {
+ self.mas_key = key;
+ int i = 0;
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.key([NSString stringWithFormat:@"%@[%d]", key, i++]);
+ }
+ return self;
+ };
+}
+
+#pragma mark - NSLayoutConstraint constant setters
+
+- (void)setInsets:(MASEdgeInsets)insets {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.insets = insets;
+ }
+}
+
+- (void)setInset:(CGFloat)inset {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.inset = inset;
+ }
+}
+
+- (void)setOffset:(CGFloat)offset {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.offset = offset;
+ }
+}
+
+- (void)setSizeOffset:(CGSize)sizeOffset {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.sizeOffset = sizeOffset;
+ }
+}
+
+- (void)setCenterOffset:(CGPoint)centerOffset {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.centerOffset = centerOffset;
+ }
+}
+
+#pragma mark - MASConstraint
+
+- (void)activate {
+ for (MASConstraint *constraint in self.childConstraints) {
+ [constraint activate];
+ }
+}
+
+- (void)deactivate {
+ for (MASConstraint *constraint in self.childConstraints) {
+ [constraint deactivate];
+ }
+}
+
+- (void)install {
+ for (MASConstraint *constraint in self.childConstraints) {
+ constraint.updateExisting = self.updateExisting;
+ [constraint install];
+ }
+}
+
+- (void)uninstall {
+ for (MASConstraint *constraint in self.childConstraints) {
+ [constraint uninstall];
+ }
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint+Private.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint+Private.h
new file mode 100755
index 0000000..ee0fd96
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint+Private.h
@@ -0,0 +1,66 @@
+//
+// MASConstraint+Private.h
+// Masonry
+//
+// Created by Nick Tymchenko on 29/04/14.
+// Copyright (c) 2014 cloudling. All rights reserved.
+//
+
+#import "MASConstraint.h"
+
+@protocol MASConstraintDelegate;
+
+
+@interface MASConstraint ()
+
+/**
+ * Whether or not to check for an existing constraint instead of adding constraint
+ */
+@property (nonatomic, assign) BOOL updateExisting;
+
+/**
+ * Usually MASConstraintMaker but could be a parent MASConstraint
+ */
+@property (nonatomic, weak) id<MASConstraintDelegate> delegate;
+
+/**
+ * Based on a provided value type, is equal to calling:
+ * NSNumber - setOffset:
+ * NSValue with CGPoint - setPointOffset:
+ * NSValue with CGSize - setSizeOffset:
+ * NSValue with MASEdgeInsets - setInsets:
+ */
+- (void)setLayoutConstantWithValue:(NSValue *)value;
+
+@end
+
+
+@interface MASConstraint (Abstract)
+
+/**
+ * Sets the constraint relation to given NSLayoutRelation
+ * returns a block which accepts one of the following:
+ * MASViewAttribute, UIView, NSValue, NSArray
+ * see readme for more details.
+ */
+- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation;
+
+/**
+ * Override to set a custom chaining behaviour
+ */
+- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
+
+@end
+
+
+@protocol MASConstraintDelegate <NSObject>
+
+/**
+ * Notifies the delegate when the constraint needs to be replaced with another constraint. For example
+ * A MASViewConstraint may turn into a MASCompositeConstraint when an array is passed to one of the equality blocks
+ */
+- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint;
+
+- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.h
new file mode 100755
index 0000000..3eaa8a1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.h
@@ -0,0 +1,272 @@
+//
+// MASConstraint.h
+// Masonry
+//
+// Created by Jonas Budelmann on 22/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASUtilities.h"
+
+/**
+ * Enables Constraints to be created with chainable syntax
+ * Constraint can represent single NSLayoutConstraint (MASViewConstraint)
+ * or a group of NSLayoutConstraints (MASComposisteConstraint)
+ */
+@interface MASConstraint : NSObject
+
+// Chaining Support
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
+ */
+- (MASConstraint * (^)(MASEdgeInsets insets))insets;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
+ */
+- (MASConstraint * (^)(CGFloat inset))inset;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeWidth, NSLayoutAttributeHeight
+ */
+- (MASConstraint * (^)(CGSize offset))sizeOffset;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
+ */
+- (MASConstraint * (^)(CGPoint offset))centerOffset;
+
+/**
+ * Modifies the NSLayoutConstraint constant
+ */
+- (MASConstraint * (^)(CGFloat offset))offset;
+
+/**
+ * Modifies the NSLayoutConstraint constant based on a value type
+ */
+- (MASConstraint * (^)(NSValue *value))valueOffset;
+
+/**
+ * Sets the NSLayoutConstraint multiplier property
+ */
+- (MASConstraint * (^)(CGFloat multiplier))multipliedBy;
+
+/**
+ * Sets the NSLayoutConstraint multiplier to 1.0/dividedBy
+ */
+- (MASConstraint * (^)(CGFloat divider))dividedBy;
+
+/**
+ * Sets the NSLayoutConstraint priority to a float or MASLayoutPriority
+ */
+- (MASConstraint * (^)(MASLayoutPriority priority))priority;
+
+/**
+ * Sets the NSLayoutConstraint priority to MASLayoutPriorityLow
+ */
+- (MASConstraint * (^)(void))priorityLow;
+
+/**
+ * Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium
+ */
+- (MASConstraint * (^)(void))priorityMedium;
+
+/**
+ * Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh
+ */
+- (MASConstraint * (^)(void))priorityHigh;
+
+/**
+ * Sets the constraint relation to NSLayoutRelationEqual
+ * returns a block which accepts one of the following:
+ * MASViewAttribute, UIView, NSValue, NSArray
+ * see readme for more details.
+ */
+- (MASConstraint * (^)(id attr))equalTo;
+
+/**
+ * Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual
+ * returns a block which accepts one of the following:
+ * MASViewAttribute, UIView, NSValue, NSArray
+ * see readme for more details.
+ */
+- (MASConstraint * (^)(id attr))greaterThanOrEqualTo;
+
+/**
+ * Sets the constraint relation to NSLayoutRelationLessThanOrEqual
+ * returns a block which accepts one of the following:
+ * MASViewAttribute, UIView, NSValue, NSArray
+ * see readme for more details.
+ */
+- (MASConstraint * (^)(id attr))lessThanOrEqualTo;
+
+/**
+ * Optional semantic property which has no effect but improves the readability of constraint
+ */
+- (MASConstraint *)with;
+
+/**
+ * Optional semantic property which has no effect but improves the readability of constraint
+ */
+- (MASConstraint *)and;
+
+/**
+ * Creates a new MASCompositeConstraint with the called attribute and reciever
+ */
+- (MASConstraint *)left;
+- (MASConstraint *)top;
+- (MASConstraint *)right;
+- (MASConstraint *)bottom;
+- (MASConstraint *)leading;
+- (MASConstraint *)trailing;
+- (MASConstraint *)width;
+- (MASConstraint *)height;
+- (MASConstraint *)centerX;
+- (MASConstraint *)centerY;
+- (MASConstraint *)baseline;
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+- (MASConstraint *)firstBaseline;
+- (MASConstraint *)lastBaseline;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+- (MASConstraint *)leftMargin;
+- (MASConstraint *)rightMargin;
+- (MASConstraint *)topMargin;
+- (MASConstraint *)bottomMargin;
+- (MASConstraint *)leadingMargin;
+- (MASConstraint *)trailingMargin;
+- (MASConstraint *)centerXWithinMargins;
+- (MASConstraint *)centerYWithinMargins;
+
+#endif
+
+
+/**
+ * Sets the constraint debug name
+ */
+- (MASConstraint * (^)(id key))key;
+
+// NSLayoutConstraint constant Setters
+// for use outside of mas_updateConstraints/mas_makeConstraints blocks
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
+ */
+- (void)setInsets:(MASEdgeInsets)insets;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
+ */
+- (void)setInset:(CGFloat)inset;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeWidth, NSLayoutAttributeHeight
+ */
+- (void)setSizeOffset:(CGSize)sizeOffset;
+
+/**
+ * Modifies the NSLayoutConstraint constant,
+ * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following
+ * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
+ */
+- (void)setCenterOffset:(CGPoint)centerOffset;
+
+/**
+ * Modifies the NSLayoutConstraint constant
+ */
+- (void)setOffset:(CGFloat)offset;
+
+
+// NSLayoutConstraint Installation support
+
+#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
+/**
+ * Whether or not to go through the animator proxy when modifying the constraint
+ */
+@property (nonatomic, copy, readonly) MASConstraint *animator;
+#endif
+
+/**
+ * Activates an NSLayoutConstraint if it's supported by an OS.
+ * Invokes install otherwise.
+ */
+- (void)activate;
+
+/**
+ * Deactivates previously installed/activated NSLayoutConstraint.
+ */
+- (void)deactivate;
+
+/**
+ * Creates a NSLayoutConstraint and adds it to the appropriate view.
+ */
+- (void)install;
+
+/**
+ * Removes previously installed NSLayoutConstraint
+ */
+- (void)uninstall;
+
+@end
+
+
+/**
+ * Convenience auto-boxing macros for MASConstraint methods.
+ *
+ * Defining MAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax.
+ * A potential drawback of this is that the unprefixed macros will appear in global scope.
+ */
+#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__)))
+#define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
+#define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))
+
+#define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__)))
+
+
+#ifdef MAS_SHORTHAND_GLOBALS
+
+#define equalTo(...) mas_equalTo(__VA_ARGS__)
+#define greaterThanOrEqualTo(...) mas_greaterThanOrEqualTo(__VA_ARGS__)
+#define lessThanOrEqualTo(...) mas_lessThanOrEqualTo(__VA_ARGS__)
+
+#define offset(...) mas_offset(__VA_ARGS__)
+
+#endif
+
+
+@interface MASConstraint (AutoboxingSupport)
+
+/**
+ * Aliases to corresponding relation methods (for shorthand macros)
+ * Also needed to aid autocompletion
+ */
+- (MASConstraint * (^)(id attr))mas_equalTo;
+- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo;
+- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo;
+
+/**
+ * A dummy method to aid autocompletion
+ */
+- (MASConstraint * (^)(id offset))mas_offset;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.m
new file mode 100755
index 0000000..52de590
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraint.m
@@ -0,0 +1,301 @@
+//
+// MASConstraint.m
+// Masonry
+//
+// Created by Nick Tymchenko on 1/20/14.
+//
+
+#import "MASConstraint.h"
+#import "MASConstraint+Private.h"
+
+#define MASMethodNotImplemented() \
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException \
+ reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \
+ userInfo:nil]
+
+@implementation MASConstraint
+
+#pragma mark - Init
+
+- (id)init {
+ NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly.");
+ return [super init];
+}
+
+#pragma mark - NSLayoutRelation proxies
+
+- (MASConstraint * (^)(id))equalTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
+ };
+}
+
+- (MASConstraint * (^)(id))mas_equalTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
+ };
+}
+
+- (MASConstraint * (^)(id))greaterThanOrEqualTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual);
+ };
+}
+
+- (MASConstraint * (^)(id))mas_greaterThanOrEqualTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual);
+ };
+}
+
+- (MASConstraint * (^)(id))lessThanOrEqualTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual);
+ };
+}
+
+- (MASConstraint * (^)(id))mas_lessThanOrEqualTo {
+ return ^id(id attribute) {
+ return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual);
+ };
+}
+
+#pragma mark - MASLayoutPriority proxies
+
+- (MASConstraint * (^)(void))priorityLow {
+ return ^id{
+ self.priority(MASLayoutPriorityDefaultLow);
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(void))priorityMedium {
+ return ^id{
+ self.priority(MASLayoutPriorityDefaultMedium);
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(void))priorityHigh {
+ return ^id{
+ self.priority(MASLayoutPriorityDefaultHigh);
+ return self;
+ };
+}
+
+#pragma mark - NSLayoutConstraint constant proxies
+
+- (MASConstraint * (^)(MASEdgeInsets))insets {
+ return ^id(MASEdgeInsets insets){
+ self.insets = insets;
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(CGFloat))inset {
+ return ^id(CGFloat inset){
+ self.inset = inset;
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(CGSize))sizeOffset {
+ return ^id(CGSize offset) {
+ self.sizeOffset = offset;
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(CGPoint))centerOffset {
+ return ^id(CGPoint offset) {
+ self.centerOffset = offset;
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(CGFloat))offset {
+ return ^id(CGFloat offset){
+ self.offset = offset;
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(NSValue *value))valueOffset {
+ return ^id(NSValue *offset) {
+ NSAssert([offset isKindOfClass:NSValue.class], @"expected an NSValue offset, got: %@", offset);
+ [self setLayoutConstantWithValue:offset];
+ return self;
+ };
+}
+
+- (MASConstraint * (^)(id offset))mas_offset {
+ // Will never be called due to macro
+ return nil;
+}
+
+#pragma mark - NSLayoutConstraint constant setter
+
+- (void)setLayoutConstantWithValue:(NSValue *)value {
+ if ([value isKindOfClass:NSNumber.class]) {
+ self.offset = [(NSNumber *)value doubleValue];
+ } else if (strcmp(value.objCType, @encode(CGPoint)) == 0) {
+ CGPoint point;
+ [value getValue:&point];
+ self.centerOffset = point;
+ } else if (strcmp(value.objCType, @encode(CGSize)) == 0) {
+ CGSize size;
+ [value getValue:&size];
+ self.sizeOffset = size;
+ } else if (strcmp(value.objCType, @encode(MASEdgeInsets)) == 0) {
+ MASEdgeInsets insets;
+ [value getValue:&insets];
+ self.insets = insets;
+ } else {
+ NSAssert(NO, @"attempting to set layout constant with unsupported value: %@", value);
+ }
+}
+
+#pragma mark - Semantic properties
+
+- (MASConstraint *)with {
+ return self;
+}
+
+- (MASConstraint *)and {
+ return self;
+}
+
+#pragma mark - Chaining
+
+- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute __unused)layoutAttribute {
+ MASMethodNotImplemented();
+}
+
+- (MASConstraint *)left {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
+}
+
+- (MASConstraint *)top {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
+}
+
+- (MASConstraint *)right {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
+}
+
+- (MASConstraint *)bottom {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
+}
+
+- (MASConstraint *)leading {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
+}
+
+- (MASConstraint *)trailing {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
+}
+
+- (MASConstraint *)width {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
+}
+
+- (MASConstraint *)height {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
+}
+
+- (MASConstraint *)centerX {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
+}
+
+- (MASConstraint *)centerY {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
+}
+
+- (MASConstraint *)baseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
+}
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+- (MASConstraint *)firstBaseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline];
+}
+- (MASConstraint *)lastBaseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline];
+}
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+- (MASConstraint *)leftMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
+}
+
+- (MASConstraint *)rightMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
+}
+
+- (MASConstraint *)topMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
+}
+
+- (MASConstraint *)bottomMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
+}
+
+- (MASConstraint *)leadingMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
+}
+
+- (MASConstraint *)trailingMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
+}
+
+- (MASConstraint *)centerXWithinMargins {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
+}
+
+- (MASConstraint *)centerYWithinMargins {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins];
+}
+
+#endif
+
+#pragma mark - Abstract
+
+- (MASConstraint * (^)(CGFloat multiplier))multipliedBy { MASMethodNotImplemented(); }
+
+- (MASConstraint * (^)(CGFloat divider))dividedBy { MASMethodNotImplemented(); }
+
+- (MASConstraint * (^)(MASLayoutPriority priority))priority { MASMethodNotImplemented(); }
+
+- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { MASMethodNotImplemented(); }
+
+- (MASConstraint * (^)(id key))key { MASMethodNotImplemented(); }
+
+- (void)setInsets:(MASEdgeInsets __unused)insets { MASMethodNotImplemented(); }
+
+- (void)setInset:(CGFloat __unused)inset { MASMethodNotImplemented(); }
+
+- (void)setSizeOffset:(CGSize __unused)sizeOffset { MASMethodNotImplemented(); }
+
+- (void)setCenterOffset:(CGPoint __unused)centerOffset { MASMethodNotImplemented(); }
+
+- (void)setOffset:(CGFloat __unused)offset { MASMethodNotImplemented(); }
+
+#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
+
+- (MASConstraint *)animator { MASMethodNotImplemented(); }
+
+#endif
+
+- (void)activate { MASMethodNotImplemented(); }
+
+- (void)deactivate { MASMethodNotImplemented(); }
+
+- (void)install { MASMethodNotImplemented(); }
+
+- (void)uninstall { MASMethodNotImplemented(); }
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.h
new file mode 100755
index 0000000..d9b58f4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.h
@@ -0,0 +1,146 @@
+//
+// MASConstraintMaker.h
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASConstraint.h"
+#import "MASUtilities.h"
+
+typedef NS_OPTIONS(NSInteger, MASAttribute) {
+ MASAttributeLeft = 1 << NSLayoutAttributeLeft,
+ MASAttributeRight = 1 << NSLayoutAttributeRight,
+ MASAttributeTop = 1 << NSLayoutAttributeTop,
+ MASAttributeBottom = 1 << NSLayoutAttributeBottom,
+ MASAttributeLeading = 1 << NSLayoutAttributeLeading,
+ MASAttributeTrailing = 1 << NSLayoutAttributeTrailing,
+ MASAttributeWidth = 1 << NSLayoutAttributeWidth,
+ MASAttributeHeight = 1 << NSLayoutAttributeHeight,
+ MASAttributeCenterX = 1 << NSLayoutAttributeCenterX,
+ MASAttributeCenterY = 1 << NSLayoutAttributeCenterY,
+ MASAttributeBaseline = 1 << NSLayoutAttributeBaseline,
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+ MASAttributeFirstBaseline = 1 << NSLayoutAttributeFirstBaseline,
+ MASAttributeLastBaseline = 1 << NSLayoutAttributeLastBaseline,
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+ MASAttributeLeftMargin = 1 << NSLayoutAttributeLeftMargin,
+ MASAttributeRightMargin = 1 << NSLayoutAttributeRightMargin,
+ MASAttributeTopMargin = 1 << NSLayoutAttributeTopMargin,
+ MASAttributeBottomMargin = 1 << NSLayoutAttributeBottomMargin,
+ MASAttributeLeadingMargin = 1 << NSLayoutAttributeLeadingMargin,
+ MASAttributeTrailingMargin = 1 << NSLayoutAttributeTrailingMargin,
+ MASAttributeCenterXWithinMargins = 1 << NSLayoutAttributeCenterXWithinMargins,
+ MASAttributeCenterYWithinMargins = 1 << NSLayoutAttributeCenterYWithinMargins,
+
+#endif
+
+};
+
+/**
+ * Provides factory methods for creating MASConstraints.
+ * Constraints are collected until they are ready to be installed
+ *
+ */
+@interface MASConstraintMaker : NSObject
+
+/**
+ * The following properties return a new MASViewConstraint
+ * with the first item set to the makers associated view and the appropriate MASViewAttribute
+ */
+@property (nonatomic, strong, readonly) MASConstraint *left;
+@property (nonatomic, strong, readonly) MASConstraint *top;
+@property (nonatomic, strong, readonly) MASConstraint *right;
+@property (nonatomic, strong, readonly) MASConstraint *bottom;
+@property (nonatomic, strong, readonly) MASConstraint *leading;
+@property (nonatomic, strong, readonly) MASConstraint *trailing;
+@property (nonatomic, strong, readonly) MASConstraint *width;
+@property (nonatomic, strong, readonly) MASConstraint *height;
+@property (nonatomic, strong, readonly) MASConstraint *centerX;
+@property (nonatomic, strong, readonly) MASConstraint *centerY;
+@property (nonatomic, strong, readonly) MASConstraint *baseline;
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+@property (nonatomic, strong, readonly) MASConstraint *firstBaseline;
+@property (nonatomic, strong, readonly) MASConstraint *lastBaseline;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+@property (nonatomic, strong, readonly) MASConstraint *leftMargin;
+@property (nonatomic, strong, readonly) MASConstraint *rightMargin;
+@property (nonatomic, strong, readonly) MASConstraint *topMargin;
+@property (nonatomic, strong, readonly) MASConstraint *bottomMargin;
+@property (nonatomic, strong, readonly) MASConstraint *leadingMargin;
+@property (nonatomic, strong, readonly) MASConstraint *trailingMargin;
+@property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins;
+@property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;
+
+#endif
+
+/**
+ * Returns a block which creates a new MASCompositeConstraint with the first item set
+ * to the makers associated view and children corresponding to the set bits in the
+ * MASAttribute parameter. Combine multiple attributes via binary-or.
+ */
+@property (nonatomic, strong, readonly) MASConstraint *(^attributes)(MASAttribute attrs);
+
+/**
+ * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeEdges
+ * which generates the appropriate MASViewConstraint children (top, left, bottom, right)
+ * with the first item set to the makers associated view
+ */
+@property (nonatomic, strong, readonly) MASConstraint *edges;
+
+/**
+ * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeSize
+ * which generates the appropriate MASViewConstraint children (width, height)
+ * with the first item set to the makers associated view
+ */
+@property (nonatomic, strong, readonly) MASConstraint *size;
+
+/**
+ * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeCenter
+ * which generates the appropriate MASViewConstraint children (centerX, centerY)
+ * with the first item set to the makers associated view
+ */
+@property (nonatomic, strong, readonly) MASConstraint *center;
+
+/**
+ * Whether or not to check for an existing constraint instead of adding constraint
+ */
+@property (nonatomic, assign) BOOL updateExisting;
+
+/**
+ * Whether or not to remove existing constraints prior to installing
+ */
+@property (nonatomic, assign) BOOL removeExisting;
+
+/**
+ * initialises the maker with a default view
+ *
+ * @param view any MASConstraint are created with this view as the first item
+ *
+ * @return a new MASConstraintMaker
+ */
+- (id)initWithView:(MAS_VIEW *)view;
+
+/**
+ * Calls install method on any MASConstraints which have been created by this maker
+ *
+ * @return an array of all the installed MASConstraints
+ */
+- (NSArray *)install;
+
+- (MASConstraint * (^)(dispatch_block_t))group;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.m
new file mode 100755
index 0000000..f11492a
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASConstraintMaker.m
@@ -0,0 +1,273 @@
+//
+// MASConstraintMaker.m
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASConstraintMaker.h"
+#import "MASViewConstraint.h"
+#import "MASCompositeConstraint.h"
+#import "MASConstraint+Private.h"
+#import "MASViewAttribute.h"
+#import "View+MASAdditions.h"
+
+@interface MASConstraintMaker () <MASConstraintDelegate>
+
+@property (nonatomic, weak) MAS_VIEW *view;
+@property (nonatomic, strong) NSMutableArray *constraints;
+
+@end
+
+@implementation MASConstraintMaker
+
+- (id)initWithView:(MAS_VIEW *)view {
+ self = [super init];
+ if (!self) return nil;
+
+ self.view = view;
+ self.constraints = NSMutableArray.new;
+
+ return self;
+}
+
+- (NSArray *)install {
+ if (self.removeExisting) {
+ NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
+ for (MASConstraint *constraint in installedConstraints) {
+ [constraint uninstall];
+ }
+ }
+ NSArray *constraints = self.constraints.copy;
+ for (MASConstraint *constraint in constraints) {
+ constraint.updateExisting = self.updateExisting;
+ [constraint install];
+ }
+ [self.constraints removeAllObjects];
+ return constraints;
+}
+
+#pragma mark - MASConstraintDelegate
+
+- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint {
+ NSUInteger index = [self.constraints indexOfObject:constraint];
+ NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint);
+ [self.constraints replaceObjectAtIndex:index withObject:replacementConstraint];
+}
+
+- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute];
+ MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute];
+ if ([constraint isKindOfClass:MASViewConstraint.class]) {
+ //replace with composite constraint
+ NSArray *children = @[constraint, newConstraint];
+ MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
+ compositeConstraint.delegate = self;
+ [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
+ return compositeConstraint;
+ }
+ if (!constraint) {
+ newConstraint.delegate = self;
+ [self.constraints addObject:newConstraint];
+ }
+ return newConstraint;
+}
+
+- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs {
+ __unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading
+ | MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX
+ | MASAttributeCenterY | MASAttributeBaseline
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+ | MASAttributeFirstBaseline | MASAttributeLastBaseline
+#endif
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+ | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin
+ | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins
+ | MASAttributeCenterYWithinMargins
+#endif
+ );
+
+ NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)");
+
+ NSMutableArray *attributes = [NSMutableArray array];
+
+ if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left];
+ if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right];
+ if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top];
+ if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom];
+ if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading];
+ if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing];
+ if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width];
+ if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height];
+ if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX];
+ if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY];
+ if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline];
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+ if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline];
+ if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline];
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+ if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin];
+ if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin];
+ if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin];
+ if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin];
+ if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin];
+ if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin];
+ if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins];
+ if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins];
+
+#endif
+
+ NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count];
+
+ for (MASViewAttribute *a in attributes) {
+ [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]];
+ }
+
+ MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
+ constraint.delegate = self;
+ [self.constraints addObject:constraint];
+ return constraint;
+}
+
+#pragma mark - standard Attributes
+
+- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
+}
+
+- (MASConstraint *)left {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
+}
+
+- (MASConstraint *)top {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
+}
+
+- (MASConstraint *)right {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight];
+}
+
+- (MASConstraint *)bottom {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom];
+}
+
+- (MASConstraint *)leading {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading];
+}
+
+- (MASConstraint *)trailing {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing];
+}
+
+- (MASConstraint *)width {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
+}
+
+- (MASConstraint *)height {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
+}
+
+- (MASConstraint *)centerX {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX];
+}
+
+- (MASConstraint *)centerY {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY];
+}
+
+- (MASConstraint *)baseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline];
+}
+
+- (MASConstraint *(^)(MASAttribute))attributes {
+ return ^(MASAttribute attrs){
+ return [self addConstraintWithAttributes:attrs];
+ };
+}
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+- (MASConstraint *)firstBaseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline];
+}
+
+- (MASConstraint *)lastBaseline {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline];
+}
+
+#endif
+
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+- (MASConstraint *)leftMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin];
+}
+
+- (MASConstraint *)rightMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin];
+}
+
+- (MASConstraint *)topMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin];
+}
+
+- (MASConstraint *)bottomMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin];
+}
+
+- (MASConstraint *)leadingMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin];
+}
+
+- (MASConstraint *)trailingMargin {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin];
+}
+
+- (MASConstraint *)centerXWithinMargins {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins];
+}
+
+- (MASConstraint *)centerYWithinMargins {
+ return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins];
+}
+
+#endif
+
+
+#pragma mark - composite Attributes
+
+- (MASConstraint *)edges {
+ return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom];
+}
+
+- (MASConstraint *)size {
+ return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight];
+}
+
+- (MASConstraint *)center {
+ return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY];
+}
+
+#pragma mark - grouping
+
+- (MASConstraint *(^)(dispatch_block_t group))group {
+ return ^id(dispatch_block_t group) {
+ NSInteger previousCount = self.constraints.count;
+ group();
+
+ NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)];
+ MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children];
+ constraint.delegate = self;
+ return constraint;
+ };
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.h
new file mode 100755
index 0000000..699041c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.h
@@ -0,0 +1,22 @@
+//
+// MASLayoutConstraint.h
+// Masonry
+//
+// Created by Jonas Budelmann on 3/08/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "MASUtilities.h"
+
+/**
+ * When you are debugging or printing the constraints attached to a view this subclass
+ * makes it easier to identify which constraints have been created via Masonry
+ */
+@interface MASLayoutConstraint : NSLayoutConstraint
+
+/**
+ * a key to associate with this constraint
+ */
+@property (nonatomic, strong) id mas_key;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.m
new file mode 100755
index 0000000..3483f02
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASLayoutConstraint.m
@@ -0,0 +1,13 @@
+//
+// MASLayoutConstraint.m
+// Masonry
+//
+// Created by Jonas Budelmann on 3/08/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "MASLayoutConstraint.h"
+
+@implementation MASLayoutConstraint
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASUtilities.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASUtilities.h
new file mode 100755
index 0000000..1dbfd93
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASUtilities.h
@@ -0,0 +1,136 @@
+//
+// MASUtilities.h
+// Masonry
+//
+// Created by Jonas Budelmann on 19/08/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+#if TARGET_OS_IPHONE || TARGET_OS_TV
+
+ #import <UIKit/UIKit.h>
+ #define MAS_VIEW UIView
+ #define MAS_VIEW_CONTROLLER UIViewController
+ #define MASEdgeInsets UIEdgeInsets
+
+ typedef UILayoutPriority MASLayoutPriority;
+ static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired;
+ static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh;
+ static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500;
+ static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow;
+ static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;
+
+#elif TARGET_OS_MAC
+
+ #import <AppKit/AppKit.h>
+ #define MAS_VIEW NSView
+ #define MASEdgeInsets NSEdgeInsets
+
+ typedef NSLayoutPriority MASLayoutPriority;
+ static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired;
+ static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh;
+ static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow;
+ static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501;
+ static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut;
+ static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow;
+ static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow;
+ static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression;
+
+#endif
+
+/**
+ * Allows you to attach keys to objects matching the variable names passed.
+ *
+ * view1.mas_key = @"view1", view2.mas_key = @"view2";
+ *
+ * is equivalent to:
+ *
+ * MASAttachKeys(view1, view2);
+ */
+#define MASAttachKeys(...) \
+ { \
+ NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__); \
+ for (id key in keyPairs.allKeys) { \
+ id obj = keyPairs[key]; \
+ NSAssert([obj respondsToSelector:@selector(setMas_key:)], \
+ @"Cannot attach mas_key to %@", obj); \
+ [obj setMas_key:key]; \
+ } \
+ }
+
+/**
+ * Used to create object hashes
+ * Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
+ */
+#define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
+#define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch)))
+
+/**
+ * Given a scalar or struct value, wraps it in NSValue
+ * Based on EXPObjectify: https://github.com/specta/expecta
+ */
+static inline id _MASBoxValue(const char *type, ...) {
+ va_list v;
+ va_start(v, type);
+ id obj = nil;
+ if (strcmp(type, @encode(id)) == 0) {
+ id actual = va_arg(v, id);
+ obj = actual;
+ } else if (strcmp(type, @encode(CGPoint)) == 0) {
+ CGPoint actual = (CGPoint)va_arg(v, CGPoint);
+ obj = [NSValue value:&actual withObjCType:type];
+ } else if (strcmp(type, @encode(CGSize)) == 0) {
+ CGSize actual = (CGSize)va_arg(v, CGSize);
+ obj = [NSValue value:&actual withObjCType:type];
+ } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {
+ MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);
+ obj = [NSValue value:&actual withObjCType:type];
+ } else if (strcmp(type, @encode(double)) == 0) {
+ double actual = (double)va_arg(v, double);
+ obj = [NSNumber numberWithDouble:actual];
+ } else if (strcmp(type, @encode(float)) == 0) {
+ float actual = (float)va_arg(v, double);
+ obj = [NSNumber numberWithFloat:actual];
+ } else if (strcmp(type, @encode(int)) == 0) {
+ int actual = (int)va_arg(v, int);
+ obj = [NSNumber numberWithInt:actual];
+ } else if (strcmp(type, @encode(long)) == 0) {
+ long actual = (long)va_arg(v, long);
+ obj = [NSNumber numberWithLong:actual];
+ } else if (strcmp(type, @encode(long long)) == 0) {
+ long long actual = (long long)va_arg(v, long long);
+ obj = [NSNumber numberWithLongLong:actual];
+ } else if (strcmp(type, @encode(short)) == 0) {
+ short actual = (short)va_arg(v, int);
+ obj = [NSNumber numberWithShort:actual];
+ } else if (strcmp(type, @encode(char)) == 0) {
+ char actual = (char)va_arg(v, int);
+ obj = [NSNumber numberWithChar:actual];
+ } else if (strcmp(type, @encode(bool)) == 0) {
+ bool actual = (bool)va_arg(v, int);
+ obj = [NSNumber numberWithBool:actual];
+ } else if (strcmp(type, @encode(unsigned char)) == 0) {
+ unsigned char actual = (unsigned char)va_arg(v, unsigned int);
+ obj = [NSNumber numberWithUnsignedChar:actual];
+ } else if (strcmp(type, @encode(unsigned int)) == 0) {
+ unsigned int actual = (unsigned int)va_arg(v, unsigned int);
+ obj = [NSNumber numberWithUnsignedInt:actual];
+ } else if (strcmp(type, @encode(unsigned long)) == 0) {
+ unsigned long actual = (unsigned long)va_arg(v, unsigned long);
+ obj = [NSNumber numberWithUnsignedLong:actual];
+ } else if (strcmp(type, @encode(unsigned long long)) == 0) {
+ unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);
+ obj = [NSNumber numberWithUnsignedLongLong:actual];
+ } else if (strcmp(type, @encode(unsigned short)) == 0) {
+ unsigned short actual = (unsigned short)va_arg(v, unsigned int);
+ obj = [NSNumber numberWithUnsignedShort:actual];
+ }
+ va_end(v);
+ return obj;
+}
+
+#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.h
new file mode 100755
index 0000000..601c25d
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.h
@@ -0,0 +1,49 @@
+//
+// MASViewAttribute.h
+// Masonry
+//
+// Created by Jonas Budelmann on 21/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASUtilities.h"
+
+/**
+ * An immutable tuple which stores the view and the related NSLayoutAttribute.
+ * Describes part of either the left or right hand side of a constraint equation
+ */
+@interface MASViewAttribute : NSObject
+
+/**
+ * The view which the reciever relates to. Can be nil if item is not a view.
+ */
+@property (nonatomic, weak, readonly) MAS_VIEW *view;
+
+/**
+ * The item which the reciever relates to.
+ */
+@property (nonatomic, weak, readonly) id item;
+
+/**
+ * The attribute which the reciever relates to
+ */
+@property (nonatomic, assign, readonly) NSLayoutAttribute layoutAttribute;
+
+/**
+ * Convenience initializer.
+ */
+- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute;
+
+/**
+ * The designated initializer.
+ */
+- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute;
+
+/**
+ * Determine whether the layoutAttribute is a size attribute
+ *
+ * @return YES if layoutAttribute is equal to NSLayoutAttributeWidth or NSLayoutAttributeHeight
+ */
+- (BOOL)isSizeAttribute;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.m
new file mode 100755
index 0000000..e573e8b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewAttribute.m
@@ -0,0 +1,46 @@
+//
+// MASViewAttribute.m
+// Masonry
+//
+// Created by Jonas Budelmann on 21/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASViewAttribute.h"
+
+@implementation MASViewAttribute
+
+- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ self = [self initWithView:view item:view layoutAttribute:layoutAttribute];
+ return self;
+}
+
+- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ self = [super init];
+ if (!self) return nil;
+
+ _view = view;
+ _item = item;
+ _layoutAttribute = layoutAttribute;
+
+ return self;
+}
+
+- (BOOL)isSizeAttribute {
+ return self.layoutAttribute == NSLayoutAttributeWidth
+ || self.layoutAttribute == NSLayoutAttributeHeight;
+}
+
+- (BOOL)isEqual:(MASViewAttribute *)viewAttribute {
+ if ([viewAttribute isKindOfClass:self.class]) {
+ return self.view == viewAttribute.view
+ && self.layoutAttribute == viewAttribute.layoutAttribute;
+ }
+ return [super isEqual:viewAttribute];
+}
+
+- (NSUInteger)hash {
+ return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.h
new file mode 100755
index 0000000..ec390d1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.h
@@ -0,0 +1,48 @@
+//
+// MASViewConstraint.h
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASViewAttribute.h"
+#import "MASConstraint.h"
+#import "MASLayoutConstraint.h"
+#import "MASUtilities.h"
+
+/**
+ * A single constraint.
+ * Contains the attributes neccessary for creating a NSLayoutConstraint and adding it to the appropriate view
+ */
+@interface MASViewConstraint : MASConstraint <NSCopying>
+
+/**
+ * First item/view and first attribute of the NSLayoutConstraint
+ */
+@property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute;
+
+/**
+ * Second item/view and second attribute of the NSLayoutConstraint
+ */
+@property (nonatomic, strong, readonly) MASViewAttribute *secondViewAttribute;
+
+/**
+ * initialises the MASViewConstraint with the first part of the equation
+ *
+ * @param firstViewAttribute view.mas_left, view.mas_width etc.
+ *
+ * @return a new view constraint
+ */
+- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute;
+
+/**
+ * Returns all MASViewConstraints installed with this view as a first item.
+ *
+ * @param view A view to retrieve constraints for.
+ *
+ * @return An array of MASViewConstraints.
+ */
++ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.m
new file mode 100755
index 0000000..173eec1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/MASViewConstraint.m
@@ -0,0 +1,401 @@
+//
+// MASViewConstraint.m
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASViewConstraint.h"
+#import "MASConstraint+Private.h"
+#import "MASCompositeConstraint.h"
+#import "MASLayoutConstraint.h"
+#import "View+MASAdditions.h"
+#import <objc/runtime.h>
+
+@interface MAS_VIEW (MASConstraints)
+
+@property (nonatomic, readonly) NSMutableSet *mas_installedConstraints;
+
+@end
+
+@implementation MAS_VIEW (MASConstraints)
+
+static char kInstalledConstraintsKey;
+
+- (NSMutableSet *)mas_installedConstraints {
+ NSMutableSet *constraints = objc_getAssociatedObject(self, &kInstalledConstraintsKey);
+ if (!constraints) {
+ constraints = [NSMutableSet set];
+ objc_setAssociatedObject(self, &kInstalledConstraintsKey, constraints, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ }
+ return constraints;
+}
+
+@end
+
+
+@interface MASViewConstraint ()
+
+@property (nonatomic, strong, readwrite) MASViewAttribute *secondViewAttribute;
+@property (nonatomic, weak) MAS_VIEW *installedView;
+@property (nonatomic, weak) MASLayoutConstraint *layoutConstraint;
+@property (nonatomic, assign) NSLayoutRelation layoutRelation;
+@property (nonatomic, assign) MASLayoutPriority layoutPriority;
+@property (nonatomic, assign) CGFloat layoutMultiplier;
+@property (nonatomic, assign) CGFloat layoutConstant;
+@property (nonatomic, assign) BOOL hasLayoutRelation;
+@property (nonatomic, strong) id mas_key;
+@property (nonatomic, assign) BOOL useAnimator;
+
+@end
+
+@implementation MASViewConstraint
+
+- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute {
+ self = [super init];
+ if (!self) return nil;
+
+ _firstViewAttribute = firstViewAttribute;
+ self.layoutPriority = MASLayoutPriorityRequired;
+ self.layoutMultiplier = 1;
+
+ return self;
+}
+
+#pragma mark - NSCoping
+
+- (id)copyWithZone:(NSZone __unused *)zone {
+ MASViewConstraint *constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:self.firstViewAttribute];
+ constraint.layoutConstant = self.layoutConstant;
+ constraint.layoutRelation = self.layoutRelation;
+ constraint.layoutPriority = self.layoutPriority;
+ constraint.layoutMultiplier = self.layoutMultiplier;
+ constraint.delegate = self.delegate;
+ return constraint;
+}
+
+#pragma mark - Public
+
++ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view {
+ return [view.mas_installedConstraints allObjects];
+}
+
+#pragma mark - Private
+
+- (void)setLayoutConstant:(CGFloat)layoutConstant {
+ _layoutConstant = layoutConstant;
+
+#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
+ if (self.useAnimator) {
+ [self.layoutConstraint.animator setConstant:layoutConstant];
+ } else {
+ self.layoutConstraint.constant = layoutConstant;
+ }
+#else
+ self.layoutConstraint.constant = layoutConstant;
+#endif
+}
+
+- (void)setLayoutRelation:(NSLayoutRelation)layoutRelation {
+ _layoutRelation = layoutRelation;
+ self.hasLayoutRelation = YES;
+}
+
+- (BOOL)supportsActiveProperty {
+ return [self.layoutConstraint respondsToSelector:@selector(isActive)];
+}
+
+- (BOOL)isActive {
+ BOOL active = YES;
+ if ([self supportsActiveProperty]) {
+ active = [self.layoutConstraint isActive];
+ }
+
+ return active;
+}
+
+- (BOOL)hasBeenInstalled {
+ return (self.layoutConstraint != nil) && [self isActive];
+}
+
+- (void)setSecondViewAttribute:(id)secondViewAttribute {
+ if ([secondViewAttribute isKindOfClass:NSValue.class]) {
+ [self setLayoutConstantWithValue:secondViewAttribute];
+ } else if ([secondViewAttribute isKindOfClass:MAS_VIEW.class]) {
+ _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute];
+ } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) {
+ _secondViewAttribute = secondViewAttribute;
+ } else {
+ NSAssert(NO, @"attempting to add unsupported attribute: %@", secondViewAttribute);
+ }
+}
+
+#pragma mark - NSLayoutConstraint multiplier proxies
+
+- (MASConstraint * (^)(CGFloat))multipliedBy {
+ return ^id(CGFloat multiplier) {
+ NSAssert(!self.hasBeenInstalled,
+ @"Cannot modify constraint multiplier after it has been installed");
+
+ self.layoutMultiplier = multiplier;
+ return self;
+ };
+}
+
+
+- (MASConstraint * (^)(CGFloat))dividedBy {
+ return ^id(CGFloat divider) {
+ NSAssert(!self.hasBeenInstalled,
+ @"Cannot modify constraint multiplier after it has been installed");
+
+ self.layoutMultiplier = 1.0/divider;
+ return self;
+ };
+}
+
+#pragma mark - MASLayoutPriority proxy
+
+- (MASConstraint * (^)(MASLayoutPriority))priority {
+ return ^id(MASLayoutPriority priority) {
+ NSAssert(!self.hasBeenInstalled,
+ @"Cannot modify constraint priority after it has been installed");
+
+ self.layoutPriority = priority;
+ return self;
+ };
+}
+
+#pragma mark - NSLayoutRelation proxy
+
+- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
+ return ^id(id attribute, NSLayoutRelation relation) {
+ if ([attribute isKindOfClass:NSArray.class]) {
+ NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
+ NSMutableArray *children = NSMutableArray.new;
+ for (id attr in attribute) {
+ MASViewConstraint *viewConstraint = [self copy];
+ viewConstraint.layoutRelation = relation;
+ viewConstraint.secondViewAttribute = attr;
+ [children addObject:viewConstraint];
+ }
+ MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
+ compositeConstraint.delegate = self.delegate;
+ [self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint];
+ return compositeConstraint;
+ } else {
+ NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation");
+ self.layoutRelation = relation;
+ self.secondViewAttribute = attribute;
+ return self;
+ }
+ };
+}
+
+#pragma mark - Semantic properties
+
+- (MASConstraint *)with {
+ return self;
+}
+
+- (MASConstraint *)and {
+ return self;
+}
+
+#pragma mark - attribute chaining
+
+- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
+ NSAssert(!self.hasLayoutRelation, @"Attributes should be chained before defining the constraint relation");
+
+ return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
+}
+
+#pragma mark - Animator proxy
+
+#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
+
+- (MASConstraint *)animator {
+ self.useAnimator = YES;
+ return self;
+}
+
+#endif
+
+#pragma mark - debug helpers
+
+- (MASConstraint * (^)(id))key {
+ return ^id(id key) {
+ self.mas_key = key;
+ return self;
+ };
+}
+
+#pragma mark - NSLayoutConstraint constant setters
+
+- (void)setInsets:(MASEdgeInsets)insets {
+ NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute;
+ switch (layoutAttribute) {
+ case NSLayoutAttributeLeft:
+ case NSLayoutAttributeLeading:
+ self.layoutConstant = insets.left;
+ break;
+ case NSLayoutAttributeTop:
+ self.layoutConstant = insets.top;
+ break;
+ case NSLayoutAttributeBottom:
+ self.layoutConstant = -insets.bottom;
+ break;
+ case NSLayoutAttributeRight:
+ case NSLayoutAttributeTrailing:
+ self.layoutConstant = -insets.right;
+ break;
+ default:
+ break;
+ }
+}
+
+- (void)setInset:(CGFloat)inset {
+ [self setInsets:(MASEdgeInsets){.top = inset, .left = inset, .bottom = inset, .right = inset}];
+}
+
+- (void)setOffset:(CGFloat)offset {
+ self.layoutConstant = offset;
+}
+
+- (void)setSizeOffset:(CGSize)sizeOffset {
+ NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute;
+ switch (layoutAttribute) {
+ case NSLayoutAttributeWidth:
+ self.layoutConstant = sizeOffset.width;
+ break;
+ case NSLayoutAttributeHeight:
+ self.layoutConstant = sizeOffset.height;
+ break;
+ default:
+ break;
+ }
+}
+
+- (void)setCenterOffset:(CGPoint)centerOffset {
+ NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute;
+ switch (layoutAttribute) {
+ case NSLayoutAttributeCenterX:
+ self.layoutConstant = centerOffset.x;
+ break;
+ case NSLayoutAttributeCenterY:
+ self.layoutConstant = centerOffset.y;
+ break;
+ default:
+ break;
+ }
+}
+
+#pragma mark - MASConstraint
+
+- (void)activate {
+ [self install];
+}
+
+- (void)deactivate {
+ [self uninstall];
+}
+
+- (void)install {
+ if (self.hasBeenInstalled) {
+ return;
+ }
+
+ if ([self supportsActiveProperty] && self.layoutConstraint) {
+ self.layoutConstraint.active = YES;
+ [self.firstViewAttribute.view.mas_installedConstraints addObject:self];
+ return;
+ }
+
+ MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item;
+ NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute;
+ MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item;
+ NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute;
+
+ // alignment attributes must have a secondViewAttribute
+ // therefore we assume that is refering to superview
+ // eg make.left.equalTo(@10)
+ if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) {
+ secondLayoutItem = self.firstViewAttribute.view.superview;
+ secondLayoutAttribute = firstLayoutAttribute;
+ }
+
+ MASLayoutConstraint *layoutConstraint
+ = [MASLayoutConstraint constraintWithItem:firstLayoutItem
+ attribute:firstLayoutAttribute
+ relatedBy:self.layoutRelation
+ toItem:secondLayoutItem
+ attribute:secondLayoutAttribute
+ multiplier:self.layoutMultiplier
+ constant:self.layoutConstant];
+
+ layoutConstraint.priority = self.layoutPriority;
+ layoutConstraint.mas_key = self.mas_key;
+
+ if (self.secondViewAttribute.view) {
+ MAS_VIEW *closestCommonSuperview = [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view];
+ NSAssert(closestCommonSuperview,
+ @"couldn't find a common superview for %@ and %@",
+ self.firstViewAttribute.view, self.secondViewAttribute.view);
+ self.installedView = closestCommonSuperview;
+ } else if (self.firstViewAttribute.isSizeAttribute) {
+ self.installedView = self.firstViewAttribute.view;
+ } else {
+ self.installedView = self.firstViewAttribute.view.superview;
+ }
+
+
+ MASLayoutConstraint *existingConstraint = nil;
+ if (self.updateExisting) {
+ existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];
+ }
+ if (existingConstraint) {
+ // just update the constant
+ existingConstraint.constant = layoutConstraint.constant;
+ self.layoutConstraint = existingConstraint;
+ } else {
+ [self.installedView addConstraint:layoutConstraint];
+ self.layoutConstraint = layoutConstraint;
+ [firstLayoutItem.mas_installedConstraints addObject:self];
+ }
+}
+
+- (MASLayoutConstraint *)layoutConstraintSimilarTo:(MASLayoutConstraint *)layoutConstraint {
+ // check if any constraints are the same apart from the only mutable property constant
+
+ // go through constraints in reverse as we do not want to match auto-resizing or interface builder constraints
+ // and they are likely to be added first.
+ for (NSLayoutConstraint *existingConstraint in self.installedView.constraints.reverseObjectEnumerator) {
+ if (![existingConstraint isKindOfClass:MASLayoutConstraint.class]) continue;
+ if (existingConstraint.firstItem != layoutConstraint.firstItem) continue;
+ if (existingConstraint.secondItem != layoutConstraint.secondItem) continue;
+ if (existingConstraint.firstAttribute != layoutConstraint.firstAttribute) continue;
+ if (existingConstraint.secondAttribute != layoutConstraint.secondAttribute) continue;
+ if (existingConstraint.relation != layoutConstraint.relation) continue;
+ if (existingConstraint.multiplier != layoutConstraint.multiplier) continue;
+ if (existingConstraint.priority != layoutConstraint.priority) continue;
+
+ return (id)existingConstraint;
+ }
+ return nil;
+}
+
+- (void)uninstall {
+ if ([self supportsActiveProperty]) {
+ self.layoutConstraint.active = NO;
+ [self.firstViewAttribute.view.mas_installedConstraints removeObject:self];
+ return;
+ }
+
+ [self.installedView removeConstraint:self.layoutConstraint];
+ self.layoutConstraint = nil;
+ self.installedView = nil;
+
+ [self.firstViewAttribute.view.mas_installedConstraints removeObject:self];
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/Masonry.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/Masonry.h
new file mode 100755
index 0000000..d1bd579
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/Masonry.h
@@ -0,0 +1,29 @@
+//
+// Masonry.h
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for Masonry.
+FOUNDATION_EXPORT double MasonryVersionNumber;
+
+//! Project version string for Masonry.
+FOUNDATION_EXPORT const unsigned char MasonryVersionString[];
+
+#import "MASUtilities.h"
+#import "View+MASAdditions.h"
+#import "View+MASShorthandAdditions.h"
+#import "ViewController+MASAdditions.h"
+#import "NSArray+MASAdditions.h"
+#import "NSArray+MASShorthandAdditions.h"
+#import "MASConstraint.h"
+#import "MASCompositeConstraint.h"
+#import "MASViewAttribute.h"
+#import "MASViewConstraint.h"
+#import "MASConstraintMaker.h"
+#import "MASLayoutConstraint.h"
+#import "NSLayoutConstraint+MASDebugAdditions.h"
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.h
new file mode 100755
index 0000000..587618d
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.h
@@ -0,0 +1,72 @@
+//
+// NSArray+MASAdditions.h
+//
+//
+// Created by Daniel Hammond on 11/26/13.
+//
+//
+
+#import "MASUtilities.h"
+#import "MASConstraintMaker.h"
+#import "MASViewAttribute.h"
+
+typedef NS_ENUM(NSUInteger, MASAxisType) {
+ MASAxisTypeHorizontal,
+ MASAxisTypeVertical
+};
+
+@interface NSArray (MASAdditions)
+
+/**
+ * Creates a MASConstraintMaker with each view in the callee.
+ * Any constraints defined are added to the view or the appropriate superview once the block has finished executing on each view
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to each view.
+ *
+ * @return Array of created MASConstraints
+ */
+- (NSArray *)mas_makeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+/**
+ * Creates a MASConstraintMaker with each view in the callee.
+ * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view.
+ * If an existing constraint exists then it will be updated instead.
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to each view.
+ *
+ * @return Array of created/updated MASConstraints
+ */
+- (NSArray *)mas_updateConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+/**
+ * Creates a MASConstraintMaker with each view in the callee.
+ * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view.
+ * All constraints previously installed for the views will be removed.
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to each view.
+ *
+ * @return Array of created/updated MASConstraints
+ */
+- (NSArray *)mas_remakeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+/**
+ * distribute with fixed spacing
+ *
+ * @param axisType which axis to distribute items along
+ * @param fixedSpacing the spacing between each item
+ * @param leadSpacing the spacing before the first item and the container
+ * @param tailSpacing the spacing after the last item and the container
+ */
+- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;
+
+/**
+ * distribute with fixed item size
+ *
+ * @param axisType which axis to distribute items along
+ * @param fixedItemLength the fixed length of each item
+ * @param leadSpacing the spacing before the first item and the container
+ * @param tailSpacing the spacing after the last item and the container
+ */
+- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.m
new file mode 100755
index 0000000..831d8cd
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASAdditions.m
@@ -0,0 +1,162 @@
+//
+// NSArray+MASAdditions.m
+//
+//
+// Created by Daniel Hammond on 11/26/13.
+//
+//
+
+#import "NSArray+MASAdditions.h"
+#import "View+MASAdditions.h"
+
+@implementation NSArray (MASAdditions)
+
+- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block {
+ NSMutableArray *constraints = [NSMutableArray array];
+ for (MAS_VIEW *view in self) {
+ NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views");
+ [constraints addObjectsFromArray:[view mas_makeConstraints:block]];
+ }
+ return constraints;
+}
+
+- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block {
+ NSMutableArray *constraints = [NSMutableArray array];
+ for (MAS_VIEW *view in self) {
+ NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views");
+ [constraints addObjectsFromArray:[view mas_updateConstraints:block]];
+ }
+ return constraints;
+}
+
+- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block {
+ NSMutableArray *constraints = [NSMutableArray array];
+ for (MAS_VIEW *view in self) {
+ NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views");
+ [constraints addObjectsFromArray:[view mas_remakeConstraints:block]];
+ }
+ return constraints;
+}
+
+- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing {
+ if (self.count < 2) {
+ NSAssert(self.count>1,@"views to distribute need to bigger than one");
+ return;
+ }
+
+ MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews];
+ if (axisType == MASAxisTypeHorizontal) {
+ MAS_VIEW *prev;
+ for (int i = 0; i < self.count; i++) {
+ MAS_VIEW *v = self[i];
+ [v mas_makeConstraints:^(MASConstraintMaker *make) {
+ if (prev) {
+ make.width.equalTo(prev);
+ make.left.equalTo(prev.mas_right).offset(fixedSpacing);
+ if (i == self.count - 1) {//last one
+ make.right.equalTo(tempSuperView).offset(-tailSpacing);
+ }
+ }
+ else {//first one
+ make.left.equalTo(tempSuperView).offset(leadSpacing);
+ }
+
+ }];
+ prev = v;
+ }
+ }
+ else {
+ MAS_VIEW *prev;
+ for (int i = 0; i < self.count; i++) {
+ MAS_VIEW *v = self[i];
+ [v mas_makeConstraints:^(MASConstraintMaker *make) {
+ if (prev) {
+ make.height.equalTo(prev);
+ make.top.equalTo(prev.mas_bottom).offset(fixedSpacing);
+ if (i == self.count - 1) {//last one
+ make.bottom.equalTo(tempSuperView).offset(-tailSpacing);
+ }
+ }
+ else {//first one
+ make.top.equalTo(tempSuperView).offset(leadSpacing);
+ }
+
+ }];
+ prev = v;
+ }
+ }
+}
+
+- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing {
+ if (self.count < 2) {
+ NSAssert(self.count>1,@"views to distribute need to bigger than one");
+ return;
+ }
+
+ MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews];
+ if (axisType == MASAxisTypeHorizontal) {
+ MAS_VIEW *prev;
+ for (int i = 0; i < self.count; i++) {
+ MAS_VIEW *v = self[i];
+ [v mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.width.equalTo(@(fixedItemLength));
+ if (prev) {
+ if (i == self.count - 1) {//last one
+ make.right.equalTo(tempSuperView).offset(-tailSpacing);
+ }
+ else {
+ CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1));
+ make.right.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset);
+ }
+ }
+ else {//first one
+ make.left.equalTo(tempSuperView).offset(leadSpacing);
+ }
+ }];
+ prev = v;
+ }
+ }
+ else {
+ MAS_VIEW *prev;
+ for (int i = 0; i < self.count; i++) {
+ MAS_VIEW *v = self[i];
+ [v mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.height.equalTo(@(fixedItemLength));
+ if (prev) {
+ if (i == self.count - 1) {//last one
+ make.bottom.equalTo(tempSuperView).offset(-tailSpacing);
+ }
+ else {
+ CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1));
+ make.bottom.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset);
+ }
+ }
+ else {//first one
+ make.top.equalTo(tempSuperView).offset(leadSpacing);
+ }
+ }];
+ prev = v;
+ }
+ }
+}
+
+- (MAS_VIEW *)mas_commonSuperviewOfViews
+{
+ MAS_VIEW *commonSuperview = nil;
+ MAS_VIEW *previousView = nil;
+ for (id object in self) {
+ if ([object isKindOfClass:[MAS_VIEW class]]) {
+ MAS_VIEW *view = (MAS_VIEW *)object;
+ if (previousView) {
+ commonSuperview = [view mas_closestCommonSuperview:commonSuperview];
+ } else {
+ commonSuperview = view;
+ }
+ previousView = view;
+ }
+ }
+ NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy.");
+ return commonSuperview;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASShorthandAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASShorthandAdditions.h
new file mode 100755
index 0000000..8b47369
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSArray+MASShorthandAdditions.h
@@ -0,0 +1,41 @@
+//
+// NSArray+MASShorthandAdditions.h
+// Masonry
+//
+// Created by Jonas Budelmann on 22/07/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "NSArray+MASAdditions.h"
+
+#ifdef MAS_SHORTHAND
+
+/**
+ * Shorthand array additions without the 'mas_' prefixes,
+ * only enabled if MAS_SHORTHAND is defined
+ */
+@interface NSArray (MASShorthandAdditions)
+
+- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block;
+- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block;
+- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block;
+
+@end
+
+@implementation NSArray (MASShorthandAdditions)
+
+- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *))block {
+ return [self mas_makeConstraints:block];
+}
+
+- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *))block {
+ return [self mas_updateConstraints:block];
+}
+
+- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *))block {
+ return [self mas_remakeConstraints:block];
+}
+
+@end
+
+#endif
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.h
new file mode 100755
index 0000000..1279b4f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.h
@@ -0,0 +1,16 @@
+//
+// NSLayoutConstraint+MASDebugAdditions.h
+// Masonry
+//
+// Created by Jonas Budelmann on 3/08/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "MASUtilities.h"
+
+/**
+ * makes debug and log output of NSLayoutConstraints more readable
+ */
+@interface NSLayoutConstraint (MASDebugAdditions)
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.m
new file mode 100755
index 0000000..ab539a2
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/NSLayoutConstraint+MASDebugAdditions.m
@@ -0,0 +1,146 @@
+//
+// NSLayoutConstraint+MASDebugAdditions.m
+// Masonry
+//
+// Created by Jonas Budelmann on 3/08/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "NSLayoutConstraint+MASDebugAdditions.h"
+#import "MASConstraint.h"
+#import "MASLayoutConstraint.h"
+
+@implementation NSLayoutConstraint (MASDebugAdditions)
+
+#pragma mark - description maps
+
++ (NSDictionary *)layoutRelationDescriptionsByValue {
+ static dispatch_once_t once;
+ static NSDictionary *descriptionMap;
+ dispatch_once(&once, ^{
+ descriptionMap = @{
+ @(NSLayoutRelationEqual) : @"==",
+ @(NSLayoutRelationGreaterThanOrEqual) : @">=",
+ @(NSLayoutRelationLessThanOrEqual) : @"<=",
+ };
+ });
+ return descriptionMap;
+}
+
++ (NSDictionary *)layoutAttributeDescriptionsByValue {
+ static dispatch_once_t once;
+ static NSDictionary *descriptionMap;
+ dispatch_once(&once, ^{
+ descriptionMap = @{
+ @(NSLayoutAttributeTop) : @"top",
+ @(NSLayoutAttributeLeft) : @"left",
+ @(NSLayoutAttributeBottom) : @"bottom",
+ @(NSLayoutAttributeRight) : @"right",
+ @(NSLayoutAttributeLeading) : @"leading",
+ @(NSLayoutAttributeTrailing) : @"trailing",
+ @(NSLayoutAttributeWidth) : @"width",
+ @(NSLayoutAttributeHeight) : @"height",
+ @(NSLayoutAttributeCenterX) : @"centerX",
+ @(NSLayoutAttributeCenterY) : @"centerY",
+ @(NSLayoutAttributeBaseline) : @"baseline",
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+ @(NSLayoutAttributeFirstBaseline) : @"firstBaseline",
+ @(NSLayoutAttributeLastBaseline) : @"lastBaseline",
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+ @(NSLayoutAttributeLeftMargin) : @"leftMargin",
+ @(NSLayoutAttributeRightMargin) : @"rightMargin",
+ @(NSLayoutAttributeTopMargin) : @"topMargin",
+ @(NSLayoutAttributeBottomMargin) : @"bottomMargin",
+ @(NSLayoutAttributeLeadingMargin) : @"leadingMargin",
+ @(NSLayoutAttributeTrailingMargin) : @"trailingMargin",
+ @(NSLayoutAttributeCenterXWithinMargins) : @"centerXWithinMargins",
+ @(NSLayoutAttributeCenterYWithinMargins) : @"centerYWithinMargins",
+#endif
+
+ };
+
+ });
+ return descriptionMap;
+}
+
+
++ (NSDictionary *)layoutPriorityDescriptionsByValue {
+ static dispatch_once_t once;
+ static NSDictionary *descriptionMap;
+ dispatch_once(&once, ^{
+#if TARGET_OS_IPHONE || TARGET_OS_TV
+ descriptionMap = @{
+ @(MASLayoutPriorityDefaultHigh) : @"high",
+ @(MASLayoutPriorityDefaultLow) : @"low",
+ @(MASLayoutPriorityDefaultMedium) : @"medium",
+ @(MASLayoutPriorityRequired) : @"required",
+ @(MASLayoutPriorityFittingSizeLevel) : @"fitting size",
+ };
+#elif TARGET_OS_MAC
+ descriptionMap = @{
+ @(MASLayoutPriorityDefaultHigh) : @"high",
+ @(MASLayoutPriorityDragThatCanResizeWindow) : @"drag can resize window",
+ @(MASLayoutPriorityDefaultMedium) : @"medium",
+ @(MASLayoutPriorityWindowSizeStayPut) : @"window size stay put",
+ @(MASLayoutPriorityDragThatCannotResizeWindow) : @"drag cannot resize window",
+ @(MASLayoutPriorityDefaultLow) : @"low",
+ @(MASLayoutPriorityFittingSizeCompression) : @"fitting size",
+ @(MASLayoutPriorityRequired) : @"required",
+ };
+#endif
+ });
+ return descriptionMap;
+}
+
+#pragma mark - description override
+
++ (NSString *)descriptionForObject:(id)obj {
+ if ([obj respondsToSelector:@selector(mas_key)] && [obj mas_key]) {
+ return [NSString stringWithFormat:@"%@:%@", [obj class], [obj mas_key]];
+ }
+ return [NSString stringWithFormat:@"%@:%p", [obj class], obj];
+}
+
+- (NSString *)description {
+ NSMutableString *description = [[NSMutableString alloc] initWithString:@"<"];
+
+ [description appendString:[self.class descriptionForObject:self]];
+
+ [description appendFormat:@" %@", [self.class descriptionForObject:self.firstItem]];
+ if (self.firstAttribute != NSLayoutAttributeNotAnAttribute) {
+ [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.firstAttribute)]];
+ }
+
+ [description appendFormat:@" %@", self.class.layoutRelationDescriptionsByValue[@(self.relation)]];
+
+ if (self.secondItem) {
+ [description appendFormat:@" %@", [self.class descriptionForObject:self.secondItem]];
+ }
+ if (self.secondAttribute != NSLayoutAttributeNotAnAttribute) {
+ [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.secondAttribute)]];
+ }
+
+ if (self.multiplier != 1) {
+ [description appendFormat:@" * %g", self.multiplier];
+ }
+
+ if (self.secondAttribute == NSLayoutAttributeNotAnAttribute) {
+ [description appendFormat:@" %g", self.constant];
+ } else {
+ if (self.constant) {
+ [description appendFormat:@" %@ %g", (self.constant < 0 ? @"-" : @"+"), ABS(self.constant)];
+ }
+ }
+
+ if (self.priority != MASLayoutPriorityRequired) {
+ [description appendFormat:@" ^%@", self.class.layoutPriorityDescriptionsByValue[@(self.priority)] ?: [NSNumber numberWithDouble:self.priority]];
+ }
+
+ [description appendString:@">"];
+ return description;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.h
new file mode 100755
index 0000000..f7343d2
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.h
@@ -0,0 +1,111 @@
+//
+// UIView+MASAdditions.h
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "MASUtilities.h"
+#import "MASConstraintMaker.h"
+#import "MASViewAttribute.h"
+
+/**
+ * Provides constraint maker block
+ * and convience methods for creating MASViewAttribute which are view + NSLayoutAttribute pairs
+ */
+@interface MAS_VIEW (MASAdditions)
+
+/**
+ * following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute
+ */
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
+@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0));
+
+#endif
+
+/**
+ * a key to associate with this view
+ */
+@property (nonatomic, strong) id mas_key;
+
+/**
+ * Finds the closest common superview between this view and another view
+ *
+ * @param view other view
+ *
+ * @return returns nil if common superview could not be found
+ */
+- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view;
+
+/**
+ * Creates a MASConstraintMaker with the callee view.
+ * Any constraints defined are added to the view or the appropriate superview once the block has finished executing
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to the view.
+ *
+ * @return Array of created MASConstraints
+ */
+- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+/**
+ * Creates a MASConstraintMaker with the callee view.
+ * Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
+ * If an existing constraint exists then it will be updated instead.
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to the view.
+ *
+ * @return Array of created/updated MASConstraints
+ */
+- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+/**
+ * Creates a MASConstraintMaker with the callee view.
+ * Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
+ * All constraints previously installed for the view will be removed.
+ *
+ * @param block scope within which you can build up the constraints which you wish to apply to the view.
+ *
+ * @return Array of created/updated MASConstraints
+ */
+- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.m
new file mode 100755
index 0000000..4fa07b4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASAdditions.m
@@ -0,0 +1,186 @@
+//
+// UIView+MASAdditions.m
+// Masonry
+//
+// Created by Jonas Budelmann on 20/07/13.
+// Copyright (c) 2013 cloudling. All rights reserved.
+//
+
+#import "View+MASAdditions.h"
+#import <objc/runtime.h>
+
+@implementation MAS_VIEW (MASAdditions)
+
+- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
+ self.translatesAutoresizingMaskIntoConstraints = NO;
+ MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
+ block(constraintMaker);
+ return [constraintMaker install];
+}
+
+- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {
+ self.translatesAutoresizingMaskIntoConstraints = NO;
+ MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
+ constraintMaker.updateExisting = YES;
+ block(constraintMaker);
+ return [constraintMaker install];
+}
+
+- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block {
+ self.translatesAutoresizingMaskIntoConstraints = NO;
+ MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
+ constraintMaker.removeExisting = YES;
+ block(constraintMaker);
+ return [constraintMaker install];
+}
+
+#pragma mark - NSLayoutAttribute properties
+
+- (MASViewAttribute *)mas_left {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeft];
+}
+
+- (MASViewAttribute *)mas_top {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTop];
+}
+
+- (MASViewAttribute *)mas_right {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRight];
+}
+
+- (MASViewAttribute *)mas_bottom {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottom];
+}
+
+- (MASViewAttribute *)mas_leading {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeading];
+}
+
+- (MASViewAttribute *)mas_trailing {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailing];
+}
+
+- (MASViewAttribute *)mas_width {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeWidth];
+}
+
+- (MASViewAttribute *)mas_height {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeHeight];
+}
+
+- (MASViewAttribute *)mas_centerX {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterX];
+}
+
+- (MASViewAttribute *)mas_centerY {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterY];
+}
+
+- (MASViewAttribute *)mas_baseline {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBaseline];
+}
+
+- (MASViewAttribute *(^)(NSLayoutAttribute))mas_attribute
+{
+ return ^(NSLayoutAttribute attr) {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:attr];
+ };
+}
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+- (MASViewAttribute *)mas_firstBaseline {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeFirstBaseline];
+}
+- (MASViewAttribute *)mas_lastBaseline {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLastBaseline];
+}
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+- (MASViewAttribute *)mas_leftMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeftMargin];
+}
+
+- (MASViewAttribute *)mas_rightMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRightMargin];
+}
+
+- (MASViewAttribute *)mas_topMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTopMargin];
+}
+
+- (MASViewAttribute *)mas_bottomMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottomMargin];
+}
+
+- (MASViewAttribute *)mas_leadingMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeadingMargin];
+}
+
+- (MASViewAttribute *)mas_trailingMargin {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailingMargin];
+}
+
+- (MASViewAttribute *)mas_centerXWithinMargins {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterXWithinMargins];
+}
+
+- (MASViewAttribute *)mas_centerYWithinMargins {
+ return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterYWithinMargins];
+}
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
+
+- (MASViewAttribute *)mas_safeAreaLayoutGuide {
+ return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom];
+}
+- (MASViewAttribute *)mas_safeAreaLayoutGuideTop {
+ return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeTop];
+}
+- (MASViewAttribute *)mas_safeAreaLayoutGuideBottom {
+ return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom];
+}
+- (MASViewAttribute *)mas_safeAreaLayoutGuideLeft {
+ return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeLeft];
+}
+- (MASViewAttribute *)mas_safeAreaLayoutGuideRight {
+ return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeRight];
+}
+
+#endif
+
+#pragma mark - associated properties
+
+- (id)mas_key {
+ return objc_getAssociatedObject(self, @selector(mas_key));
+}
+
+- (void)setMas_key:(id)key {
+ objc_setAssociatedObject(self, @selector(mas_key), key, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+#pragma mark - heirachy
+
+- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view {
+ MAS_VIEW *closestCommonSuperview = nil;
+
+ MAS_VIEW *secondViewSuperview = view;
+ while (!closestCommonSuperview && secondViewSuperview) {
+ MAS_VIEW *firstViewSuperview = self;
+ while (!closestCommonSuperview && firstViewSuperview) {
+ if (secondViewSuperview == firstViewSuperview) {
+ closestCommonSuperview = secondViewSuperview;
+ }
+ firstViewSuperview = firstViewSuperview.superview;
+ }
+ secondViewSuperview = secondViewSuperview.superview;
+ }
+ return closestCommonSuperview;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASShorthandAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASShorthandAdditions.h
new file mode 100755
index 0000000..1c19a94
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/View+MASShorthandAdditions.h
@@ -0,0 +1,133 @@
+//
+// UIView+MASShorthandAdditions.h
+// Masonry
+//
+// Created by Jonas Budelmann on 22/07/13.
+// Copyright (c) 2013 Jonas Budelmann. All rights reserved.
+//
+
+#import "View+MASAdditions.h"
+
+#ifdef MAS_SHORTHAND
+
+/**
+ * Shorthand view additions without the 'mas_' prefixes,
+ * only enabled if MAS_SHORTHAND is defined
+ */
+@interface MAS_VIEW (MASShorthandAdditions)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *left;
+@property (nonatomic, strong, readonly) MASViewAttribute *top;
+@property (nonatomic, strong, readonly) MASViewAttribute *right;
+@property (nonatomic, strong, readonly) MASViewAttribute *bottom;
+@property (nonatomic, strong, readonly) MASViewAttribute *leading;
+@property (nonatomic, strong, readonly) MASViewAttribute *trailing;
+@property (nonatomic, strong, readonly) MASViewAttribute *width;
+@property (nonatomic, strong, readonly) MASViewAttribute *height;
+@property (nonatomic, strong, readonly) MASViewAttribute *centerX;
+@property (nonatomic, strong, readonly) MASViewAttribute *centerY;
+@property (nonatomic, strong, readonly) MASViewAttribute *baseline;
+@property (nonatomic, strong, readonly) MASViewAttribute *(^attribute)(NSLayoutAttribute attr);
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *firstBaseline;
+@property (nonatomic, strong, readonly) MASViewAttribute *lastBaseline;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *leftMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *rightMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *topMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *bottomMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *leadingMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *trailingMargin;
+@property (nonatomic, strong, readonly) MASViewAttribute *centerXWithinMargins;
+@property (nonatomic, strong, readonly) MASViewAttribute *centerYWithinMargins;
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
+
+@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0));
+@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0));
+
+#endif
+
+- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block;
+- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block;
+- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block;
+
+@end
+
+#define MAS_ATTR_FORWARD(attr) \
+- (MASViewAttribute *)attr { \
+ return [self mas_##attr]; \
+}
+
+@implementation MAS_VIEW (MASShorthandAdditions)
+
+MAS_ATTR_FORWARD(top);
+MAS_ATTR_FORWARD(left);
+MAS_ATTR_FORWARD(bottom);
+MAS_ATTR_FORWARD(right);
+MAS_ATTR_FORWARD(leading);
+MAS_ATTR_FORWARD(trailing);
+MAS_ATTR_FORWARD(width);
+MAS_ATTR_FORWARD(height);
+MAS_ATTR_FORWARD(centerX);
+MAS_ATTR_FORWARD(centerY);
+MAS_ATTR_FORWARD(baseline);
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+
+MAS_ATTR_FORWARD(firstBaseline);
+MAS_ATTR_FORWARD(lastBaseline);
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
+
+MAS_ATTR_FORWARD(leftMargin);
+MAS_ATTR_FORWARD(rightMargin);
+MAS_ATTR_FORWARD(topMargin);
+MAS_ATTR_FORWARD(bottomMargin);
+MAS_ATTR_FORWARD(leadingMargin);
+MAS_ATTR_FORWARD(trailingMargin);
+MAS_ATTR_FORWARD(centerXWithinMargins);
+MAS_ATTR_FORWARD(centerYWithinMargins);
+
+#endif
+
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
+
+MAS_ATTR_FORWARD(safeAreaLayoutGuideTop);
+MAS_ATTR_FORWARD(safeAreaLayoutGuideBottom);
+MAS_ATTR_FORWARD(safeAreaLayoutGuideLeft);
+MAS_ATTR_FORWARD(safeAreaLayoutGuideRight);
+
+#endif
+
+- (MASViewAttribute *(^)(NSLayoutAttribute))attribute {
+ return [self mas_attribute];
+}
+
+- (NSArray *)makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block {
+ return [self mas_makeConstraints:block];
+}
+
+- (NSArray *)updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block {
+ return [self mas_updateConstraints:block];
+}
+
+- (NSArray *)remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block {
+ return [self mas_remakeConstraints:block];
+}
+
+@end
+
+#endif
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.h
new file mode 100755
index 0000000..79fd1fa
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.h
@@ -0,0 +1,30 @@
+//
+// UIViewController+MASAdditions.h
+// Masonry
+//
+// Created by Craig Siemens on 2015-06-23.
+//
+//
+
+#import "MASUtilities.h"
+#import "MASConstraintMaker.h"
+#import "MASViewAttribute.h"
+
+#ifdef MAS_VIEW_CONTROLLER
+
+@interface MAS_VIEW_CONTROLLER (MASAdditions)
+
+/**
+ * following properties return a new MASViewAttribute with appropriate UILayoutGuide and NSLayoutAttribute
+ */
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuide;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuide;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideTop;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideBottom;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideTop;
+@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideBottom;
+
+
+@end
+
+#endif
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.m
new file mode 100755
index 0000000..2f5139f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/Masonry/ViewController+MASAdditions.m
@@ -0,0 +1,39 @@
+//
+// UIViewController+MASAdditions.m
+// Masonry
+//
+// Created by Craig Siemens on 2015-06-23.
+//
+//
+
+#import "ViewController+MASAdditions.h"
+
+#ifdef MAS_VIEW_CONTROLLER
+
+@implementation MAS_VIEW_CONTROLLER (MASAdditions)
+
+- (MASViewAttribute *)mas_topLayoutGuide {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom];
+}
+- (MASViewAttribute *)mas_topLayoutGuideTop {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeTop];
+}
+- (MASViewAttribute *)mas_topLayoutGuideBottom {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom];
+}
+
+- (MASViewAttribute *)mas_bottomLayoutGuide {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop];
+}
+- (MASViewAttribute *)mas_bottomLayoutGuideTop {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop];
+}
+- (MASViewAttribute *)mas_bottomLayoutGuideBottom {
+ return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeBottom];
+}
+
+
+
+@end
+
+#endif
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.h
new file mode 100755
index 0000000..b679036
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.h
@@ -0,0 +1,32 @@
+//
+// HQEditImageActionView.h
+// CivilAviation
+//
+// Created by iOS on 2019/3/29.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "Masonry.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class HQEditImageActionView;
+@protocol HQEditImageActionViewDelegate <NSObject>
+
+- (void)action:(HQEditImageActionView *)action didClickButton:(UIButton *)button atIndex:(NSInteger)index;
+
+@end
+
+@interface HQEditImageActionView : UIView
+
+@property (nonatomic, weak) id <HQEditImageActionViewDelegate> delegate;
+
+//@property (nonatomic, strong) UIButton *rotateButton;
+@property (nonatomic, strong) UIButton *cancelButton;
+//@property (nonatomic, strong) UIButton *originButton;
+@property (nonatomic, strong) UIButton *finishButton;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.m
new file mode 100755
index 0000000..ac5a15c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageActionView.m
@@ -0,0 +1,144 @@
+//
+// HQEditImageActionView.m
+// CivilAviation
+//
+// Created by iOS on 2019/3/29.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import "HQEditImageActionView.h"
+
+@interface HQEditImageActionView ()
+
+@property (nonatomic, strong) UIView *line;
+
+@end
+
+@implementation HQEditImageActionView
+
+- (instancetype)init {
+ if (self = [super init]) {
+
+ self.backgroundColor = [UIColor colorWithWhite:0 alpha:.85f];
+
+// [self addSubview:self.rotateButton];
+ [self addSubview:self.cancelButton];
+// [self addSubview:self.originButton];
+ [self addSubview:self.finishButton];
+
+ [self addSubview:self.line];
+
+ [self makeConstraints];
+ }
+ return self;
+}
+
+- (void)makeConstraints {
+
+// [self.rotateButton mas_makeConstraints:^(MASConstraintMaker *make) {
+// make.left.equalTo(@0);
+// make.top.equalTo(@0);
+// make.width.equalTo(@(25 + 40));
+// make.height.equalTo(@49);
+// }];
+
+ [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.left.equalTo(@20);
+ make.width.equalTo(@50);
+ make.height.equalTo(@49);
+ make.top.equalTo(@49);
+ }];
+
+// [self.originButton mas_makeConstraints:^(MASConstraintMaker *make) {
+// make.width.equalTo(@50);
+// make.height.equalTo(@49);
+// make.top.equalTo(@49);
+// make.centerX.equalTo(@0);
+// }];
+
+ [self.finishButton mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.right.equalTo(@-20);
+ make.width.equalTo(@50);
+ make.height.equalTo(@49);
+ make.top.equalTo(@49);
+ }];
+
+ [self.line mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.top.equalTo(@49);
+ make.left.right.equalTo(@0);
+ make.height.equalTo(@.7f);
+ }];
+}
+
+#pragma mrak - event response
+- (void)buttonAction:(UIButton *)button {
+ if ([self.delegate respondsToSelector:@selector(action:didClickButton:atIndex:)]) {
+ [self.delegate action:self didClickButton:button atIndex:button.tag];
+ }
+}
+
+#pragma mark - getter & setter
+//- (UIButton *)rotateButton {
+// if (!_rotateButton) {
+// _rotateButton = [[UIButton alloc] init];
+//
+// [_rotateButton setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ic_rotate_90_degrees_ccw" ofType:@"png"]] forState:UIControlStateNormal];
+// _rotateButton.tag = 0;
+// _rotateButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
+// [_rotateButton.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
+// make.width.height.equalTo(@25);
+// make.center.equalTo(@0);
+// }];
+// [_rotateButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
+// }
+// return _rotateButton;
+//}
+
+- (UIButton *)cancelButton {
+ if (!_cancelButton) {
+ _cancelButton = [[UIButton alloc] init];
+
+ [_cancelButton setTitle:@"鍙栨秷" forState:UIControlStateNormal];
+ [_cancelButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
+ _cancelButton.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:16];
+ _cancelButton.tag = 1;
+ [_cancelButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
+ }
+ return _cancelButton;
+}
+
+//- (UIButton *)originButton {
+// if (!_originButton) {
+// _originButton = [[UIButton alloc] init];
+//
+// [_originButton setTitle:@"杩樺師" forState:UIControlStateNormal];
+// [_originButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
+// _originButton.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:16];
+// _originButton.tag = 2;
+// [_originButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
+// }
+// return _originButton;
+//}
+
+- (UIButton *)finishButton {
+ if (!_finishButton) {
+ _finishButton = [[UIButton alloc] init];
+
+ [_finishButton setTitle:@"瀹屾垚" forState:UIControlStateNormal];
+ [_finishButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
+ _finishButton.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:16];
+ _finishButton.tag = 3;
+ [_finishButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
+ }
+ return _finishButton;
+}
+
+- (UIView *)line {
+ if (!_line) {
+ _line = [[UIView alloc] init];
+ _line.backgroundColor = [UIColor colorWithWhite:1 alpha:.3f];
+ }
+ return _line;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.h
new file mode 100755
index 0000000..bf9d2fe
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.h
@@ -0,0 +1,39 @@
+//
+// HQEditImageCaptureView.h
+// CivilAviation
+//
+// Created by iOS on 2019/4/1.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "Masonry.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HQEditImageCaptureView : UIView
+
+@property (nonatomic, weak) UIImageView *imageView;
+@property (nonatomic, weak) UIView *captureView;
+
+@property (nonatomic, assign) NSInteger rotateTimes;
+
+
+/**
+ 鎴彇View鑾峰彇鍥剧墖
+
+ @return View涓殑鍥剧墖
+ */
+- (UIImage *)captureImage;
+
+
+/**
+ 鎴彇妗嗗搴斿師鍥剧墖
+
+ @return 鍘熷浘鐗�
+ */
+- (UIImage *)captureOriginalImage;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.m
new file mode 100755
index 0000000..01e4c32
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageCaptureView.m
@@ -0,0 +1,87 @@
+//
+// HQEditImageCaptureView.m
+// CivilAviation
+//
+// Created by iOS on 2019/4/1.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import "HQEditImageCaptureView.h"
+
+@implementation HQEditImageCaptureView
+
+- (instancetype)init {
+ if (self = [super init]) {
+ self.layer.masksToBounds = NO;
+ }
+ return self;
+}
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+ UIView *view = [super hitTest:point withEvent:event];
+ if (view) {
+ return view;
+ } else {
+ return self.captureView;
+ }
+}
+
+- (UIImage *)captureImage {
+
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.frame.size.width,self.frame.size.height), NO, 0.0);
+ [self.layer renderInContext:UIGraphicsGetCurrentContext()];
+ UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ return viewImage;
+}
+
+- (UIImage *)captureOriginalImage {
+ UIScrollView *scrollView = (UIScrollView *)self.captureView;
+ UIImage *orignaImage = self.imageView.image;
+
+ CGFloat width = (self.captureView.frame.size.width/self.imageView.frame.size.width)*orignaImage.size.width;
+ CGFloat height = (scrollView.frame.size.height/scrollView.frame.size.width)*width;
+ CGSize captureSize = CGSizeMake(width, height);
+
+ CGFloat x = (scrollView.contentOffset.x/self.imageView.frame.size.width)*orignaImage.size.width;
+ CGFloat y = (scrollView.contentOffset.y/self.imageView.frame.size.height)*orignaImage.size.height;
+ CGPoint captureOffset = CGPointMake(x, y);
+
+ // 闀垮寰皟
+ if (x + width >= self.imageView.frame.size.width) {
+ x = self.imageView.frame.size.width - width;
+ }
+ if (y + height >= self.imageView.frame.size.height) {
+ y = self.imageView.frame.size.height - height;
+ }
+
+ CGRect captureRect;
+ if (self.rotateTimes % 2 == 0) {
+ captureRect = CGRectMake(captureOffset.x, captureOffset.y, captureSize.width, captureSize.height);
+ } else {
+ captureRect = CGRectMake(captureOffset.x, captureOffset.y, captureSize.height, captureSize.width);
+ }
+
+ CGImageRef temp = CGImageCreateWithImageInRect(orignaImage.CGImage, captureRect);
+ UIImage *result = [UIImage imageWithCGImage:temp];
+ CGImageRelease(temp);
+
+ result = [self rotateImage:result times:self.rotateTimes];
+
+ return result;
+}
+
+- (UIImage *)rotateImage:(UIImage *)image times:(NSInteger)rotateTimes {
+ if (rotateTimes % 4 == 0) {
+ return image;
+ } else if (rotateTimes % 4 == 1) {
+ return [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationLeft];
+ } else if (rotateTimes % 4 == 2) {
+ return [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationDown];
+ } else {
+ return [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationRight];
+ }
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.h
new file mode 100755
index 0000000..b4e3ab6
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.h
@@ -0,0 +1,41 @@
+//
+// HQEditImageEditView.h
+// CivilAviation
+//
+// Created by iOS on 2019/4/1.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "Masonry.h"
+
+NS_ASSUME_NONNULL_BEGIN
+@class HQEditImageEditView;
+@protocol HQEditImageEditViewDelegate <NSObject>
+
+- (void)editView:(HQEditImageEditView *)editView anchorPointIndex:(NSInteger)anchorPointIndex rect:(CGRect)rect;
+
+@end
+
+@interface HQEditImageEditView : UIView
+
+@property (nonatomic, weak) id <HQEditImageEditViewDelegate> delegate;
+
+@property (nonatomic, strong) UIView *maskView;
+
+@property (nonatomic, strong) UIView *preView;
+@property (nonatomic, strong) UIView *lineWrap;
+
+@property (nonatomic, strong) UIView *imageWrap;
+
+@property (nonatomic, assign) CGSize previewSize;
+@property (nonatomic, assign) UIEdgeInsets margin;
+@property (nonatomic, assign) BOOL maskViewAnimation;
+
+- (instancetype)initWithMargin:(UIEdgeInsets)margin size:(CGSize)size;
+
+- (void)maskViewShowWithDuration:(CGFloat)duration;
+- (void)maskViewHideWithDuration:(CGFloat)duration;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.m
new file mode 100755
index 0000000..9fda543
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HQImageEditViewController/View/HQEditImageEditView.m
@@ -0,0 +1,360 @@
+//
+// HQEditImageEditView.m
+// CivilAviation
+//
+// Created by iOS on 2019/4/1.
+// Copyright 漏 2019 iOS. All rights reserved.
+//
+
+#import "HQEditImageEditView.h"
+
+@interface HQEditImageEditView ()
+@property (nonatomic, assign) BOOL isMoving;
+@end
+
+@implementation HQEditImageEditView
+
+- (instancetype)initWithMargin:(UIEdgeInsets)margin size:(CGSize)size {
+ if (self = [super init]) {
+ self.layer.masksToBounds = NO;
+
+ self.margin = margin;
+ self.previewSize = size;
+
+ [self addSubview:self.maskView];
+ [self addSubview:self.preView];
+
+ [self.preView addSubview:self.lineWrap];
+ [self.lineWrap addSubview:self.imageWrap];
+
+ [self makeConstraints];
+ }
+ return self;
+}
+
+- (void)makeConstraints {
+ [self.maskView mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.top.equalTo(@(-self.margin.top));
+ make.left.equalTo(@(-self.margin.left));
+ make.width.equalTo(@(self.previewSize.width + self.margin.left + self.margin.right));
+ make.height.equalTo(@(self.previewSize.height + self.margin.top + self.margin.bottom));
+ }];
+
+ [self.preView mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.edges.equalTo(@0);
+ }];
+
+ [self.imageWrap mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.left.top.equalTo(@-1.5f);
+ make.bottom.right.equalTo(@1.5f);
+ }];
+}
+
+#pragma mark - public method
+- (void)maskViewShowWithDuration:(CGFloat)duration {
+ if (self.maskViewAnimation) {
+ [UIView animateWithDuration:duration animations:^{
+ self.maskView.alpha = 1;
+ }];
+ }
+}
+- (void)maskViewHideWithDuration:(CGFloat)duration {
+ if (self.maskViewAnimation) {
+ [UIView animateWithDuration:duration animations:^{
+ self.maskView.alpha = 0;
+ }];
+ }
+}
+
+#pragma mark - private method
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+ if (self.imageWrap.hidden == NO && self.isMoving == NO) {
+ for (UIView *view in self.imageWrap.subviews) {
+ CGRect rect = [view convertRect:view.bounds toView:self];
+ CGRect touchRect;
+
+ switch (view.tag) {
+ case 0: // 宸︿笂
+ touchRect = CGRectMake(rect.origin.x - rect.size.width, rect.origin.y - rect.size.height, rect.size.width*2, rect.size.height * 2);
+ break;
+
+ case 1: // 鍙充笂
+ touchRect = CGRectMake(rect.origin.x, rect.origin.y - rect.size.height, rect.size.width*2, rect.size.height * 2);
+ break;
+
+ case 2: // 宸︿笅
+ touchRect = CGRectMake(rect.origin.x - rect.size.width, rect.origin.y , rect.size.width*2, rect.size.height * 2);
+ break;
+
+ case 3: // 鍙充笅
+ touchRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width*2, rect.size.height * 2);
+ break;
+
+ default:
+ touchRect = CGRectZero;
+ break;
+ }
+ if (CGRectContainsPoint(touchRect, point)) {
+ return view;
+ }
+ }
+ }
+ return nil;
+}
+
+#pragma mark - touch
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ self.isMoving = YES;
+ [self maskViewHideWithDuration:.2f];
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ CGPoint current = [touches.anyObject locationInView:self];
+ CGPoint pre = [touches.anyObject previousLocationInView:self];
+
+ if (touches.anyObject.view.tag == 0) { // 宸︿笂
+ CGPoint move = CGPointMake(current.x - pre.x, current.y - pre.y);
+ CGFloat moveFit = fabs(move.x) > fabs(move.y) ? move.x : move.y;
+
+ CGFloat x = (self.lineWrap.frame.origin.x + moveFit) >= 0 ? (self.lineWrap.frame.origin.x + moveFit) : 0;
+ if (x >= self.previewSize.width/3.f) {
+ x = self.previewSize.width/3.f;
+ }
+ CGFloat y = (self.previewSize.height/self.previewSize.width) * x;
+ self.lineWrap.frame = CGRectMake(x, y, self.previewSize.width - x, self.previewSize.height - y);
+ } else if (touches.anyObject.view.tag == 1) { // 鍙充笂
+ CGPoint move = CGPointMake(pre.x - current.x, current.y - pre.y);
+ CGFloat moveFit = fabs(move.x) > fabs(move.y) ? move.x : move.y;
+
+ CGFloat width = (self.lineWrap.frame.size.width - moveFit) <= self.previewSize.width ? (self.lineWrap.frame.size.width - moveFit) : self.previewSize.width;
+ if (width <= self.previewSize.width*2/3.f) {
+ width = self.previewSize.width*2/3.f;
+ }
+ CGFloat height = (self.previewSize.height/self.previewSize.width) * width;
+ CGFloat y = self.previewSize.height - height;
+ self.lineWrap.frame = CGRectMake(0, y, width, height);
+ } else if (touches.anyObject.view.tag == 2) { // 宸︿笅
+ CGPoint move = CGPointMake(current.x - pre.x, pre.y - current.y);
+ CGFloat moveFit = fabs(move.x) > fabs(move.y) ? move.x : move.y;
+
+ CGFloat x = (self.lineWrap.frame.origin.x + moveFit) >= 0 ? (self.lineWrap.frame.origin.x + moveFit) : 0;
+ if (x >= self.previewSize.width/3.f) {
+ x = self.previewSize.width/3.f;
+ }
+ CGFloat height = self.previewSize.height - x*(self.previewSize.height/self.previewSize.width);
+ self.lineWrap.frame = CGRectMake(x, 0, self.previewSize.width - x, height);
+ } else if (touches.anyObject.view.tag == 3) { // 鍙充笅
+ CGPoint move = CGPointMake(pre.x - current.x, pre.y - current.y);
+ CGFloat moveFit = fabs(move.x) > fabs(move.y) ? move.x : move.y;
+
+ CGFloat width = (self.lineWrap.frame.size.width - moveFit) <= self.previewSize.width ? (self.lineWrap.frame.size.width - moveFit) : self.previewSize.width;
+ if (width <= self.previewSize.width*2/3.f) {
+ width = self.previewSize.width*2/3.f;
+ }
+ CGFloat height = (self.previewSize.height/self.previewSize.width) * width;;
+ self.lineWrap.frame = CGRectMake(0, 0, width, height);
+ }
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ [self.lineWrap mas_remakeConstraints:^(MASConstraintMaker *make) {
+ make.edges.equalTo(@0);
+ }];
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ if (!self.isMoving) {
+ return;
+ }
+
+ CGRect orignalFrame = self.lineWrap.frame;
+
+ self.imageWrap.hidden = YES;
+ if (touches.anyObject.view.tag == 0) { // 宸︿笂
+ self.lineWrap.layer.anchorPoint = CGPointMake(1, 1);
+ } else if (touches.anyObject.view.tag == 1) { // 鍙充笂
+ self.lineWrap.layer.anchorPoint = CGPointMake(0, 1);
+ } else if (touches.anyObject.view.tag == 2) { // 宸︿笅
+ self.lineWrap.layer.anchorPoint = CGPointMake(1, 0);
+ } else if (touches.anyObject.view.tag == 3) { // 鍙充笅
+ self.lineWrap.layer.anchorPoint = CGPointMake(0, 0);
+ }
+ self.lineWrap.frame = orignalFrame;
+ if ([self.delegate respondsToSelector:@selector(editView:anchorPointIndex:rect:)]) {
+ [self.delegate editView:self anchorPointIndex:touches.anyObject.view.tag rect:self.lineWrap.frame];
+ }
+
+
+ [UIView animateWithDuration:.2f animations:^{
+ self.lineWrap.transform = CGAffineTransformMakeScale(self.previewSize.width/self.lineWrap.frame.size.width, self.previewSize.height/self.lineWrap.frame.size.height);
+ } completion:^(BOOL finished) {
+ self.isMoving = NO;
+ self.imageWrap.hidden = NO;
+ self.lineWrap.layer.anchorPoint = CGPointMake(.5f, .5f);
+ self.lineWrap.transform = CGAffineTransformIdentity;
+ self.lineWrap.frame = CGRectMake(0, 0, self.previewSize.width, self.previewSize.height);
+ }];
+}
+
+#pragma mark - getter & setter
+- (UIView *)preView {
+ if (!_preView) {
+ _preView = [[UIView alloc] init];
+ }
+ return _preView;
+}
+
+- (UIView *)maskView {
+ if (!_maskView) {
+ _maskView = [[UIView alloc] init];
+ _maskView.backgroundColor = [UIColor colorWithWhite:0 alpha:.85f];
+
+ UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, self.previewSize.width + self.margin.left + self.margin.right, self.previewSize.height + self.margin.top + self.margin.bottom)];
+ [path appendPath:[[UIBezierPath bezierPathWithRect:CGRectMake(self.margin.left, self.margin.top, self.previewSize.width, self.previewSize.height)] bezierPathByReversingPath]];
+
+ CAShapeLayer *layer = [CAShapeLayer layer];
+ layer.path = path.CGPath;
+ [_maskView.layer setMask:layer];
+
+ _maskView.alpha = 0;
+ }
+ return _maskView;
+}
+
+- (UIView *)lineWrap {
+ if (!_lineWrap) {
+ _lineWrap = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.previewSize.width, self.previewSize.height)];
+
+ UIView *top = [[UIView alloc] init];
+ [_lineWrap addSubview:top];
+
+ [top mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.top.equalTo(@0);
+ make.left.right.equalTo(@0);
+ make.height.equalTo(@1.5f);
+ }];
+
+ UIView *left = [[UIView alloc] init];
+ [_lineWrap addSubview:left];
+
+ [left mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.top.bottom.equalTo(@0);
+ make.left.equalTo(@0);
+ make.width.equalTo(@1.5f);
+ }];
+
+ UIView *right = [[UIView alloc] init];
+ [_lineWrap addSubview:right];
+
+ [right mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.top.bottom.equalTo(@0);
+ make.right.equalTo(@0);
+ make.width.equalTo(@1.5f);
+ }];
+
+ UIView *bottom = [[UIView alloc] init];
+ [_lineWrap addSubview:bottom];
+
+ [bottom mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.bottom.equalTo(@0);
+ make.left.right.equalTo(@0);
+ make.height.equalTo(@1.5f);
+ }];
+
+ top.layer.backgroundColor = UIColor.whiteColor.CGColor;
+ top.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.3].CGColor;
+ top.layer.shadowOffset = CGSizeMake(0,0);
+ top.layer.shadowOpacity = 1;
+ top.layer.shadowRadius = 2;
+
+ left.layer.backgroundColor = UIColor.whiteColor.CGColor;
+ left.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.3].CGColor;
+ left.layer.shadowOffset = CGSizeMake(0,0);
+ left.layer.shadowOpacity = 1;
+ left.layer.shadowRadius = 2;
+
+ bottom.layer.backgroundColor = UIColor.whiteColor.CGColor;
+ bottom.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.3].CGColor;
+ bottom.layer.shadowOffset = CGSizeMake(0,0);
+ bottom.layer.shadowOpacity = 1;
+ bottom.layer.shadowRadius = 2;
+
+ right.layer.backgroundColor = UIColor.whiteColor.CGColor;
+ right.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.3].CGColor;
+ right.layer.shadowOffset = CGSizeMake(0,0);
+ right.layer.shadowOpacity = 1;
+ right.layer.shadowRadius = 2;
+
+
+ NSMutableArray *rowLines = [NSMutableArray array];
+ for (int i = 0; i < 4; i++) {
+ UIView *line = [[UIView alloc] init];
+ line.backgroundColor = [UIColor colorWithWhite:1 alpha:.8f];
+ [_lineWrap addSubview:line];
+ [rowLines addObject:line];
+ line.hidden = (i == 0 || i == 3) ? YES : NO;
+ }
+
+ [rowLines mas_distributeViewsAlongAxis:MASAxisTypeVertical withFixedItemLength:1 leadSpacing:0 tailSpacing:0];
+ [rowLines mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.height.equalTo(@1);
+ make.left.right.equalTo(@0);
+ }];
+
+ NSMutableArray *columnLins = [NSMutableArray array];
+ for (int i = 0; i < 4; i++) {
+ UIView *line = [[UIView alloc] init];
+ line.backgroundColor = [UIColor colorWithWhite:1 alpha:.8f];
+ [_lineWrap addSubview:line];
+ [columnLins addObject:line];
+ line.hidden = (i == 0 || i == 3) ? YES : NO;
+ }
+
+ [columnLins mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedItemLength:1 leadSpacing:0 tailSpacing:0];
+ [columnLins mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.width.equalTo(@1);
+ make.top.bottom.equalTo(@0);
+ }];
+ }
+ return _lineWrap;
+}
+
+- (UIView *)imageWrap {
+ if (!_imageWrap) {
+ _imageWrap = [[UIView alloc] initWithFrame:CGRectZero];
+
+ UIImageView *topLeft = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cycle_top_left" ofType:@"png"]]];
+ topLeft.tag = 0;
+ [_imageWrap addSubview:topLeft];
+ [topLeft mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.left.top.equalTo(@0);
+ make.width.height.equalTo(@24);
+ }];
+
+ UIImageView *topright = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cycle_top_right" ofType:@"png"]]];
+ topright.tag = 1;
+ [_imageWrap addSubview:topright];
+ [topright mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.right.top.equalTo(@0);
+ make.width.height.equalTo(@24);
+ }];
+
+ UIImageView *bottomLeft = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cycle_bottom_left" ofType:@"png"]]];
+ bottomLeft.tag = 2;
+ [_imageWrap addSubview:bottomLeft];
+ [bottomLeft mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.left.bottom.equalTo(@0);
+ make.width.height.equalTo(@24);
+ }];
+
+ UIImageView *bottomRight = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cycle_bottom_right" ofType:@"png"]]];
+ bottomRight.tag = 3;
+ [_imageWrap addSubview:bottomRight];
+ [bottomRight mas_makeConstraints:^(MASConstraintMaker *make) {
+ make.bottom.right.equalTo(@0);
+ make.width.height.equalTo(@24);
+ }];
+ }
+ return _imageWrap;
+}
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.h
new file mode 100644
index 0000000..4e9492e
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.h
@@ -0,0 +1,36 @@
+//
+// HdlCorpImageViewController.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/17.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+@protocol SaveImageCallBack <NSObject>
+
+-(void)SaveImageCallBack:(NSString *)imagePathName;
+
+@end
+
+
+
+//typedef void(^SaveImageCallBack)(NSString *imagePathName);
+
+@interface HdlCorpImageViewController : UIViewController
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int openType;
+
+
+@property (nonatomic,weak) id<SaveImageCallBack> mSaveImageCallBack;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.m
new file mode 100644
index 0000000..dae572f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/HdlCorpImageViewController.m
@@ -0,0 +1,132 @@
+//
+// HdlCorpImageViewController.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/17.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HdlCorpImageViewController.h"
+#import "UIImage+Crop.h"
+#import "CropImageController.h"
+
+#define WEAKSELF_AT __weak __typeof(&*self)weakSelf_AT = self;
+
+@interface HdlCorpImageViewController ()<CropImageDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
+
+@property (nonatomic, strong) NSString *mCropPicturePath; //鍥剧墖璺緞
+@property (nonatomic, strong) NSString *mCropPictureName; //鍥剧墖鍛藉悕
+
+@end
+
+@implementation HdlCorpImageViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ self.view.backgroundColor = [UIColor whiteColor];
+ _mCropPictureName = @"hdl_headPicture.Png";
+ if(_openType == 101){
+ [self openTypeCamera];
+ }else{
+ [self openTypePhotoLibrary];
+ }
+
+ // Do any additional setup after loading the view.
+}
+
+#pragma mark - 涓婁紶澶村儚
+-(void)openTypeCamera{
+ WEAKSELF_AT
+ UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
+ imagePickerController.delegate = weakSelf_AT;
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
+
+ [self presentViewController:imagePickerController animated:YES completion:nil];
+}
+
+-(void)openTypePhotoLibrary;{
+ WEAKSELF_AT
+ UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
+ imagePickerController.delegate = weakSelf_AT;
+ imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+ [self presentViewController:imagePickerController animated:YES completion:nil];
+
+}
+
+#pragma mark -- UIImagePickerControllerDelegate
+- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
+ [picker dismissViewControllerAnimated:YES completion:nil];
+// [picker dismissViewControllerAnimated:YES completion:^{
+//
+// }];
+// [picker dismissViewControllerAnimated:YES completion:^{
+// UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
+// CropImageController * con = [[CropImageController alloc] initWithImage:image delegate:self];
+// [self.navigationController pushViewController:con animated:YES];
+// }];
+
+ UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
+ CGFloat width = [UIScreen mainScreen].bounds.size.width;
+ CGFloat height = image.size.height * (width/image.size.width);
+ UIImage * orImage = [image resizeImageWithSize:CGSizeMake(width, height)];
+ CropImageController * con = [[CropImageController alloc] initWithImage:orImage delegate:self];
+ con.ovalClip = NO;
+ [self.navigationController pushViewController:con animated:YES];
+}
+
+// 鍙栨秷鍥剧墖閫夋嫨璋冪敤姝ゆ柟娉�
+- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
+
+ [self backAction:NO];
+}
+
+
+
+-(void)backAction:(BOOL)bGetPicture{
+ if(bGetPicture){
+ if(self.mSaveImageCallBack != NULL){
+ [self.mSaveImageCallBack SaveImageCallBack:_mCropPicturePath];
+ NSLog(@"鍏抽棴椤甸潰");
+ }
+ }
+ [self.navigationController popViewControllerAnimated:YES];
+}
+
+
+#pragma mark -- CropImageDelegate
+- (void)cropImageDidFinishedWithImage:(NSString *)imageName bSuccess:(BOOL)bSuccess{
+
+ if(bSuccess){
+ //淇濆瓨鍒版湰鍦板苟杩斿洖璺緞
+// _mCropPicturePath
+// NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
+//
+// NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:
+// [NSString stringWithFormat:@"%@", _mCropPictureName]]; // 淇濆瓨鏂囦欢鐨勫悕绉�
+//
+// BOOL result =[UIImagePNGRepresentation(image)writeToFile:filePath atomically:YES]; // 淇濆瓨鎴愬姛浼氳繑鍥瀁ES
+// if (result == YES) {
+//// _mCropPicturePath =_mCropPictureName;
+// _mCropPicturePath =filePath;
+// NSLog(@"淇濆瓨鎴愬姛");
+// }
+
+ _mCropPicturePath = imageName;
+ [self backAction:bSuccess];
+ }else{
+ [self backAction:bSuccess];
+ }
+
+}
+
+/*
+ #pragma mark - Navigation
+
+ // In a storyboard-based application, you will often want to do a little preparation before navigation
+ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+ }
+ */
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.h
new file mode 100755
index 0000000..2bb85b8
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.h
@@ -0,0 +1,27 @@
+//
+// UIImage+Crop.h
+// CropImage
+//
+// Created by limuyun on 2017/1/11.
+// Copyright 漏 2017骞� biiway. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (Crop)
+
+/**
+ 缂╂斁鎸囧畾澶у皬
+
+ @param newSize 缂╂斁鍚庣殑灏哄
+ @return UIImage
+ */
+- (UIImage *)resizeImageWithSize:(CGSize)newSize;
+
+/**
+ 鍥剧墖鍦嗗舰瑁佸壀
+
+ @return UIImage
+ */
+- (UIImage *)ovalClip;
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.m
new file mode 100755
index 0000000..8510925
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImage+Crop.m
@@ -0,0 +1,40 @@
+//
+// UIImage+Crop.m
+// CropImage
+//
+// Created by limuyun on 2017/1/11.
+// Copyright 漏 2017骞� biiway. All rights reserved.
+//
+
+#import "UIImage+Crop.h"
+
+@implementation UIImage (Crop)
+
+- (UIImage *)resizeImageWithSize:(CGSize)newSize {
+ CGFloat newWidth = newSize.width;
+ CGFloat newHeight = newSize.height;
+ float width = self.size.width;
+ float height = self.size.height;
+ if (width != newWidth || height != newHeight) {
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), YES, [UIScreen mainScreen].scale);
+ [self drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
+
+ UIImage *resized = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return resized;
+ }
+ return self;
+}
+- (UIImage *)ovalClip {
+
+ CGSize size = self.size;
+ UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
+ UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
+ [path addClip];
+ [self drawAtPoint:CGPointZero];
+ UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ return image;
+}
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.h
new file mode 100644
index 0000000..08a9dcb
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.h
@@ -0,0 +1,34 @@
+//
+// UIImageCrop.h
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/10/21.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface UIImageCrop : NSObject
+
+/**
+ 缂╂斁鎸囧畾澶у皬
+
+ @param newSize 缂╂斁鍚庣殑灏哄
+ @return UIImage
+ */
++(UIImage *)resizeImageWithSize:(UIImage *)img newSize:(CGSize)newSize;
+
+/**
+ 鍥剧墖鍦嗗舰瑁佸壀
+
+ @return UIImage
+ */
++(UIImage *)ovalClip:(UIImage *)img;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.m
new file mode 100644
index 0000000..c82cbad
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/CropImage/UIImageCrop.m
@@ -0,0 +1,43 @@
+//
+// UIImageCrop.m
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/10/21.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "UIImageCrop.h"
+
+@implementation UIImageCrop
+
+
+
++(UIImage *)resizeImageWithSize:(UIImage *)img newSize:(CGSize)newSize{
+ CGFloat newWidth = newSize.width;
+ CGFloat newHeight = newSize.height;
+ float width = img.size.width;
+ float height = img.size.height;
+ if (width != newWidth || height != newHeight) {
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), YES, [UIScreen mainScreen].scale);
+ [img drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
+
+ UIImage *resized = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return resized;
+ }
+ return img;
+}
++(UIImage *)ovalClip:(UIImage *)img{
+
+ CGSize size = img.size;
+ UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
+ UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, img.size.width, img.size.height)];
+ [path addClip];
+ [img drawAtPoint:CGPointZero];
+ UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ return image;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.h
new file mode 100644
index 0000000..af47e2a
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.h
@@ -0,0 +1,62 @@
+//
+// HDLGestureLockView.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/30.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@class HDLGestureLockView;
+
+@protocol SSGestureLockViewDelegate <NSObject>
+@optional
+
+- (void)didSelectedGestureLockView:(NSString *)selectNumStr selectCount:(int)selectCount;
+
+@end
+
+
+@interface HDLGestureLockView : UIView
+///鍨傜洿闂撮殧
+@property (nonatomic, assign) CGFloat verticalSpace;
+///姘村钩闂撮殧
+@property (nonatomic, assign) CGFloat horizontalSpace;
+///鐢荤嚎鐨勫搴�
+@property (nonatomic, assign) CGFloat lineWidth;
+///鐢荤嚎鐨勯鑹�
+@property (nonatomic, strong) UIColor *selectedLineColor;
+///閿欒鏄敾绾跨殑棰滆壊
+@property (nonatomic, strong) UIColor *errorLineColor;
+@property (nonatomic, strong) UIColor *normalColor;
+///reset 寤惰繜鏃堕棿
+@property (nonatomic, assign) int resetDelayMillis;
+
+
+@property (nonatomic, weak) id<SSGestureLockViewDelegate>delegate;
+
+@property (nonatomic, assign) BOOL showErrorStatus;///灞曠ず閿欒鍦扮姸鎬�
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameLockView:(CGRect) mCGRect;
+
+
+-(void)setSolidType:(BOOL)isSolidType;
+
+@end
+NS_ASSUME_NONNULL_END
+
+
+//# HDLGestureLockView(鎵嬪娍瑙i攣)
+//*****V1.0.2*****
+//2020-06-17
+//1.澧炲姞瀹炲績鍦嗙偣鐨勬晥鏋� 瑙i攣鏍峰紡绫诲瀷銆�
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.m
new file mode 100644
index 0000000..8148149
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/GestureLockView/HDLGestureLockView.m
@@ -0,0 +1,434 @@
+//
+// HDLGestureLockView.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/10/30.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLGestureLockView.h"
+#import "HDLUtlisXM.h"
+
+#define SSGestureLock_ButtonSize CGSizeMake(20,20)//娌℃湁閫夋嫨鎸夐挳鐨勫ぇ灏�
+#define SSGestureLock_SelectedButtonSize CGSizeMake(60,60)//閫夋嫨鍚庢寜閽殑澶у皬
+#define SSGestureLock_SelectedLineColor HEXCOLOR(0xFC744B)//閫夋嫨鏃跺�欑嚎鐨勯鑹�
+#define SSGestureLock_SelectedErrorLineColor HEXCOLOR(0xFF0000) //閫夋嫨鍚庨敊璇嚎鐨勯鑹�
+//#define SSGestureLock_NomarlColor HEXCOLOR(0xD5DBE8)
+#define SSGestureLock_BorderColor HEXCOLOR(0x818181)
+#define SSGestureLock_NomarlColor HEXCOLOR(0xC0C7D4)
+
+
+CGFloat const SSGestureLock_DrawLineWidth = 2; //鐢荤嚎鐨勫搴�
+CGFloat const SSGestureLock_ButtonSpaceH = 30; //妯悜闂撮殧
+CGFloat const SSGestureLock_ButtonSpaceV = 30; //绾靛悜闂撮殧
+
+NSInteger const SSGestureLock_EachNum = 3;
+NSInteger const SSGestureLock_ButtonCount = 9;
+
+typedef NS_ENUM(NSInteger, SSGestureLockKeyType) {
+ SSGestureLockKeyNormalType,
+ SSGestureLockKeySelectedType,
+ SSGestureLockKeyErrorType,
+};
+
+
+@interface SSGestureLockKeyView:UIView
+
+@property (nonatomic, assign) SSGestureLockKeyType keyType;
+@property (nonatomic, strong) UIView *smallView;
+@property (nonatomic, strong) UIColor *errorColor;
+@property (nonatomic, strong) UIColor *normalColor;
+@property (nonatomic, strong) UIColor *selectedColor;
+@property (nonatomic, strong) UIColor *selectedColor_Alpha;
+@property (nonatomic, strong) UIColor *errorColor_Alpha;
+@property (nonatomic, assign) BOOL isSolidType;
+
+@end
+
+@implementation SSGestureLockKeyView
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ self.backgroundColor = [UIColor clearColor];
+ _smallView = [UIView new];
+ [self addSubview:_smallView];
+
+
+ }
+ return self;
+}
+
+- (void)layoutSubviews{
+ [super layoutSubviews];
+ ///鏍规嵁澶у皬鏉ヨ缃渾瑙�
+ self.layer.cornerRadius = self.frame.size.height/2;
+ self.layer.masksToBounds = true;
+// self.layer.borderWidth = 1.0f;
+// self.layer.borderColor = SSGestureLock_BorderColor.CGColor;
+
+ CGFloat smallView_x = CGRectGetWidth(self.frame)*1/3;
+ CGFloat smallView_y = CGRectGetWidth(self.frame)*1/3;
+ CGFloat smallView_width = CGRectGetWidth(self.frame)*1/3;
+ self.smallView.frame = CGRectMake(smallView_x, smallView_y, smallView_width, smallView_width);
+ self.smallView.layer.cornerRadius = self.smallView.frame.size.height/2;
+
+ if(_isSolidType){
+ self.smallView.backgroundColor = self.normalColor;
+ }else{
+ self.layer.borderWidth = 1.0f;
+ self.layer.borderColor = SSGestureLock_BorderColor.CGColor;
+ }
+}
+
+- (void)setErrorColor:(UIColor *)errorColor{
+ _errorColor = errorColor;
+ _errorColor_Alpha = [self getNewColorWith:errorColor newAlpha:0.2F];
+}
+- (void)setNormalColor:(UIColor *)normalColor{
+ _normalColor = normalColor;
+ // self.smallView.backgroundColor = _normalColor;
+}
+- (void)setSelectedColor:(UIColor *)selectedColor{
+ _selectedColor = selectedColor;
+ _selectedColor_Alpha = [self getNewColorWith:selectedColor newAlpha:0.2F];
+}
+
+// 鏀瑰彉UIColor鐨凙lpha
+- (UIColor *)getNewColorWith:(UIColor *)color newAlpha:(float)newAlpha{
+ CGFloat red = 0.0;
+ CGFloat green = 0.0;
+ CGFloat blue = 0.0;
+ CGFloat alpha = 0.0;
+ [color getRed:&red green:&green blue:&blue alpha:&alpha];
+ UIColor *newColor = [UIColor colorWithRed:red green:green blue:blue alpha:newAlpha];
+ return newColor;
+}
+
+- (void)setKeyType:(SSGestureLockKeyType)keyType{
+ _keyType = keyType;
+
+ if(!_isSolidType){
+ if (_keyType == SSGestureLockKeyNormalType) {
+ // self.backgroundColor = [UIColor clearColor];
+ self.smallView.backgroundColor = [UIColor clearColor];
+ self.layer.borderColor = SSGestureLock_BorderColor.CGColor;
+ }
+ if (_keyType == SSGestureLockKeySelectedType) {
+ // self.backgroundColor = self.normalColor;
+ self.smallView.backgroundColor = self.selectedColor;
+ self.layer.borderColor = self.selectedColor.CGColor;
+ }
+
+ if (_keyType == SSGestureLockKeyErrorType) {
+ // self.backgroundColor = self.normalColor;
+ self.smallView.backgroundColor = self.errorColor;
+ self.layer.borderColor = self.errorColor.CGColor;
+ }
+
+ }else{
+ if (_keyType == SSGestureLockKeyNormalType) {
+ self.smallView.backgroundColor = self.normalColor;
+ self.backgroundColor = [UIColor clearColor];
+ // self.layer.borderColor = SSOnGestureLock_BorderColor.CGColor;
+ }
+ if (_keyType == SSGestureLockKeySelectedType) {
+ self.smallView.backgroundColor = self.selectedColor;
+ // self.layer.borderColor = self.selectedColor.CGColor;
+ self.backgroundColor = self.selectedColor_Alpha;
+ }
+
+ if (_keyType == SSGestureLockKeyErrorType) {
+ self.smallView.backgroundColor = self.errorColor;
+ self.backgroundColor = self.errorColor_Alpha;
+ // self.layer.borderColor = self.errorColor.CGColor;
+ }
+ }
+}
+
+@end
+
+
+@interface HDLGestureLockView ()
+@property (nonatomic, strong) NSMutableArray <SSGestureLockKeyView *>* keyViewArray;
+@property (nonatomic, strong) NSMutableArray <SSGestureLockKeyView *> *selectedKeyViewArray;
+@property (nonatomic, assign) CGPoint movePoint;
+@property (nonatomic, strong) CAShapeLayer *drawLayer;
+@property (nonatomic, assign) BOOL isSolidType; //鏄惁涓哄疄蹇冨渾鐐圭殑鎵嬪娍瑙i攣绫诲瀷
+
+@end
+
+@implementation HDLGestureLockView
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ self.lineWidth = SSGestureLock_DrawLineWidth;
+ self.errorLineColor = SSGestureLock_SelectedErrorLineColor;
+ self.selectedLineColor = SSGestureLock_SelectedLineColor;
+ self.horizontalSpace = SSGestureLock_ButtonSpaceH;
+ self.verticalSpace = SSGestureLock_ButtonSpaceV;
+ self.normalColor = SSGestureLock_NomarlColor;
+ [self setViews];
+ }
+ return self;
+}
+
+- (CAShapeLayer *)drawLayer{
+ if (!_drawLayer) {
+ _drawLayer = [CAShapeLayer layer];
+ _drawLayer.fillColor = [UIColor clearColor].CGColor;
+ _drawLayer.lineWidth = self.lineWidth;
+ _drawLayer.lineJoin = @"round";
+ [self.layer addSublayer:_drawLayer];
+ }
+ return _drawLayer;
+}
+
+
+- (NSMutableArray *)keyViewArray{
+ if (!_keyViewArray) {
+ _keyViewArray = @[].mutableCopy;
+ }
+ return _keyViewArray;
+}
+- (NSMutableArray *)selectedKeyViewArray{
+ if (!_selectedKeyViewArray) {
+ _selectedKeyViewArray = @[].mutableCopy;
+ }
+ return _selectedKeyViewArray;
+}
+
+- (void)setHorizontalSpace:(CGFloat)horizontalSpace{
+ _horizontalSpace = horizontalSpace;
+ [self setNeedsLayout];
+}
+
+- (void)setVerticalSpace:(CGFloat)verticalSpace{
+ _verticalSpace = verticalSpace;
+ [self setNeedsLayout];
+}
+
+- (void)setErrorLineColor:(UIColor *)errorLineColor{
+ _errorLineColor = errorLineColor;
+ for (SSGestureLockKeyView *view in self.keyViewArray) {
+ view.errorColor = errorLineColor;
+ }
+}
+- (void)setSelectedLineColor:(UIColor *)selectedLineColor{
+ _selectedLineColor = selectedLineColor;
+ for (SSGestureLockKeyView *view in self.keyViewArray) {
+ view.selectedColor = selectedLineColor;
+ }
+}
+- (void)setNormalColor:(UIColor *)normalColor{
+ _normalColor = normalColor;
+ for (SSGestureLockKeyView *view in self.keyViewArray) {
+ view.normalColor = normalColor;
+ }
+}
+- (void)setShowErrorStatus:(BOOL)showErrorStatus{
+ _showErrorStatus = showErrorStatus;
+
+}
+
+- (void)layoutSubviews{
+ [super layoutSubviews];
+
+ CGFloat keyViewWidth = (CGRectGetWidth(self.frame)- (SSGestureLock_EachNum-1)*self.horizontalSpace)/SSGestureLock_EachNum;
+ CGFloat keyViewHeight = (CGRectGetHeight(self.frame)- (SSGestureLock_EachNum-1)*self.verticalSpace)/SSGestureLock_EachNum;
+ for (NSUInteger i=0; i<self.keyViewArray.count; i++) {
+
+ NSInteger num = i/SSGestureLock_EachNum;
+ NSInteger remainNum = i%SSGestureLock_EachNum;
+
+ UIView *view = self.keyViewArray[i];
+ view.frame = CGRectMake((keyViewWidth+self.horizontalSpace)*remainNum, (keyViewHeight+self.verticalSpace)*num, keyViewWidth, keyViewHeight);
+
+ }
+
+}
+
+- (void)setViews{
+ self.backgroundColor = [UIColor clearColor];
+ for (NSUInteger i = 0; i < SSGestureLock_ButtonCount; i++) {
+ SSGestureLockKeyView *keyView = [[SSGestureLockKeyView alloc]init];
+ keyView.errorColor = self.errorLineColor;
+ keyView.selectedColor = self.selectedLineColor;
+ keyView.normalColor = self.normalColor;
+ keyView.isSolidType = self.isSolidType;
+ keyView.tag = i+1;
+ [self addSubview:keyView];
+ [self.keyViewArray addObject:keyView];
+ }
+}
+
+
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+ [super drawRect:rect];
+
+ if (self.selectedKeyViewArray.count>0) {
+
+ UIBezierPath *bezierPath = [UIBezierPath bezierPath];
+ SSGestureLockKeyView *firstKeyView = [self.selectedKeyViewArray objectAtIndex:0];
+ [bezierPath moveToPoint:firstKeyView.center];
+ if (self.showErrorStatus) {
+ self.drawLayer.strokeColor = self.errorLineColor.CGColor;
+
+ }else{
+ self.drawLayer.strokeColor = self.selectedLineColor.CGColor;
+ }
+ for (int i = 0; i < [self.selectedKeyViewArray count]; i++) {
+ SSGestureLockKeyView *KeyView = [self.selectedKeyViewArray objectAtIndex:i];
+ if (!self.showErrorStatus) {
+ KeyView.keyType = SSGestureLockKeySelectedType;
+ }else{
+ KeyView.keyType = SSGestureLockKeyErrorType;
+
+ }
+ [bezierPath addLineToPoint:KeyView.center];
+ }
+
+ if (!CGPointEqualToPoint(self.movePoint, CGPointZero)) {
+ [bezierPath addLineToPoint:self.movePoint];
+ }
+
+ self.drawLayer.path = bezierPath.CGPath;
+
+ }else{
+ [self.drawLayer removeFromSuperlayer];
+ self.drawLayer = nil;
+ }
+
+ // Drawing code
+}
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
+ UITouch *touch = [touches anyObject];
+ CGPoint locationPoint = [touch locationInView:self];
+ SSGestureLockKeyView *keyView = [self returnContainKeyViewWithPoint:locationPoint];
+ if (keyView) {
+ [self.selectedKeyViewArray addObject:keyView];
+ }
+ [self setNeedsDisplay];
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
+ UITouch *touch = [touches anyObject];
+ CGPoint locationPoint = [touch locationInView:self];
+ if (CGRectContainsPoint(CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), locationPoint)) {
+ SSGestureLockKeyView *keyView = [self returnContainKeyViewWithPoint:locationPoint];
+ if (keyView&&![self.selectedKeyViewArray containsObject:keyView]) {
+ [self.selectedKeyViewArray addObject:keyView];
+ }
+ self.movePoint = locationPoint;
+ [self setNeedsDisplay];
+ }
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
+ if ([self.delegate respondsToSelector:@selector(didSelectedGestureLockView:selectCount:)]) {
+ [self.delegate didSelectedGestureLockView:[self returnKeyNumStr] selectCount:[self.selectedKeyViewArray count]];
+ }
+ if (self.showErrorStatus) {
+ [self ss_changeSelectedKeyViewWithKeytype:SSGestureLockKeyErrorType];
+ [self setNeedsDisplay];
+ }
+
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ [self.selectedKeyViewArray removeAllObjects];
+ self.movePoint = CGPointZero;
+ [self setNeedsDisplay];
+ [self ss_changeAllKeyViewWithKeytype:SSGestureLockKeyNormalType];
+ self.showErrorStatus = NO;
+ });
+
+
+}
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
+ [self.selectedKeyViewArray removeAllObjects];
+ self.movePoint = CGPointZero;
+ [self setNeedsDisplay];
+ [self ss_changeAllKeyViewWithKeytype:SSGestureLockKeyNormalType];
+}
+
+#pragma mark - 鏍规嵁鍧愭爣鎵惧嚭鎵�鍦ㄧ殑keyView
+- (SSGestureLockKeyView *)returnContainKeyViewWithPoint:(CGPoint)point{
+ SSGestureLockKeyView *tempView = nil;
+ for (SSGestureLockKeyView *keyView in self.keyViewArray) {
+ if (CGRectContainsPoint(keyView.frame, point)) {
+ tempView = keyView;
+ break;
+ }
+ }
+ return tempView;
+}
+#pragma mark - 杩樺師鎵�鏈塳eyView鐨勭姸鎬�
+- (void)ss_changeAllKeyViewWithKeytype:(SSGestureLockKeyType)keyType{
+ for (SSGestureLockKeyView *keyView in self.keyViewArray) {
+ if (keyView.keyType != keyType) {
+ keyView.keyType = keyType;
+ }
+ }
+}
+- (void)ss_changeSelectedKeyViewWithKeytype:(SSGestureLockKeyType)keyType{
+ for (SSGestureLockKeyView *keyView in self.selectedKeyViewArray) {
+ if (keyView.keyType != keyType) {
+ keyView.keyType = keyType;
+ }
+ }
+}
+
+
+- (NSString *)returnKeyNumStr{
+
+ NSString *keyNumStr = @"";
+ for (int i = 0; i < [self.selectedKeyViewArray count]; i++) {
+
+ SSGestureLockKeyView *KeyView = [self.selectedKeyViewArray objectAtIndex:i];
+ keyNumStr = [keyNumStr stringByAppendingString:[NSString stringWithFormat:@"%ld",KeyView.tag]];
+ }
+ return keyNumStr;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameLockView:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ // [self refreshFrame];
+
+ int mSpace = self.frame.size.width/(2*SSGestureLock_EachNum - 1);
+ self.horizontalSpace = mSpace;
+ self.verticalSpace = mSpace;
+ //// [self refreshFrame];
+
+}
+
+/// 2020-06-17
+/// 璁剧疆瀹炲績妯″紡
+/// @param isSolidType 鏄惁
+-(void)setSolidType:(BOOL)isSolidType{
+ self.isSolidType = isSolidType;
+ [self resetViews];
+}
+
+
+/// 閲嶇疆view
+- (void)resetViews{
+ //绉婚櫎鎵�鏈夊瓙view
+ for(UIView *view in [self subviews])
+ {
+ [view removeFromSuperview];
+ }
+ [_keyViewArray removeAllObjects];
+ [self setViews];
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.h
new file mode 100644
index 0000000..f5b1356
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.h
@@ -0,0 +1,107 @@
+//
+// HDLArcScaleSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/12.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLArcScaleSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+/**
+ 绾挎潯鑳屾櫙鑹层��
+ */
+@property (nonatomic, strong) UIColor *pathBackColor;
+
+
+
+#pragma mark HDLArcScaleSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(CGFloat)mMinValue mMaxValue:(CGFloat)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.m
new file mode 100644
index 0000000..f7c8ec8
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/HDLArcScaleSeekBar.m
@@ -0,0 +1,887 @@
+//
+// HDLArcScaleSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/12.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLArcScaleSeekBar.h"
+#import "ScalePointData.h"
+#import "HDLUtlisXM.h"
+
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+#define APP_DEFAULT_ROUND_BORDER_COLOR HEXCOLOR(0xEAEAEB)
+
+
+@interface HDLArcScaleSeekBar ()
+
+/**鏄惁姝e湪绉诲姩*/
+@property (nonatomic, assign) BOOL bTouchMove;
+/**杩涘害鍗曚綅绗﹀彿*/
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+/**鏈�灏忓��*/
+@property (nonatomic, assign) CGFloat mMinValue;
+/**鏈�澶у��*/
+@property (nonatomic, assign) CGFloat mMaxValue;
+/**娓愬彉鑹插紑濮嬮鑹层��*/
+@property (nonatomic, strong) UIColor *startColor;
+
+/**娓愬彉鑹茬粨鏉熼鑹层��*/
+@property (nonatomic, strong) UIColor *endColor;
+/**寮�鍙h搴�*/
+@property (nonatomic, assign) CGFloat mOpenAngle;
+// 鍦嗗姬鐨勮捣濮嬭搴�
+@property (nonatomic, assign) CGFloat mStartAngle;
+// 鍦嗗姬鐨勮捣濮嬭搴�
+@property (nonatomic, assign) CGFloat mEndAngle;
+// 鍦嗗姬鐨勭粡杩囨�昏寖鍥磋搴﹁搴�
+@property (nonatomic, assign) CGFloat mSweepAngle;
+// 娓愬彉鑹层��
+@property (nonatomic, strong) UIColor *currentColor;
+@property (nonatomic, strong) UIColor *currentWaveColor;
+// 鏄惁绂荤嚎
+@property (nonatomic, assign) BOOL isOffline;
+
+
+@property (nonatomic, copy) NSMutableArray *pointArray;//not recommended
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mArcProgressBarColors;
+
+@end
+
+
+@implementation HDLArcScaleSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInArcProgress;
+
+ CGFloat mSeekBarHeight;
+ CGFloat mSeekBarWidth;
+ CGFloat mSeekBarRadius;
+
+ // 鎺т欢姝f柟褰㈣竟瀹�
+ CGFloat _mArcWidth;
+ CGFloat _mPercent;
+ CGFloat _mCornerRadius;
+
+ //******************鑳屾櫙鍦�******************
+ // 鍓垏鍦嗙殑鍗婂緞
+ int clipRadius;
+ // 娉㈡氮鍥哄畾楂樺害
+ int mWaveHeight;
+ //鑳屾櫙鍦嗗
+ CGFloat bgRoundWidth;
+ // 鍓垏鍦嗙殑X鍧愭爣
+ CGFloat mRoundX;
+ // 鑳屾櫙鍦嗗埌鍒诲害鐨勮窛绂�
+ CGFloat bgRoundPadding;
+ // 鍦嗗姬鐨勫崐寰�
+ CGFloat mArcRadius;
+
+ //******************鍒诲害******************
+ // 鍒诲害绾块珮
+ CGFloat mScaleLineHeight;
+ CGFloat mScaleLineHeightOut;
+
+ // 鍒诲害绾垮
+ CGFloat mScaleLineWidth;
+ // 鍒诲害绾夸箣闂撮棿闅�
+ CGFloat mLinePadding;
+ //鍒诲害鎬绘暟
+ int mLineCount;
+ // 褰撳墠杩涘害鐨勫埢搴︾嚎鏁�
+ int mTargetCount;
+ //姣忔牸鍒诲害鐨勮搴�
+ CGFloat mAngle;
+
+ //******************娉㈡氮******************
+ CGFloat _mWaveStartX;
+ CGFloat _mWaveEndX;
+ CGFloat _waveStartY;
+ CGFloat _mWaveEndY;
+
+ CGFloat _waveA;
+ CGFloat mCycleFactorW;
+
+
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 16;
+ _mPercent = 0;
+ _mMaxValue = 35.0f;
+ _mMinValue = 16.0f;
+ _mCornerRadius = 0;
+ _mOpenAngle = 90;
+ mScaleLineWidth = 15;
+// mLinePadding = 10;
+ mScaleLineHeight = 15;
+ mScaleLineHeightOut = mScaleLineHeight/4;
+ mScaleLineWidth = 2;
+ bgRoundWidth = 8;
+ bgRoundPadding = 16;
+ mRoundX = 0;
+ mLinePadding = 10;
+
+ mCycleFactorW = M_PI*2/self.bounds.size.width;
+ _waveStartY = self.bounds.size.width*3/4;
+ _mWaveStartX = 0;
+ _mWaveEndX = self.bounds.size.width;
+ _mWaveEndY = self.bounds.size.height;
+ _waveA = 15.0f ;
+ _pointArray = [NSMutableArray array];
+
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 20;
+ _mProgressBarUnitSring = @"鈩�";
+ _isProgressTextShow = YES;
+ _pathBackColor = APP_DEFAULT_ROUND_BORDER_COLOR;
+
+ _startColor = HEXCOLOR(0x495AF4);
+ _endColor = HEXCOLOR(0xAE50A8);
+ _mArcProgressBarColors = @[
+ (id) _startColor.CGColor,
+ (id)_endColor.CGColor
+ ];
+
+ _currentColor = _startColor;
+ _currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
+
+ [self refreshFrame];
+
+ self.backgroundColor = [UIColor clearColor];
+
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ // _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onArcSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onArcSizeChange{
+ mSeekBarWidth = self.frame.size.width;
+ mSeekBarHeight = self.frame.size.height;
+
+ _mSweepAngle = 360 - _mOpenAngle;
+ _mStartAngle = 90 + _mOpenAngle/2;
+ _mEndAngle = GETEndAngle(_mOpenAngle/2);
+ _mArcWidth = MIN(mSeekBarWidth, mSeekBarHeight);
+
+ mCycleFactorW = M_PI*2/_mArcWidth;
+
+ // mArcRadius = (_mArcWidth - mScaleLineHeight)/2 ;
+ mArcRadius = _mArcWidth / 2 ;
+ _mCenterPoint = CGPointMake(_mArcWidth/2, _mArcWidth/2);
+ mRoundX = mScaleLineHeight + bgRoundPadding + mScaleLineHeightOut;
+ clipRadius = (int)(mArcRadius - mRoundX);
+ int ll = (int) ( _mSweepAngle * M_PI * mArcRadius) / 180;
+ mLineCount = (int)(ll / (mScaleLineWidth + mLinePadding));
+ mAngle = _mSweepAngle / mLineCount;
+ mWaveHeight = clipRadius / 3 ;
+ mTargetCount = (int)(_mPercent * mLineCount);
+
+
+ _mWaveStartX = mRoundX;
+ _mWaveEndX = mSeekBarWidth - _mWaveStartX;
+ //楂樹负鍦嗙殑6鍒嗕箣涓�宸﹀彸
+ _waveStartY = _mArcWidth - mRoundX - clipRadius/3;
+ _mWaveEndY = mSeekBarHeight - _mWaveStartX;
+
+ [self loadScalePointArray];//鏇存柊鍒诲害绾垮潗鏍�
+
+}
+
+
+-(void)loadScalePointArray{
+ [_pointArray removeAllObjects];
+ CGFloat nowAngle;
+ CGPoint p1;
+ CGPoint p2;
+ for (int i = 0; i <= mLineCount; i++) {
+ nowAngle = _mStartAngle + mAngle*i;
+ p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeightOut];
+ p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight-mScaleLineHeightOut];
+ ScalePointData *mData = [[ScalePointData alloc] init];
+ mData.startPoint = p1;
+ mData.endPoint = p2;
+
+ [_pointArray addObject:mData];
+ }
+}
+
+
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鍥哄畾鐨勮儗鏅渾寮�*********
+ // [self drawBackArc:ctx];
+ // [self drawProgressBar2:ctx];
+
+ //********鑳屾櫙鍦�*********
+ [self drawRoundView:ctx r:rect];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+
+ // [self drawArcWithGradient:ctx rect:rect];//缁樺埗娓愬彉鏁堟灉
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ [self drawOfflineView:ctx];
+
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawRoundView:(CGContextRef)ctx r:(CGRect)r{
+
+ //瀹炵嚎妞渾
+ //鍨傜洿灞呬腑
+ CGRect rectRing = CGRectMake(mRoundX, mRoundX, clipRadius*2, clipRadius*2);
+
+ // CGContextDrawPath(ctx, kCGPathFill);
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:rectRing];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+ //*******缁樺埗娉㈡氮鏁堟灉鍖哄煙*********
+ [self drawWaveView:ctx number:0];
+
+ // [self drawWaveView:ctx number:1];
+
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+ CGContextSetLineWidth(ctx, bgRoundWidth);
+ CGContextSetStrokeColorWithColor(ctx, _pathBackColor.CGColor);
+ CGContextAddEllipseInRect(ctx, rectRing);
+
+ CGContextDrawPath(ctx, kCGPathStroke);
+
+}
+
+
+
+/*
+ y = Asin(蠅x+蠁)+k
+ A琛ㄧず鎸箙锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鐨勯珮搴�
+ 蠅琛ㄧず棰戠巼锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮瀵嗛泦搴�
+ 蠁琛ㄧず鍒濈浉锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鍒濆浣嶇疆
+ k琛ㄧず楂樺害锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鍦ㄥ睆骞曚腑y杞寸殑浣嶇疆銆�
+ */
+
+//姝e鸡鏇茬嚎鍏紡锛歽=Asin(蠅x+蠁)+k
+//
+//A :鎸箙,鏇茬嚎鏈�楂樹綅鍜屾渶浣庝綅鐨勮窛绂�
+//
+//蠅 :瑙掗�熷害,鐢ㄤ簬鎺у埗鍛ㄦ湡澶у皬锛屽崟浣峹涓捣浼忕殑涓暟
+//
+//K :鍋忚窛,鏇茬嚎涓婁笅鍋忕Щ閲�
+//
+//蠁 :鍒濈浉,鏇茬嚎宸﹀彸鍋忕Щ閲�
+
+-(void)drawWaveView:(CGContextRef)ctx number:(int)number{
+
+ CGContextBeginPath(ctx);
+ //1銆佹坊鍔犵涓�鐐�
+ CGContextMoveToPoint(ctx, _mWaveStartX, _waveStartY );
+ CGFloat y = _waveStartY ;
+
+ if(number > 0){
+ //2銆佹坊鍔犳按娉㈡氮鏁堟灉锛屾鐜勫嚱鏁� 鏉ヨ绠楁瘡涓�涓儚绱犵殑鍧愭爣
+ for (int i = _mWaveStartX; i <= _mWaveEndX; ++i) {
+ y = _waveA * sin(mCycleFactorW * i+ 16) + _waveStartY ;
+ CGContextAddLineToPoint(ctx, i, y);
+ }
+
+ }else{
+ //2銆佹坊鍔犳按娉㈡氮鏁堟灉锛屾鐜勫嚱鏁� 鏉ヨ绠楁瘡涓�涓儚绱犵殑鍧愭爣
+ for (int i = _mWaveStartX; i <= _mWaveEndX; ++i) {
+ y = _waveA * cos(mCycleFactorW * i + 5) + _waveStartY ;
+ CGContextAddLineToPoint(ctx, i, y);
+ }
+
+ }
+ CGContextAddLineToPoint(ctx, _mWaveEndX, _mWaveEndY);
+ CGContextAddLineToPoint(ctx, _mWaveStartX, _mWaveEndY);
+
+
+ // CGContextClosePath(ctx);
+ // CGContextSetFillColorWithColor(ctx, _currentWaveColor.CGColor );
+ // CGContextDrawPath(ctx, kCGPathFill);
+
+ [self drawArcWithGradient:ctx];
+}
+
+
+/**
+ 缁樺埗娓愬彉鏁堟灉
+ */
+-(void)drawArcWithGradient:(CGContextRef)ctx{
+ // 鍒涘缓涓�涓笎鍙樿壊
+ // 鍒涘缓RGB鑹插僵绌洪棿锛屽垱寤鸿繖涓互鍚庯紝context閲岄潰鐢ㄧ殑棰滆壊閮芥槸鐢≧GB琛ㄧず
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+
+ CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mArcProgressBarColors, NULL);
+ // 閲婃斁鑹插僵绌洪棿
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+
+ // "鍙嶉�夎矾寰�"
+ // CGContextReplacePathWithStrokedPath
+ // 灏哻ontext涓殑璺緞鏇挎崲鎴愯矾寰勭殑鎻忚竟鐗堟湰锛屼娇鐢ㄥ弬鏁癱ontext鍘昏绠楄矾寰勶紙鍗冲垱寤烘柊鐨勮矾寰勬槸鍘熸潵璺緞鐨勬弿杈癸級銆傜敤鎭板綋鐨勯鑹插~鍏呭緱鍒扮殑璺緞灏嗕骇鐢熺被浼肩粯鍒跺師鏉ヨ矾寰勭殑鏁堟灉銆備綘鍙互鍍忎娇鐢ㄤ竴鑸殑璺緞涓�鏍蜂娇鐢ㄥ畠銆備緥濡傦紝浣犲彲浠ラ�氳繃璋冪敤CGContextClip鍘诲壀瑁佽繖涓矾寰勭殑鎻忚竟
+ // CGContextReplacePathWithStrokedPath(ctx);
+ // // 鍓璺緞
+ CGContextClip(ctx);
+ // CGRect drawRect2 = CGRectMake(_mWaveStartX, _waveStartY , clipRadius*2, _waveStartY );
+ // 鐢ㄦ笎鍙樿壊濉厖
+ CGContextDrawLinearGradient(ctx, gradient, CGPointMake(_mWaveStartX+30, _waveStartY), CGPointMake(_mArcWidth-_mWaveStartX-30, _mArcWidth), 0);
+ // 閲婃斁娓愬彉鑹�
+ CGGradientRelease(gradient);
+ gradient = NULL;
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+}
+
+/**
+ 缁樺埗鍥哄畾鐨勮儗鏅渾寮�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawBackArc:(CGContextRef)ctx{
+
+
+ //1.1 璁剧疆绾挎潯鐨勫搴�
+ CGContextSetLineWidth(ctx, mScaleLineHeight);
+ //1.2 璁剧疆绾挎潯鐨勮捣濮嬬偣鏍峰紡
+ CGContextSetLineCap(ctx, kCGLineCapButt);
+ //1.3 铏氬疄鍒囨崲 锛屽疄绾�5铏氱嚎10
+ CGFloat length[] = {mScaleLineWidth, mLinePadding};
+ CGContextSetLineDash(ctx, 0, length, 2);
+ //1.4 璁剧疆棰滆壊
+ [_pathBackColor set];
+ //2.璁剧疆璺緞
+ CGContextAddArc(ctx, _mArcWidth/2 , _mArcWidth/2, mArcRadius, M_PI/180*_mStartAngle, M_PI/180*(_mEndAngle), 0);
+ //3.缁樺埗
+ CGContextStrokePath(ctx);
+
+
+}
+
+
+/*
+ * 鏍规嵁褰撳墠瑙掑害 璁$畻鍑烘嫋鍔ㄦ寜閽纭殑鍦嗗績鍧愭爣
+ */
+-(CGPoint)getThumbCenterPointFromAngle:(int)angleInt rdius:(CGFloat)rdius{
+ CGPoint result;
+ result.y = round(_mCenterPoint.y + rdius * sin(ToRad(angleInt)));
+ result.x = round(_mCenterPoint.x + rdius * cos(ToRad(angleInt)));
+ return result;
+}
+
+/**
+ 缁樺埗鍒诲害杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+ if([_pointArray count] != mLineCount + 1) return;
+
+ for (int i = 0; i <= mLineCount; i++) {
+
+ UIBezierPath *linePath = [UIBezierPath bezierPath];
+ ScalePointData *mData = [_pointArray objectAtIndex:i];
+
+ if(i <= mTargetCount && mTargetCount != 0){
+ if(i == mTargetCount){
+ //鏈�鍚庝竴鏉″埢搴﹀姞闀挎晥鏋�
+ CGFloat nowAngle = _mStartAngle + mAngle*i;
+ CGPoint p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius];
+ CGPoint p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight-mScaleLineHeightOut];
+ [linePath moveToPoint:p1];
+ [linePath addLineToPoint:p2];
+ }else{
+ [linePath moveToPoint:mData.startPoint];
+ [linePath addLineToPoint:mData.endPoint];
+
+ }
+ CGContextSetLineWidth(ctx, mScaleLineWidth);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+
+ CGFloat mColorPercent = (CGFloat) i / mLineCount;
+
+ _currentColor = [self getGradientColor:mColorPercent];
+ _currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
+
+ [_currentColor setStroke];
+ } else {
+ [linePath moveToPoint:mData.startPoint];
+ [linePath addLineToPoint:mData.endPoint];
+ CGContextSetLineWidth(ctx, mScaleLineWidth);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ //鑳屾櫙鍖洪棿
+ [_pathBackColor setStroke];
+ }
+ CGContextAddPath(ctx, linePath.CGPath);
+ CGContextStrokePath(ctx);
+
+ }
+
+
+
+
+
+ // for (int i = 0; i < mLineCount; i++) {
+ //
+ // UIBezierPath *linePath = [UIBezierPath bezierPath];
+ // CGFloat nowAngle = _mStartAngle + mAngle*i;
+ // CGFloat decreaseValue = 0;
+ //
+ // // [linePath moveToPoint:CGPointMake(mArcRadius+(mArcRadius-decreaseValue)*cosf(nowAngle), mArcRadius+(mArcRadius-decreaseValue)*sinf(nowAngle))];
+ // // [linePath addLineToPoint:CGPointMake(mArcRadius+(mArcRadius-mScaleLineHeight)*cosf(nowAngle), mArcRadius+(mArcRadius-mScaleLineHeight)*sinf(nowAngle))];
+ // //
+ //
+ // CGPoint p1 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius];
+ // CGPoint p2 = [self getThumbCenterPointFromAngle:nowAngle rdius:mArcRadius-mScaleLineHeight];
+ //
+ // [linePath moveToPoint:p1];
+ // [linePath addLineToPoint:p2];
+ //
+ //
+ // CGContextSetLineWidth(ctx, mScaleLineWidth);
+ // CGContextSetLineCap(ctx, kCGLineCapRound);
+ //
+ // if(i <= mTargetCount && mTargetCount != 0){
+ //
+ // CGFloat mColorPercent = (CGFloat) i / mLineCount;
+ //
+ // _currentColor = [self getGradientColor:mColorPercent];
+ // _currentWaveColor = [self getColorWithAlpha:_currentColor alpha:0.7f];
+ //
+ // [_currentColor setStroke];
+ // } else {
+ // //鑳屾櫙鍖洪棿
+ // [_pathBackColor setStroke];
+ // }
+ // CGContextAddPath(ctx, linePath.CGPath);
+ // CGContextStrokePath(ctx);
+ //
+ // }
+
+}
+
+///**
+// 缁樺埗鍒诲害杩涘害鏉�
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawProgressBar2:(CGContextRef)ctx{
+//
+//
+// //1.1 璁剧疆绾挎潯鐨勫搴�
+// CGContextSetLineWidth(ctx, mScaleLineHeight);
+// //1.2 璁剧疆绾挎潯鐨勮捣濮嬬偣鏍峰紡
+// CGContextSetLineCap(ctx, kCGLineCapButt);
+// //1.3 铏氬疄鍒囨崲 锛屽疄绾�5铏氱嚎10
+// CGFloat length[] = {mScaleLineWidth, mLinePadding};
+// CGContextSetLineDash(ctx, 0, length, 2);
+//
+// //1.4 璁剧疆棰滆壊
+// CGFloat mColorPercent = (CGFloat) 0 / mLineCount;
+// _currentColor = [self getGradientColor:mColorPercent];
+// [_currentColor setStroke];
+//
+//
+// //2.璁剧疆璺緞
+//
+//// [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(numberChange:) name:@"number" object:nil];
+//
+// CGFloat end = -5*M_PI_4+(6*M_PI_4*_mProgress/100);
+//
+// CGContextAddArc(ctx, _mArcWidth/2 , _mArcWidth/2, mArcRadius,M_PI/180*_mStartAngle, end , 0);
+//
+// //3.缁樺埗
+// CGContextStrokePath(ctx);
+//
+//}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ CGPoint startPoint = [touch locationInView:self];
+ _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+
+ // _bIsInArcProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ if(_bIsInArcProgress){
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ }
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ if(_bIsInArcProgress){
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ }
+ if(_bIsInArcProgress){
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+ }
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInArcProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+static inline CGFloat AngleFromNorth(CGPoint p1, CGPoint p2, BOOL flipped) {
+ CGPoint v = CGPointMake(p2.x-p1.x,p2.y-p1.y);
+ CGFloat vmag = sqrt(SQR(v.x) + SQR(v.y)), result = 0;
+ v.x /= vmag;
+ v.y /= vmag;
+ double radians = atan2(v.y,v.x);
+ result = ToDeg(radians);
+ return (result >=0 ? result : result + 360.0);
+}
+
+
+-(void)getCurrentAngleWithPoint:(CGPoint)point {
+
+
+}
+
+/*
+ * 鍒ゆ柇鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+ */
+-(BOOL)getStartPointIsInArcProgress:(CGPoint)lastPoint {
+ BOOL isIn = NO;
+ //鐢ㄤ簬鎺掗櫎鐐瑰湪鍦嗗闈㈢偣涓庡渾蹇冨崐寰勪竴鍗婁互鍐呯殑鐐�
+ if ((lastPoint.x >= 0 && lastPoint.x <= mSeekBarWidth)&&(lastPoint.y >= 0 && lastPoint.y <= mSeekBarHeight)) {
+ if ([self getTwoPointDistance:lastPoint endPonit:_mCenterPoint] > (mArcRadius - mRoundX)) {
+ isIn = YES;
+ }
+ }
+ return isIn;
+}
+
+/**
+ 璁$畻2鐐瑰潗鏍囦箣闂寸殑璺濈
+
+ @param startPoint 璧风偣鍧愭爣
+ @param endPonit 缁堢偣鍧愭爣
+ @return 璺濈
+ */
+-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
+ CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
+ float d = sqrt(SQR(v.x) + SQR(v.y));
+ // NSLog(@"2鐐硅窛绂�:%f ", d);
+// NSLog(@"getTwoPointDistance2鐐硅窛绂�:%f ", d);
+ return d;
+
+}
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+
+ CGFloat currentAngle = floor(AngleFromNorth(_mCenterPoint, point, NO));
+
+ //鍒ゆ柇鏄惁鍦ㄧ鍚堣搴�
+ if(currentAngle < _mStartAngle-10 && currentAngle > _mEndAngle+10){
+ return;
+ }
+
+ int diffAngle = currentAngle - _mStartAngle;
+
+
+ if (diffAngle < 0) {
+ if(currentAngle < 90) {
+ diffAngle = (diffAngle + 360) % 360;
+ }else {
+ diffAngle = 0;
+ }
+ }
+
+ _mPercent = diffAngle / _mSweepAngle;
+
+
+ // NSLog(@"point.y:%f currentAngle:%f diffAngle:%d",point.x, currentAngle,diffAngle);
+
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = _mPercent * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ mTargetCount = (int)(_mPercent * mLineCount);
+
+
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+
+ mTargetCount = (int)(_mPercent * mLineCount);
+
+ // [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+
+
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(CGFloat)mMinValue mMaxValue:(CGFloat)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+
+
+//鑾峰彇褰撳墠棰滆壊
+- (UIColor *)getGradientColor:(CGFloat)current {
+
+ CGFloat c1[4];
+ CGFloat c2[4];
+
+ [_startColor getRed:&c1[0] green:&c1[1] blue:&c1[2] alpha:&c1[3]];
+ [_endColor getRed:&c2[0] green:&c2[1] blue:&c2[2] alpha:&c2[3]];
+
+ return [UIColor colorWithRed:current*c2[0]+(1-current)*c1[0] green:current*c2[1]+(1-current)*c1[1] blue:current*c2[2]+(1-current)*c1[2] alpha:current*c2[3]+(1-current)*c1[3]];
+}
+
+//鑾峰彇褰撳墠棰滆壊
+- (UIColor *)getColorWithAlpha:(UIColor*)mColor alpha:(CGFloat)alpha {
+ CGFloat c1[4];
+ [mColor getRed:&c1[0] green:&c1[1] blue:&c1[2] alpha:&c1[3]];
+ return [UIColor colorWithRed:c1[0] green:c1[1] blue:c1[2] alpha:alpha];
+}
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ _startColor = startColor;
+ _endColor = endColor;
+ _mArcProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.h
new file mode 100644
index 0000000..2799882
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.h
@@ -0,0 +1,22 @@
+//
+// ScalePointData.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/13.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ScalePointData : NSObject
+
+//鍒诲害绾胯捣鐐�
+@property (nonatomic, assign) CGPoint startPoint;
+//鍒诲害绾跨粓鐐�
+@property (nonatomic, assign) CGPoint endPoint;;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.m
new file mode 100644
index 0000000..1591b70
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcScaleSeekBar/ScalePointData.m
@@ -0,0 +1,15 @@
+//
+// ScalePointData.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/13.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "ScalePointData.h"
+
+@implementation ScalePointData
+
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.h
new file mode 100644
index 0000000..b79288e
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.h
@@ -0,0 +1,189 @@
+//
+// HDLArcSeekbar.h
+// HDL-ArcSeekbar
+//
+// Created by HDL on 2019/7/19.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+
+#define APP_DEFAULT_BG [UIColor colorWithRed:72/255.0f green:72/255.0f blue:73/255.0f alpha:1.0f]
+
+typedef enum
+{
+ HDL_THUMB_FILL,
+ HDL_THUMB_STROKE,
+}HDLThumbMode;
+
+@protocol HDLArcSeekbarProgressChangedDelegate <NSObject>
+
+//鎵嬫寚鎸変笅锛屽紑濮嬬偣鍑�
+-(void)onStartTrackingTouch;
+
+//婊戝姩瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onProgressChanged:(int)mProgress;
+
+//鍋滄婊戝姩鎴栫粨鏉熺偣鍑伙紝瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onStopTrackingTouch:(int)mProgress;
+
+
+@end
+
+@interface HDLArcSeekbar : UIControl
+
+
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+///**
+// 杩涘害鏉¢鑹�
+// */
+//@property (nonatomic, strong) UIColor* mArcProgressBarColor;
+
+/**
+ 鑳屾櫙棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+/**
+ 鎷栧姩鎸夐挳棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) float mProgressCurrentValue;
+
+/**
+ 鍦嗗姬瀹藉害
+ */
+@property (nonatomic, assign) float mArcWidth;
+
+/**
+ 鎷栧姩鎸夐挳瀹藉害
+ */
+@property (nonatomic, assign) float mThumbWidth;
+
+/**
+ Thumb 鎷栧姩鎸夐挳椋庢牸
+ */
+@property (nonatomic, assign) HDLThumbMode mThumbMode;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+/**
+ 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+ */
+@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLArcSeekbarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLArcSeekbarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+/**
+ 璁剧疆寮�鍙h搴�
+
+ @param mOpenAngle 寮�鍙h搴�
+ */
+-(void)setOpenAngle:(float)mOpenAngle;
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+///**
+// *璁剧疆鏄惁鍙互鐐瑰嚮
+// */
+//-(void)setIsClickable:(BOOL)isClickable;
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameArc:(CGRect) mCGRect;
+
+
+
+///**
+// 璁剧疆娓愬彉鏁堟灉 棰滆壊鏁扮粍
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors;
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+/**
+ 璁剧疆杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor;
+
+@end
+
+
+//*****V1.0.3*****
+//# HDLArcSeekbar(鍦嗗姬鎷栧姩鏉�)
+//- [x] 澧炲姞onStartTrackingTouch 寮�濮嬬偣鍑讳簨浠讹紱
+
+
+//*****V1.0.2*****
+//# HDLArcSeekbar(鍦嗗姬鎷栧姩鏉�)
+//- [x] 澧炲姞鎷栧姩鎸夐挳瀹藉害鑷畾涔夛紱
+//- [x] 浼樺寲杩涘害鏄剧ず鏂囨湰浣嶇疆锛屽疄鐜版枃鏈眳涓紱
+//- [x] 淇敼绠楁硶锛屼紭鍖栨嫋鍔ㄦ寜閽嚜瀹氫箟瀹藉害鑰屼笉褰卞搷浣嶇疆锛�
+//- [x] 澧炲姞娓愬彉鏁堟灉锛�
+
+
+//*****V1.0.1*****
+//# HDLArcSeekbar(鍦嗗姬鎷栧姩鏉�)
+//- [x] 鏀寔杩涘害搴︾姸鎬佹樉绀哄��,鍜岃嚜瀹氫箟鏄剧ず鍗曚綅
+//- [x] 鏀寔杩涘害鏄剧ず鏉�
+//- [x] 澧炲姞绂佹鐐瑰嚮鎺ュ彛
+//
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.m
new file mode 100644
index 0000000..2eda209
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLArcSeekbar.m
@@ -0,0 +1,610 @@
+//
+// HDLArcSeekbar.m
+// HDL-ArcSeekbar
+//
+// Created by HDL on 2019/7/19.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLArcSeekbar.h"
+
+#define ToRad(deg) ( (M_PI * (deg)) / 180.0 )
+#define ToDeg(rad) ( (180.0 * (rad)) / M_PI )
+#define SQR(x) ( (x) * (x) )
+#define GETEndAngle(X) ( ((90-X) < 0) ? ((90-X)+360) : (90-X) )
+#define GETStartAngle(X) ( 90 + X)
+//#define DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC 30 // 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+#define DEFAULT_PADDING 40 //鍦嗗姬鑷甫PADDING鍊硷紝涓轰簡鏄剧ず杩涘害test鏂囧瓧
+#define DEFAULT_OPEN_ANGLE 30.0f // 寮�鍙h搴�
+
+
+@interface HDLArcSeekbar ()
+
+/**
+ 寮�鍙h搴�
+ */
+@property (nonatomic, assign) float mOpenAngle;
+
+//* 闃叉绐佸彉
+//* 鐢变簬杩涘害鏉℃椂鍦嗗姬褰㈢姸鐨�,鍥犳杩涘害鍙兘浼氫粠 0.0 鐩存帴绐佸彉鍒� 1.0 鎴栬�呯浉鍙�,鍥犳鍦ㄨ绠楄繘搴︿笌褰撳墠杩涘害宸紓杩囧ぇ鏃�,绂佹鏀瑰彉褰撳墠杩涘害.
+/**
+ 鏄惁鍏佽绐佸彉
+ */
+@property (nonatomic, assign) BOOL bAllowTouchSkip;
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mArcProgressBarColors;
+
+
+
+@end
+
+
+@implementation HDLArcSeekbar{
+ int _mProgressAngle; //褰撳墠杩涘害鍊煎搴旂殑瑙掑害
+ int _fixedAngle;
+ int _mMoveCount;
+
+ float _mArcStartAngle;
+ float _mArcEndAngle;
+ float _mArcAngle;
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+ CGFloat _mArcRadius; //鍗婂緞
+ CGFloat _mArcHeight;
+ bool _bIsInArcProgress;
+
+
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+ _mOpenAngle = DEFAULT_OPEN_ANGLE;
+ _mThumbMode = HDL_THUMB_STROKE;
+ _bAllowTouchSkip = NO; //绂佹绐佸彉
+ _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+ _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+ _mArcAngle = 360.0f - _mOpenAngle;
+ _mProgressAngle = _mArcStartAngle;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mProgressCurrentValue = _mMinValue;
+ _mArcWidth = 15.0f;
+ _mThumbWidth = 17.0f;
+ _mArcBackBarColor = APP_DEFAULT_BG;
+ // _mArcProgressBarColor = APP_BACKGROUND;
+ [self setProgressBarColor:UIColor.whiteColor];
+ _mThumbColor = [UIColor whiteColor];
+ _mProgressTextColor = [UIColor whiteColor];
+ _mProgressTextSize = 12;
+ _mTextDefaultDistance = 30;
+ _mProgressBarUnitSring = @"%";
+
+ if(self.frame.size.height > self.frame.size.width){
+ _mArcHeight = self.frame.size.width;
+ }else{
+ _mArcHeight = self.frame.size.height;
+ }
+ _mArcRadius = _mArcHeight/2 - _mArcWidth/2 - DEFAULT_PADDING;
+
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ self.backgroundColor = [UIColor clearColor];
+ }
+
+ return self;
+}
+
+
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鍥哄畾鐨勮儗鏅渾寮�*********
+ CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, _mArcRadius, M_PI/180*_mArcStartAngle, M_PI/180*_mArcEndAngle, 0);
+ [self setEndCornersRounded:ctx mUIColor:_mArcBackBarColor];//璁剧疆鏈鍦嗚鍜岄鑹�
+
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉″渾寮�*********
+ CGContextSetLineWidth(ctx, _mArcWidth);
+ // CGContextSetLineCap(ctx, kCGLineCapButt);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ CGContextDrawPath(ctx, kCGPathStroke);
+ CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, _mArcRadius, M_PI/180*_mArcStartAngle, M_PI/180*(_mProgressAngle), 0);
+ // [self setEndCornersRounded:ctx mUIColor:_mArcProgressBarColor];//璁剧疆鏈鍦嗚鍜岄鑹�
+
+ [self drawArcWithGradient:ctx rect:rect];//缁樺埗娓愬彉鏁堟灉
+
+
+ //*********缁樺埗鎷栧姩鐨凾humb鍦嗗舰鎸夐挳*********
+ [self drawThumbHandle:ctx];
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+
+}
+
+/**
+ 璁剧疆鏈鍦嗚
+
+ @param ctx ctx
+ @param mUIColor 棰滆壊
+ */
+-(void)setEndCornersRounded:(CGContextRef)ctx mUIColor:(UIColor*)mUIColor{
+ //**********************鏈鍦嗚**********************
+ CGContextSetStrokeColorWithColor(ctx, mUIColor.CGColor);
+ CGContextSetLineWidth(ctx, _mArcWidth);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ CGContextDrawPath(ctx, kCGPathStroke);
+}
+
+/**
+ 缁樺埗娓愬彉鏁堟灉
+ */
+-(void)drawArcWithGradient:(CGContextRef)ctx rect:(CGRect)rect{
+ // 鍒涘缓涓�涓笎鍙樿壊
+ // 鍒涘缓RGB鑹插僵绌洪棿锛屽垱寤鸿繖涓互鍚庯紝context閲岄潰鐢ㄧ殑棰滆壊閮芥槸鐢≧GB琛ㄧず
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+
+ // // 娓愬彉鑹茬殑棰滆壊
+ // NSArray *colorArr = @[
+ // (id)[UIColor blueColor].CGColor,
+ // (id)[UIColor yellowColor].CGColor
+ // ];
+ CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mArcProgressBarColors, NULL);
+ // 閲婃斁鑹插僵绌洪棿
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+
+ // "鍙嶉�夎矾寰�"
+ // CGContextReplacePathWithStrokedPath
+ // 灏哻ontext涓殑璺緞鏇挎崲鎴愯矾寰勭殑鎻忚竟鐗堟湰锛屼娇鐢ㄥ弬鏁癱ontext鍘昏绠楄矾寰勶紙鍗冲垱寤烘柊鐨勮矾寰勬槸鍘熸潵璺緞鐨勬弿杈癸級銆傜敤鎭板綋鐨勯鑹插~鍏呭緱鍒扮殑璺緞灏嗕骇鐢熺被浼肩粯鍒跺師鏉ヨ矾寰勭殑鏁堟灉銆備綘鍙互鍍忎娇鐢ㄤ竴鑸殑璺緞涓�鏍蜂娇鐢ㄥ畠銆備緥濡傦紝浣犲彲浠ラ�氳繃璋冪敤CGContextClip鍘诲壀瑁佽繖涓矾寰勭殑鎻忚竟
+ CGContextReplacePathWithStrokedPath(ctx);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ // 鐢ㄦ笎鍙樿壊濉厖
+ CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, rect.size.height / 2), CGPointMake(rect.size.width, rect.size.height / 2), 0);
+ // 閲婃斁娓愬彉鑹�
+ CGGradientRelease(gradient);
+ gradient = NULL;
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+}
+
+/**
+ 缁樺埗鎷栧姩Thumb鎸夐挳
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawThumbHandle:(CGContextRef)ctx{
+ CGPoint mThumbCenterPoint = [self getThumbCenterPointFromAngle: _mProgressAngle];
+ [_mThumbColor setStroke];
+ [_mThumbColor setFill];
+ if(_mThumbMode == HDL_THUMB_FILL){ //瀹炲績鍦�
+ CGContextSetLineWidth(ctx, _mThumbWidth);
+ CGContextFillEllipseInRect(ctx, CGRectMake(mThumbCenterPoint.x - _mThumbWidth/2, mThumbCenterPoint.y - _mThumbWidth/2, _mThumbWidth, _mThumbWidth));
+
+ }else{
+ //绌哄績鍦�
+ CGContextSetLineWidth(ctx, _mThumbWidth/3);
+ CGContextStrokeEllipseInRect(ctx, CGRectMake(mThumbCenterPoint.x - _mThumbWidth/2, mThumbCenterPoint.y -_mThumbWidth/2, _mThumbWidth, _mThumbWidth));
+ // CGContextAddEllipseInRect(ctx, CGRectMake(mThumbCenterPoint.x+2, mThumbCenterPoint.y+2, _mArcWidth-4, _mArcWidth-4));
+ // CGContextDrawPath(ctx, kCGPathStroke);
+ }
+
+ //缁樺埗褰撳墠杩涘害鍊兼枃鏈�
+ CGPoint outsidePoint = [self getCalcOutsidePoint:mThumbCenterPoint centerPoint:_mCenterPoint mRadius:_mArcRadius];
+ [self drawString:[NSString stringWithFormat:@"%d%@", (int8_t)roundf(_mProgressCurrentValue), _mProgressBarUnitSring] outsidePoint:outsidePoint];
+}
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+/**
+ 璁$畻2鐐瑰潗鏍囦箣闂寸殑璺濈
+
+ @param startPoint 璧风偣鍧愭爣
+ @param endPonit 缁堢偣鍧愭爣
+ @return 璺濈
+ */
+-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
+ CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
+ float d = sqrt(SQR(v.x) + SQR(v.y));
+ NSLog(@"2鐐硅窛绂�:%f ", d);
+ return d;
+
+}
+
+/*
+ * 鏍规嵁褰撳墠瑙掑害 璁$畻鍑烘嫋鍔ㄦ寜閽纭殑鍦嗗績鍧愭爣
+ */
+-(CGPoint)getThumbCenterPointFromAngle:(int)angleInt{
+ //Define the Circle center
+ // CGPoint centerPoint = CGPointMake(self.frame.size.width/2 - _mArcWidth/2, self.frame.size.height/2 - _mArcWidth/2);
+ // //Define The point position on the circumference
+ // CGPoint result;
+ // result.y = round(centerPoint.y + _mArcRadius * sin(ToRad(angleInt)));
+ // result.x = round(centerPoint.x + _mArcRadius * cos(ToRad(angleInt)));
+
+
+ CGPoint result;
+ result.y = round(_mCenterPoint.y + _mArcRadius * sin(ToRad(angleInt)));
+ result.x = round(_mCenterPoint.x + _mArcRadius * cos(ToRad(angleInt)));
+ return result;
+}
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+ CGPoint startPoint = [touch locationInView:self];
+ _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getEndPointIsInArcProgress:lastPoint];//鍒ゆ柇鏈�鍚庣寮�鐨勫潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:(int8_t)roundf(_mProgressCurrentValue)];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+ // CGPoint lastPoint = [touch locationInView:self];
+ // [self getPointIsInArcProgress:lastPoint];//鍒ゆ柇鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+
+ if(_bIsInArcProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鍒ゆ柇鏈�鍚庣寮�鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+
+ @param lastPoint 鏈�鍚庣殑鍧愭爣
+ */
+-(void)getEndPointIsInArcProgress:(CGPoint)lastPoint {
+ //鐢ㄤ簬鎺掗櫎鐐瑰湪鍦嗗闈㈢偣涓庡渾蹇冨崐寰勪竴鍗婁互鍐呯殑鐐�
+ if([self getStartPointIsInArcProgress:lastPoint]){
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+}
+
+/*
+ * 鍒ゆ柇鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+ * In the clickable area
+ * R/2 R/2
+ * [----锛圧----.鈥斺�斺�斺�斿渾蹇�----.鈥斺�斺�斺�擱)----]
+ * { 鍙偣鍑诲尯鍩� }*涓嶅彲鐐瑰尯鍩�*{ 鍙偣鍑诲尯鍩� }
+ */
+-(BOOL)getStartPointIsInArcProgress:(CGPoint)lastPoint {
+ BOOL isIn = NO;
+ //鐢ㄤ簬鎺掗櫎鐐瑰湪鍦嗗闈㈢偣涓庡渾蹇冨崐寰勪竴鍗婁互鍐呯殑鐐�
+ if ((lastPoint.x >= 0 &&lastPoint.x <= _mArcHeight)&&(lastPoint.y >= 0 && lastPoint.y <= _mArcHeight)) {
+ CGFloat leftR = (_mArcHeight - _mArcRadius) / 2;
+ CGFloat rightR = (_mArcHeight + _mArcRadius) / 2;
+ if ((lastPoint.x <= leftR || lastPoint.x >= rightR)
+ || (lastPoint.y <= leftR || lastPoint.y >= rightR)) {
+ isIn = YES;
+ }
+ }
+ return isIn;
+}
+
+/**
+ 鍒ゆ柇鏄惁涓虹獊鍙樺潗鏍�
+
+ @param oldP 涓婁竴娆$殑杩涘害瑙掑害
+ @param newP 褰撳墠鍧愭爣瀵瑰簲鐨勮搴�
+ @return 鍒ゆ柇缁撴灉
+ */
+-(BOOL)getIfMutationPoint:(int)oldP newP:(int)newP{
+ return fabsf( (newP - oldP) / (_mArcStartAngle + _mArcAngle)) > 0.5f;
+}
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶇湡姝g殑瑙掑害鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+ // NSLog(@"_mProgressAngle start:%f ",_mProgressCurrentValue);
+
+ int currentAngle = floor(AngleFromNorth(_mCenterPoint, point, NO));
+
+ if (currentAngle > _mArcEndAngle && currentAngle < _mArcStartAngle) {
+
+ }else{
+ if (currentAngle <= _mArcEndAngle) {
+ currentAngle += 360.0f;
+ }
+
+ if(_bTouchMove){ //绉诲姩鐨勬椂鍊欐墠闃叉绐佸彉
+ if(!_bAllowTouchSkip){ //绂佹绐佸彉
+ // 涓嶅厑璁哥獊鍙�
+ if([self getIfMutationPoint:_mProgressAngle newP:currentAngle]){
+ return;
+ }
+ }
+ _mProgressAngle = currentAngle;
+ _mProgressCurrentValue = [self getProgressValueFromAngle];
+ //绉诲姩鐨勬椂鍊欐墠鍙戦�乷nProgressChanged浠g悊浜嬩欢
+ [self.mProgressChangedDelegate onProgressChanged:(int8_t)roundf(_mProgressCurrentValue)];
+
+ }else{
+ _mProgressAngle = currentAngle;
+ _mProgressCurrentValue = [self getProgressValueFromAngle];
+ }
+
+ // NSLog(@"_mProgressAngle end:%d ",_mProgressAngle);
+
+ }
+
+ [self setNeedsDisplay];
+
+}
+
+static inline float AngleFromNorth(CGPoint p1, CGPoint p2, BOOL flipped) {
+ CGPoint v = CGPointMake(p2.x-p1.x,p2.y-p1.y);
+ float vmag = sqrt(SQR(v.x) + SQR(v.y)), result = 0;
+ v.x /= vmag;
+ v.y /= vmag;
+ double radians = atan2(v.y,v.x);
+ result = ToDeg(radians);
+ return (result >=0 ? result : result + 360.0);
+}
+
+/**
+ 鑾峰彇鐩稿悓璺濈涓嬶紝鍦嗗姬瀵瑰簲鐨勭涓夌偣鍧愭爣
+
+ @param mPoint 褰撳墠鍦嗗姬鍧愭爣
+ @param centerPoint 鍦嗗姬鍦嗗績鍧愭爣
+ @param mRadius 鍦嗗姬鍗婂緞
+ @return 鍦嗗鍧愭爣
+ */
+-(CGPoint) getCalcOutsidePoint:(CGPoint) mPoint centerPoint:(CGPoint)centerPoint mRadius:(float)mRadius {
+ CGFloat newX = (mPoint.x * (mRadius + _mTextDefaultDistance) - centerPoint.x * _mTextDefaultDistance) / mRadius;
+ CGFloat newY = (mPoint.y * (mRadius + _mTextDefaultDistance) - centerPoint.y * _mTextDefaultDistance) / mRadius;
+ return CGPointMake(newX, newY);
+}
+
+
+/**
+ 鏍规嵁瑙掑害 璁$畻鍑哄綋鍓嶈繘搴﹀��
+ 鍦ㄨ繖涓湴鏂硅皟鏁磋繘搴︽潯
+
+ @return 鐪熸鐨勮繘搴﹀��
+ */
+-(float)getProgressValueFromAngle {
+ if(_mProgressAngle <= _mArcEndAngle) {
+ _mProgressCurrentValue = 360 - _mArcStartAngle + _mProgressAngle;
+ } else if(_mProgressAngle > _mArcEndAngle && _mProgressAngle < _mArcStartAngle){
+
+ }else{
+ _mProgressCurrentValue = _mProgressAngle - _mArcStartAngle;
+ }
+ _fixedAngle = _mProgressCurrentValue;
+ // NSLog(@"KK_mProgressCurrentValueangle:%d",_mProgressAngle);
+ // NSLog(@"KK_mProgressCurrentValue:%f",_mProgressCurrentValue);
+ return (_mProgressCurrentValue*(_mMaxValue - _mMinValue))/_mArcAngle + _mMinValue;
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+// _mProgressCurrentValue = mProgress - _mMinValue;
+ _mProgressCurrentValue = mProgress;
+ _mProgressAngle = (mProgress - _mMinValue) * _mArcAngle / (_mMaxValue - _mMinValue) + _mArcStartAngle;
+
+// [self.mProgressChangedDelegate onProgressChanged:(int8_t)roundf(_mProgressCurrentValue)];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆寮�鍙h搴�
+
+ @param mOpenAngle 寮�鍙h搴�
+ */
+-(void)setOpenAngle:(float)mOpenAngle{
+ _mOpenAngle = mOpenAngle;
+ _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+ _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+ _mArcAngle = 360.0f - _mOpenAngle;
+ _mProgressAngle = _mArcStartAngle;
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgressCurrentValue = _mMinValue;
+ _mProgressAngle = _mProgressCurrentValue * _mArcAngle / (_mMaxValue - _mMinValue) + _mArcStartAngle;
+}
+
+-(void)initWithFrameArc:(CGRect) mCGRect{
+ self.frame = mCGRect;
+
+ if(self.frame.size.height > self.frame.size.width){
+ _mArcHeight = self.frame.size.width;
+ }else{
+ _mArcHeight = self.frame.size.height;
+ }
+ _mArcRadius = _mArcHeight/2 - _mArcWidth/2 - DEFAULT_PADDING;
+
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+}
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param mColors 棰滆壊鏁扮粍
+ */
+-(void)setProgressBarColors:(NSArray *)mColors{
+
+ // NSArray * colors = [NSArray arrayWithObjects锛氾紙id锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+
+}
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param mColors 棰滆壊鏁扮粍
+ */
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mArcProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mArcProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+}
+
+///**
+// 璁剧疆寮�鍙h搴�
+//
+// @param mOpenAngle 寮�鍙h搴�
+// */
+//-(void)setOpenAngle:(float)mOpenAngle{
+// _mOpenAngle = mOpenAngle;
+// _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+// _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+// _mArcAngle = 360.0f - _mOpenAngle;
+// _mProgressAngle = _mArcStartAngle;
+//}
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.h
new file mode 100644
index 0000000..eee1988
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.h
@@ -0,0 +1,137 @@
+//
+// HDLDiyArcSeekbar.h
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLDiyArcSeekbar : UIControl
+
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+/**
+ 鑳屾櫙棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) float mProgressCurrentValue;
+
+/**
+ 鍦嗗姬瀹藉害
+ */
+@property (nonatomic, assign) float mArcWidth;
+
+
+
+
+#pragma mark HDLRollSeekBarSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+/**
+ 璁剧疆寮�鍙h搴�
+
+ @param mOpenAngle 寮�鍙h搴�
+ */
+-(void)setOpenAngle:(float)mOpenAngle;
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+/**
+ 璁剧疆杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor;
+
+/**
+ 璁剧疆绂荤嚎鏃� 杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setOfflineProgressBarColor:(UIColor *)oneColor;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding;
+
+
+/**
+ 璁剧疆鎸夐挳瀹藉害
+ */
+-(void)setThumbImgBtnWidth:(int)Width;
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setThumbImgBtnImg:(UIImage*) mImage;
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖鏄惁鏄剧ず
+ */
+-(void)setThumbImgBtnShow:(BOOL) isShow;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+
+/**
+ 璁剧疆鍦嗗姬瀹藉害
+ */
+-(void)setArcWidth:(float)mArcWidth;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.m
new file mode 100644
index 0000000..71b78f7
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/HDLDiyArcSeekbar.m
@@ -0,0 +1,682 @@
+//
+// HDLDiyArcSeekbar.m
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import "HDLDiyArcSeekbar.h"
+#import "HDLUtlisXM.h"
+
+//#define APP_DEFAULT_BG HEXCOLOR(0xF2F3F7)
+#define APP_DEFAULT_BG_OFFLINE HEXCOLOR(0xDFE1E6)
+
+#define ToRad(deg) ( (M_PI * (deg)) / 180.0 )
+#define ToDeg(rad) ( (180.0 * (rad)) / M_PI )
+#define SQR(x) ( (x) * (x) )
+#define GETEndAngle(X) ( ((90-X) < 0) ? ((90-X)+360) : (90-X) )
+#define GETStartAngle(X) ( 90 + X)
+//#define DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC 30 // 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+//#define DEFAULT_PADDING 40 //鍦嗗姬鑷甫PADDING鍊硷紝涓轰簡鏄剧ず杩涘害test鏂囧瓧
+#define DEFAULT_OPEN_ANGLE 180.0f // 寮�鍙h搴�
+
+
+@interface HDLDiyArcSeekbar ()
+
+/**
+ 寮�鍙h搴�
+ */
+@property (nonatomic, assign) float mOpenAngle;
+
+//* 闃叉绐佸彉
+//* 鐢变簬杩涘害鏉℃椂鍦嗗姬褰㈢姸鐨�,鍥犳杩涘害鍙兘浼氫粠 0.0 鐩存帴绐佸彉鍒� 1.0 鎴栬�呯浉鍙�,鍥犳鍦ㄨ绠楄繘搴︿笌褰撳墠杩涘害宸紓杩囧ぇ鏃�,绂佹鏀瑰彉褰撳墠杩涘害.
+/**
+ 鏄惁鍏佽绐佸彉
+ */
+@property (nonatomic, assign) BOOL bAllowTouchSkip;
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+///**
+// 杩涘害鍗曚綅绗﹀彿
+// */
+//@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mArcProgressBarColors;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mArcOfflineProgressBarColors;
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int DiyBarPadding;
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+/**
+ 鏄惁鏄剧ず鎷栧姩鎸夐挳
+ */
+@property (nonatomic, assign) BOOL isThumbImgBtnShow;
+
+@end
+
+
+@implementation HDLDiyArcSeekbar{
+ int _mProgressAngle; //褰撳墠杩涘害鍊煎搴旂殑瑙掑害
+ int _fixedAngle;
+ int _mMoveCount;
+
+ float _mArcStartAngle;
+ float _mArcEndAngle;
+ float _mArcAngle;
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+ CGFloat _mArcRadius; //鍗婂緞
+ CGFloat _mArcHeight;
+ bool _bIsInArcProgress;
+ UIImage *_thumbImgBtn;
+ CGFloat _thumbImgBtnWidth;
+
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+ _mOpenAngle = DEFAULT_OPEN_ANGLE;
+ _bAllowTouchSkip = NO; //绂佹绐佸彉
+ _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+ _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+ _mArcAngle = 360.0f - _mOpenAngle;
+ _mProgressAngle = _mArcStartAngle;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mProgressCurrentValue = _mMinValue;
+ _mArcWidth = 10.0f;
+ _thumbImgBtnWidth = _mArcWidth * 2;
+ _DiyBarPadding = _thumbImgBtnWidth/2+5;
+ _isThumbImgBtnShow = YES;
+ _mArcBackBarColor = HEXCOLOR(0xF2F3F7);
+
+ [self setProgressBarColor:HEXCOLOR(0xFFEB3B)];
+ [self setOfflineProgressBarColor:HEXCOLOR(0xD3D3D3)];
+ [self refreshFrame];
+ self.backgroundColor = [UIColor clearColor];
+ _thumbImgBtn = [UIImage imageNamed:@"ic_wd_curtain_h_open"];
+
+ }
+
+ return self;
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+ */
+-(void)refreshFrame{
+ if(self.frame.size.height > self.frame.size.width){
+ _mArcHeight = self.frame.size.width;
+ }else{
+ _mArcHeight = self.frame.size.height;
+ }
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onDiyBarSizeChange];
+}
+
+/**
+ onDiyBarSizeChange
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+ */
+-(void)onDiyBarSizeChange{
+ _mArcRadius = _mArcHeight/2 - _mArcWidth/2 - _DiyBarPadding;
+
+}
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鍥哄畾鐨勮儗鏅渾寮�*********
+ if(_mArcEndAngle == 90){
+ CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, _mArcRadius, M_PI/180*_mArcStartAngle, M_PI/180*450, 0);
+ }else{
+ CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, _mArcRadius, M_PI/180*_mArcStartAngle, M_PI/180*_mArcEndAngle, 0);
+
+ }
+ [self setEndCornersRounded:ctx mUIColor:_mArcBackBarColor];//璁剧疆鏈鍦嗚鍜岄鑹�
+
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉″渾寮�*********
+ CGContextSetLineWidth(ctx, _mArcWidth);
+ // CGContextSetLineCap(ctx, kCGLineCapButt);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ CGContextDrawPath(ctx, kCGPathStroke);
+ CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, _mArcRadius, M_PI/180*_mArcStartAngle, M_PI/180*(_mProgressAngle), 0);
+ // [self setEndCornersRounded:ctx mUIColor:_mArcProgressBarColor];//璁剧疆鏈鍦嗚鍜岄鑹�
+
+ [self drawArcWithGradient:ctx rect:rect];//缁樺埗娓愬彉鏁堟灉
+
+
+ //*********缁樺埗鎷栧姩鐨凾humb鍦嗗舰鎸夐挳*********
+ [self drawThumbHandle:ctx];
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+
+}
+
+/**
+ 璁剧疆鏈鍦嗚
+
+ @param ctx ctx
+ @param mUIColor 棰滆壊
+ */
+-(void)setEndCornersRounded:(CGContextRef)ctx mUIColor:(UIColor*)mUIColor{
+ //**********************鏈鍦嗚**********************
+ CGContextSetStrokeColorWithColor(ctx, mUIColor.CGColor);
+ CGContextSetLineWidth(ctx, _mArcWidth);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ CGContextDrawPath(ctx, kCGPathStroke);
+}
+
+/**
+ 缁樺埗娓愬彉鏁堟灉
+ */
+-(void)drawArcWithGradient:(CGContextRef)ctx rect:(CGRect)rect{
+ // 鍒涘缓涓�涓笎鍙樿壊
+ // 鍒涘缓RGB鑹插僵绌洪棿锛屽垱寤鸿繖涓互鍚庯紝context閲岄潰鐢ㄧ殑棰滆壊閮芥槸鐢≧GB琛ㄧず
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGGradientRef gradient;
+ if(!_isOffline){
+ gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mArcProgressBarColors, NULL);
+ }else{
+ gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mArcOfflineProgressBarColors, NULL);
+ }
+
+ // 閲婃斁鑹插僵绌洪棿
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+
+ // "鍙嶉�夎矾寰�"
+ // CGContextReplacePathWithStrokedPath
+ // 灏哻ontext涓殑璺緞鏇挎崲鎴愯矾寰勭殑鎻忚竟鐗堟湰锛屼娇鐢ㄥ弬鏁癱ontext鍘昏绠楄矾寰勶紙鍗冲垱寤烘柊鐨勮矾寰勬槸鍘熸潵璺緞鐨勬弿杈癸級銆傜敤鎭板綋鐨勯鑹插~鍏呭緱鍒扮殑璺緞灏嗕骇鐢熺被浼肩粯鍒跺師鏉ヨ矾寰勭殑鏁堟灉銆備綘鍙互鍍忎娇鐢ㄤ竴鑸殑璺緞涓�鏍蜂娇鐢ㄥ畠銆備緥濡傦紝浣犲彲浠ラ�氳繃璋冪敤CGContextClip鍘诲壀瑁佽繖涓矾寰勭殑鎻忚竟
+ CGContextReplacePathWithStrokedPath(ctx);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ // 鐢ㄦ笎鍙樿壊濉厖
+ CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, rect.size.height / 2), CGPointMake(rect.size.width, rect.size.height / 2), 0);
+ // 閲婃斁娓愬彉鑹�
+ CGGradientRelease(gradient);
+ gradient = NULL;
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+}
+
+/**
+ 缁樺埗鎷栧姩Thumb鎸夐挳
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawThumbHandle:(CGContextRef)ctx{
+ if(!_isThumbImgBtnShow) return;
+
+ CGPoint mThumbCenterPoint = [self getThumbCenterPointFromAngle: _mProgressAngle];
+ CGRect rectImage = CGRectMake(mThumbCenterPoint.x - _thumbImgBtnWidth/2, mThumbCenterPoint.y - _thumbImgBtnWidth/2, _thumbImgBtnWidth, _thumbImgBtnWidth);
+ [_thumbImgBtn drawInRect:rectImage];
+}
+
+///**
+// drawString 鐜板湪褰撳墠杩涘害鍊�
+// @param mText 鏄剧ず鏂囨湰
+// @param outsidePoint 鍧愭爣
+// */
+//- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+// NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+// paragraph.alignment = NSTextAlignmentCenter;
+// NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+// NSForegroundColorAttributeName : _mProgressTextColor,
+// NSParagraphStyleAttributeName : paragraph
+// };
+//
+// // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+// // [mText drawInRect:textRect withAttributes:dic];
+//
+// //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+// CGSize textSize = [mText sizeWithAttributes:dic];
+// CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+// [mText drawAtPoint:textPoint withAttributes:dic];
+//
+//}
+
+
+/**
+ 璁$畻2鐐瑰潗鏍囦箣闂寸殑璺濈
+
+ @param startPoint 璧风偣鍧愭爣
+ @param endPonit 缁堢偣鍧愭爣
+ @return 璺濈
+ */
+-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
+ CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
+ float d = sqrt(SQR(v.x) + SQR(v.y));
+ NSLog(@"2鐐硅窛绂�:%f ", d);
+ return d;
+
+}
+
+/*
+ * 鏍规嵁褰撳墠瑙掑害 璁$畻鍑烘嫋鍔ㄦ寜閽纭殑鍦嗗績鍧愭爣
+ */
+-(CGPoint)getThumbCenterPointFromAngle:(int)angleInt{
+ //Define the Circle center
+ // CGPoint centerPoint = CGPointMake(self.frame.size.width/2 - _mArcWidth/2, self.frame.size.height/2 - _mArcWidth/2);
+ // //Define The point position on the circumference
+ // CGPoint result;
+ // result.y = round(centerPoint.y + _mArcRadius * sin(ToRad(angleInt)));
+ // result.x = round(centerPoint.x + _mArcRadius * cos(ToRad(angleInt)));
+
+
+ CGPoint result;
+ result.y = round(_mCenterPoint.y + _mArcRadius * sin(ToRad(angleInt)));
+ result.x = round(_mCenterPoint.x + _mArcRadius * cos(ToRad(angleInt)));
+ return result;
+}
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+ CGPoint startPoint = [touch locationInView:self];
+ _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getEndPointIsInArcProgress:lastPoint];//鍒ゆ柇鏈�鍚庣寮�鐨勫潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:(int8_t)roundf(_mProgressCurrentValue)];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+ // CGPoint lastPoint = [touch locationInView:self];
+ // [self getPointIsInArcProgress:lastPoint];//鍒ゆ柇鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+
+ if(_bIsInArcProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鍒ゆ柇鏈�鍚庣寮�鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+
+ @param lastPoint 鏈�鍚庣殑鍧愭爣
+ */
+-(void)getEndPointIsInArcProgress:(CGPoint)lastPoint {
+ //鐢ㄤ簬鎺掗櫎鐐瑰湪鍦嗗闈㈢偣涓庡渾蹇冨崐寰勪竴鍗婁互鍐呯殑鐐�
+ if([self getStartPointIsInArcProgress:lastPoint]){
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+}
+
+/*
+ * 鍒ゆ柇鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+ * In the clickable area
+ * R/2 R/2
+ * [----锛圧----.鈥斺�斺�斺�斿渾蹇�----.鈥斺�斺�斺�擱)----]
+ * { 鍙偣鍑诲尯鍩� }*涓嶅彲鐐瑰尯鍩�*{ 鍙偣鍑诲尯鍩� }
+ */
+-(BOOL)getStartPointIsInArcProgress:(CGPoint)lastPoint {
+ BOOL isIn = NO;
+ //鐢ㄤ簬鎺掗櫎鐐瑰湪鍦嗗闈㈢偣涓庡渾蹇冨崐寰勪竴鍗婁互鍐呯殑鐐�
+ if ((lastPoint.x >= 0 &&lastPoint.x <= _mArcHeight)&&(lastPoint.y >= 0 && lastPoint.y <= _mArcHeight)) {
+ CGFloat leftR = (_mArcHeight - _mArcRadius) / 2;
+ CGFloat rightR = (_mArcHeight + _mArcRadius) / 2;
+ if ((lastPoint.x <= leftR || lastPoint.x >= rightR)
+ || (lastPoint.y <= leftR || lastPoint.y >= rightR)) {
+ isIn = YES;
+ }
+ }
+ return isIn;
+}
+
+/**
+ 鍒ゆ柇鏄惁涓虹獊鍙樺潗鏍�
+
+ @param oldP 涓婁竴娆$殑杩涘害瑙掑害
+ @param newP 褰撳墠鍧愭爣瀵瑰簲鐨勮搴�
+ @return 鍒ゆ柇缁撴灉
+ */
+-(BOOL)getIfMutationPoint:(int)oldP newP:(int)newP{
+ return fabsf( (newP - oldP) / (_mArcStartAngle + _mArcAngle)) > 0.5f;
+}
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶇湡姝g殑瑙掑害鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+ // NSLog(@"_mProgressAngle start:%f ",_mProgressCurrentValue);
+
+ int currentAngle = floor(AngleFromNorth(_mCenterPoint, point, NO));
+
+ if (currentAngle > _mArcEndAngle && currentAngle < _mArcStartAngle) {
+
+ }else{
+ if (currentAngle <= _mArcEndAngle) {
+ currentAngle += 360.0f;
+ }
+
+ if(_bTouchMove){ //绉诲姩鐨勬椂鍊欐墠闃叉绐佸彉
+ if(!_bAllowTouchSkip){ //绂佹绐佸彉
+ // 涓嶅厑璁哥獊鍙�
+ if([self getIfMutationPoint:_mProgressAngle newP:currentAngle]){
+ return;
+ }
+ }
+ _mProgressAngle = currentAngle;
+ _mProgressCurrentValue = [self getProgressValueFromAngle];
+ //绉诲姩鐨勬椂鍊欐墠鍙戦�乷nProgressChanged浠g悊浜嬩欢
+ [self.mProgressChangedDelegate onProgressChanged:(int8_t)roundf(_mProgressCurrentValue)];
+
+ }else{
+ _mProgressAngle = currentAngle;
+ _mProgressCurrentValue = [self getProgressValueFromAngle];
+ }
+
+ // NSLog(@"_mProgressAngle end:%d ",_mProgressAngle);
+
+ }
+
+ [self setNeedsDisplay];
+
+}
+
+static inline float AngleFromNorth(CGPoint p1, CGPoint p2, BOOL flipped) {
+ CGPoint v = CGPointMake(p2.x-p1.x,p2.y-p1.y);
+ float vmag = sqrt(SQR(v.x) + SQR(v.y)), result = 0;
+ v.x /= vmag;
+ v.y /= vmag;
+ double radians = atan2(v.y,v.x);
+ result = ToDeg(radians);
+ return (result >=0 ? result : result + 360.0);
+}
+
+///**
+// 鑾峰彇鐩稿悓璺濈涓嬶紝鍦嗗姬瀵瑰簲鐨勭涓夌偣鍧愭爣
+//
+// @param mPoint 褰撳墠鍦嗗姬鍧愭爣
+// @param centerPoint 鍦嗗姬鍦嗗績鍧愭爣
+// @param mRadius 鍦嗗姬鍗婂緞
+// @return 鍦嗗鍧愭爣
+// */
+//-(CGPoint) getCalcOutsidePoint:(CGPoint) mPoint centerPoint:(CGPoint)centerPoint mRadius:(float)mRadius {
+// CGFloat newX = (mPoint.x * (mRadius + _mTextDefaultDistance) - centerPoint.x * _mTextDefaultDistance) / mRadius;
+// CGFloat newY = (mPoint.y * (mRadius + _mTextDefaultDistance) - centerPoint.y * _mTextDefaultDistance) / mRadius;
+// return CGPointMake(newX, newY);
+//}
+
+
+/**
+ 鏍规嵁瑙掑害 璁$畻鍑哄綋鍓嶈繘搴﹀��
+ 鍦ㄨ繖涓湴鏂硅皟鏁磋繘搴︽潯
+
+ @return 鐪熸鐨勮繘搴﹀��
+ */
+-(float)getProgressValueFromAngle {
+ if(_mProgressAngle <= _mArcEndAngle) {
+ _mProgressCurrentValue = 360 - _mArcStartAngle + _mProgressAngle;
+ } else if(_mProgressAngle > _mArcEndAngle && _mProgressAngle < _mArcStartAngle){
+
+ }else{
+ _mProgressCurrentValue = _mProgressAngle - _mArcStartAngle;
+ }
+ _fixedAngle = _mProgressCurrentValue;
+ // NSLog(@"KK_mProgressCurrentValueangle:%d",_mProgressAngle);
+ // NSLog(@"KK_mProgressCurrentValue:%f",_mProgressCurrentValue);
+ return (_mProgressCurrentValue*(_mMaxValue - _mMinValue))/_mArcAngle + _mMinValue;
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ // _mProgressCurrentValue = mProgress - _mMinValue;
+ _mProgressCurrentValue = mProgress;
+ _mProgressAngle = (mProgress - _mMinValue) * _mArcAngle / (_mMaxValue - _mMinValue) + _mArcStartAngle;
+
+ // [self.mProgressChangedDelegate onProgressChanged:(int8_t)roundf(_mProgressCurrentValue)];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆寮�鍙h搴�
+
+ @param mOpenAngle 寮�鍙h搴�
+ */
+-(void)setOpenAngle:(float)mOpenAngle{
+ _mOpenAngle = mOpenAngle;
+ _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+ _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+ _mArcAngle = 360.0f - _mOpenAngle;
+ _mProgressAngle = _mArcStartAngle;
+ [self setNeedsDisplay];
+}
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgressCurrentValue = _mMinValue;
+ _mProgressAngle = _mProgressCurrentValue * _mArcAngle / (_mMaxValue - _mMinValue) + _mArcStartAngle;
+}
+
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+
+
+}
+
+///**
+// 璁剧疆娓愬彉鏁堟灉
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors{
+//
+// // NSArray * colors = [NSArray arrayWithObjects锛氾紙id锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+//
+//}
+//
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param mColors 棰滆壊鏁扮粍
+ */
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mArcProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mArcProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆绂荤嚎杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setOfflineProgressBarColor:(UIColor *)oneColor{
+ _mArcOfflineProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+}
+
+
+///**
+// 璁剧疆寮�鍙h搴�
+//
+// @param mOpenAngle 寮�鍙h搴�
+// */
+//-(void)setOpenAngle:(float)mOpenAngle{
+// _mOpenAngle = mOpenAngle;
+// _mArcStartAngle = GETStartAngle(_mOpenAngle/2);
+// _mArcEndAngle = GETEndAngle(_mOpenAngle/2);
+// _mArcAngle = 360.0f - _mOpenAngle;
+// _mProgressAngle = _mArcStartAngle;
+//}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding{
+ _DiyBarPadding = Padding;
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 璁剧疆鎸夐挳楂樺害
+ */
+-(void)setThumbImgBtnWidth:(int)mWidth{
+ _thumbImgBtnWidth = mWidth;
+ _DiyBarPadding = _thumbImgBtnWidth/2+5;
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setThumbImgBtnImg:(UIImage*) mImage{
+ _thumbImgBtn = mImage;
+}
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setThumbImgBtnShow:(BOOL) isShow{
+ _isThumbImgBtnShow = isShow;
+}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 璁剧疆鍦嗗姬瀹藉害
+ */
+-(void)setArcWidth:(float)mArcWidth{
+ _mArcWidth = mArcWidth;
+ [self onDiyBarSizeChange];
+
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.h
new file mode 100644
index 0000000..4d4593b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.h
@@ -0,0 +1,32 @@
+//
+// SeekBarDelegate.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+@protocol HDLSeekBarProgressChangedDelegate <NSObject>
+
+//鎵嬫寚鎸変笅锛屽紑濮嬬偣鍑�
+-(void)onStartTrackingTouch;
+
+//婊戝姩瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onProgressChanged:(int)mProgress;
+
+//鍋滄婊戝姩鎴栫粨鏉熺偣鍑伙紝瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onStopTrackingTouch:(int)mProgress;
+
+
+@end
+
+@interface SeekBarDelegate : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.m
new file mode 100644
index 0000000..3752f0f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLArcSeekbar/SeekBarDelegate.m
@@ -0,0 +1,13 @@
+//
+// SeekBarDelegate.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "SeekBarDelegate.h"
+
+@implementation SeekBarDelegate
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.h
new file mode 100644
index 0000000..71de74f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.h
@@ -0,0 +1,60 @@
+//
+// HDLCoverFlow.h
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/23.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+@protocol SelectItemDelegate <NSObject>
+
+////鎵嬫寚鎸変笅锛屽紑濮嬬偣鍑�
+//-(void)onStartTrackingTouch;
+
+//閫変腑椤�
+-(void)onSelectItem:(NSInteger)mSelectIndex;
+
+
+
+@end
+
+@interface HDLCoverFlow : UIView
+
+#pragma mark SelectItemDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<SelectItemDelegate> mSelectItemDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+
+/**
+ 璁剧疆view
+
+ @param viewsData
+ */
+-(void)addCoverFlowViewDatas:(NSArray<UIView *> *) viewsData;
+
+/**
+ 璁剧疆閫変腑
+
+ @param selectIndex
+ */
+-(void)setCoverFlowSelectIndex:(NSInteger) selectIndex;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameArc:(CGRect) mCGRect;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.m
new file mode 100644
index 0000000..6ae5d20
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlow.m
@@ -0,0 +1,127 @@
+//
+// HDLCoverFlow.m
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/23.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+#import "HDLCoverFlow.h"
+#import "HDLCoverFlowCell.h"
+#import "HDLCoverFlowLayout.h"
+
+@interface HDLCoverFlow()<UICollectionViewDataSource,UICollectionViewDelegate>
+@property (nonatomic,strong) UICollectionView *mUICollectionView;
+
+
+@end
+
+
+@implementation HDLCoverFlow{
+
+ NSArray<UIView *> *viewDataArray;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame{
+ if (self = [super initWithFrame:frame]) {
+ [self addSubview:self.mUICollectionView];
+ }
+ return self;
+}
+
+#pragma mark- 瀛愭帶浠跺潗鏍�
+//褰撴帶浠舵湰韬殑灏哄鍙戦�佹敼鍙樻椂锛岀郴缁熶細鑷姩璋冪敤杩欎釜鏂规硶
+- (void)layoutSubviews{
+ [super layoutSubviews];
+
+ CGFloat personW = self.frame.size.width;
+ CGFloat personH = self.frame.size.height;
+
+ self.mUICollectionView.frame = CGRectMake(0, 0, personW, personH);
+
+}
+
+#pragma mark- 鎳掑姞杞�
+- (UICollectionView *)mUICollectionView{
+ if (_mUICollectionView == nil) {
+ HDLCoverFlowLayout *flowLayout = [[HDLCoverFlowLayout alloc]init];
+
+ _mUICollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0,self.frame.size.width, self.frame.size.height) collectionViewLayout:flowLayout];
+ _mUICollectionView.backgroundColor = [UIColor lightGrayColor];
+ // 璁剧疆鏁版嵁婧愬璞�
+ _mUICollectionView.dataSource = self;
+ _mUICollectionView.delegate = self;
+ // 娉ㄥ唽cell
+ [_mUICollectionView registerClass:[HDLCoverFlowCell class] forCellWithReuseIdentifier:@"CoverFlowID"];
+
+
+ }
+ return _mUICollectionView;
+}
+
+
+#pragma mark - 鏁版嵁婧愭柟娉�
+// 杩斿洖item鐨勪釜鏁�!
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+ return viewDataArray.count;
+}
+
+// 杩斿洖cell!
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+
+ // 1.鍒涘缓cell
+ HDLCoverFlowCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CoverFlowID" forIndexPath:indexPath];
+
+ [cell setCustomViewCell: viewDataArray[indexPath.row]];
+ // 3.杩斿洖cell
+ return cell;
+}
+
+
+#pragma mark --UICollectionViewDelegate
+//UICollectionView琚�変腑鏃惰皟鐢ㄧ殑鏂规硶
+-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
+{
+// // 1.鍒涘缓cell
+// ZHCoverFlowCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CoverFlowID" forIndexPath:indexPath];
+// cell.backgroundColor = [UIColor redColor];
+
+ NSLog(@"鐐瑰嚮浜嗭細%ld",(indexPath.row));
+
+ [_mSelectItemDelegate onSelectItem:indexPath.row];
+}
+
+
+#pragma mark - 鍔犺浇鏁版嵁
+
+-(void)addCoverFlowViewDatas:(NSArray<UIView *> *) viewsData{
+ viewDataArray = viewsData;
+ [_mUICollectionView reloadData];
+}
+
+/**
+ 璁剧疆閫変腑
+
+ @param selectIndex
+ */
+-(void)setCoverFlowSelectIndex:(NSInteger) selectIndex{
+
+ [self.mUICollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:selectIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
+// _mUICollectionView
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameArc:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ _mUICollectionView.frame = self.frame;
+ _mUICollectionView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+}
+
+@end
+
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.h
new file mode 100644
index 0000000..bba1c3b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.h
@@ -0,0 +1,21 @@
+//
+// HDLCoverFlowCell.h
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/26.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HDLCoverFlowCell : UICollectionViewCell
+
+
+
+- (void)setCustomViewCell:(UIView *)cellView;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.m
new file mode 100644
index 0000000..6f2d126
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowCell.m
@@ -0,0 +1,73 @@
+//
+// HDLCoverFlowCell.m
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/26.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+#import "HDLCoverFlowCell.h"
+
+
+@interface HDLCoverFlowCell ()
+
+/**
+ * 鐢ㄤ簬鏄剧ず閫氱敤View
+ */
+@property (strong, nonatomic) UIView *mCustomView;
+
+@end
+
+@implementation HDLCoverFlowCell
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ [self setupUI];
+ }
+ return self;
+}
+
+#pragma mark - 璁剧疆鏁版嵁 鍔犺浇鑷畾涔塚iewCell
+- (void)setCustomViewCell:(UIView *)cellView {
+
+// cellView.frame = self.bounds;
+//// cellView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+// [self.mCustomView removeFromSuperview];
+// self.mCustomView = cellView;
+// [self addSubview:self.mCustomView];
+
+
+ // cellView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self.mCustomView removeFromSuperview];
+
+ self.mCustomView = [[UIView alloc]initWithFrame:self.bounds];
+
+ cellView.center = CGPointMake(self.mCustomView.frame.size.width/2, self.mCustomView.frame.size.height/2);
+ [self.mCustomView addSubview:cellView];
+ [self addSubview:self.mCustomView];
+}
+
+#pragma mark - 鎼缓鐣岄潰
+- (void)setupUI {
+ [self.contentView addSubview:self.mCustomView];
+}
+
+- (UIView *)CustomView{
+ if (_mCustomView == nil) {
+ _mCustomView = [[UIView alloc]initWithFrame:self.bounds];
+ // 璁剧疆鍦嗚
+ _mCustomView.layer.cornerRadius = 10;
+ _mCustomView.layer.masksToBounds = YES;
+ // 璁剧疆杈规棰滆壊
+ _mCustomView.layer.borderColor = [UIColor whiteColor].CGColor;
+ _mCustomView.layer.borderWidth = 1;
+ }
+ return _mCustomView;
+}
+
+
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.h
new file mode 100644
index 0000000..7b34bab
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.h
@@ -0,0 +1,18 @@
+//
+// HDLCoverFlowLayout.h
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/26.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HDLCoverFlowLayout : UICollectionViewFlowLayout
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.m
new file mode 100644
index 0000000..11c2677
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCoverFlow/HDLCoverFlowLayout.m
@@ -0,0 +1,163 @@
+//
+// HDLCoverFlowLayout.m
+// CoverFlow
+//
+// Created by JLCHEN on 2019/8/26.
+// Copyright 漏 2019 JLCHEN. All rights reserved.
+//
+
+#import "HDLCoverFlowLayout.h"
+
+
+@implementation HDLCoverFlowLayout
+
+- (void)prepareLayout {
+
+ [super prepareLayout];
+
+ // 1.璋冩暣婊氬姩鏂瑰悜
+ self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
+
+ // 2.璁剧疆澶у皬
+ CGFloat itemH = self.collectionView.bounds.size.height * 0.8;
+ CGFloat itemW = self.collectionView.bounds.size.width * 0.65;
+
+ self.itemSize = CGSizeMake(itemW, itemH);
+
+ // 3.璁剧疆闂磋窛
+ self.minimumLineSpacing = 0;
+
+// self.minimumInteritemSpacing = 0;
+
+ // 4.璁剧疆鍐呰竟璺�
+ CGFloat inset = (self.collectionView.bounds.size.width - itemW) * 0.5;
+// CGFloat inset = 0;
+ self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
+
+
+
+}
+
+#pragma mark - 甯冨眬涓�瀹氬嵈涓庣殑cell
+- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
+
+ // 1.鍏堣幏鍙栫郴缁熷竷灞�濂界殑缁撴灉!
+ NSArray<UICollectionViewLayoutAttributes *> *oldAttrsArr = [super layoutAttributesForElementsInRect:rect];
+
+ // 2.閬嶅巻闆嗗悎,杩涜淇敼
+ // 2.1 涓存椂闆嗗悎
+ NSMutableArray *tempArrM = [NSMutableArray array];
+
+ // 2.2 閬嶅巻闆嗗悎,淇敼灞炴��
+ [oldAttrsArr enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+
+ // 2.2.1 淇敼涔嬪墠鍏坈opy!
+ UICollectionViewLayoutAttributes *newAttr = obj.copy;
+
+ // newAttr.transform3D = CATransform3DRotate(newAttr.transform3D, M_PI_4, 0, 1, 0);
+ // 2.2.2 淇敼灞炴��! -> 缂╂斁 & 鏃嬭浆!
+ // MARK: - 1.缂╂斁
+ // - 1.灞忓箷涓嚎鐨勪綅缃�
+ CGFloat screenCenterX = self.collectionView.bounds.size.width * 0.5 + self.collectionView.contentOffset.x;
+
+ // - 2.姣忎釜cell鐨勪腑蹇冪殑x!!
+ CGFloat itemCenterX = newAttr.center.x;
+
+ // - 3.璁$畻璺濈
+ CGFloat distance = screenCenterX - itemCenterX;
+
+ // - 4.灏嗚窛绂昏浆鎹㈡垚缂╂斁鐨勬瘮渚�! ABS() -> 鍙栫粷瀵瑰��!
+ CGFloat scale = 1 - ABS(distance/4) / self.collectionView.bounds.size.width;
+
+// NSLog(@"scale: %f",scale);
+
+ // - 5.鏃嬭浆
+ // - 5.1 鏃嬭浆鐨勮搴�!
+ CGFloat angle = (1 - scale) * M_PI_2 *2;
+
+ // 濡傛灉璺濈澶т簬0,宸﹁竟 -> * 1,姝g殑瑙掑害
+ // 濡傛灉璺濈灏忎簬0,鍙宠竟 -> * -1,璐熺殑瑙掑害!
+ angle *= ((distance > 0) ? 1 : -1);
+
+ // - 鍗曚綅鐭╅樀
+ CATransform3D transform = CATransform3DIdentity;
+
+ // - 5.3 澧炲姞閫忚鏁堟灉
+ transform.m34 = - 1.0 / 500;
+
+
+ // - 4.2 缂╂斁
+ transform = CATransform3DScale(transform, scale, scale, 1);
+
+ // - 5.2 鏃嬭浆
+ transform = CATransform3DRotate(transform, angle, 0, 1, 0);
+
+
+ // 4.3 璧嬪��!
+ newAttr.transform3D = transform;
+
+ // 2.2.x 淇濆瓨鍒颁复鏃堕泦鍚�
+ [tempArrM addObject:newAttr];
+ }];
+
+ // 3.杩斿洖
+ return tempArrM;
+
+}
+
+#pragma mark - 鍙鏄剧ず鐨勫尯鍩熷彂鐢熷彉鍖�,灏遍噸鏂拌绠楀竷灞�!
+// Invalidate 澶辨晥! 杩斿洖YES! 鍙鏄剧ず鐨勫尯鍩熷彂鐢熸敼鍙�,灏辫甯冨眬澶辨晥!
+// 閲嶆柊璁$畻甯冨眬!
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
+
+ return YES;
+}
+
+#pragma mark - 璁$畻鍋滅暀鐨勪綅缃�
+- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
+
+ // 1.鑾峰彇绯荤粺璁$畻濂界殑鍊�
+ CGPoint point = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity];
+
+ // 2.璁$畻灞忓箷鍙鍖哄煙 -> CGRect!
+ CGRect rect;
+ rect.size = self.collectionView.bounds.size;
+#warning - 棰勮鍋滅暀鐨勪綅缃椂,鍐呭鐨勫亸绉婚噺!
+ rect.origin = proposedContentOffset;
+
+ // 3.鑾峰彇鍙鍖哄煙鍐呯殑cell!
+#warning - 鍒╃敤涓婇潰鐨勬柟娉�,璁$畻鍙鍖哄煙鍐呯殑cell!
+ NSArray<UICollectionViewLayoutAttributes *> *visibleAttrs = [self layoutAttributesForElementsInRect:rect];
+
+ // 4.闇�瑕佹壘鍑哄叾涓渶杩戠殑cell!
+ // 4.2 閬嶅巻,鎵惧嚭璺濈灞忓箷涓嚎鏈�杩戠殑cell瀵瑰簲鐨刟ttr
+ // - 灞忓箷涓嚎鐨剎
+ CGFloat screenCenterX = proposedContentOffset.x + self.collectionView.bounds.size.width * 0.5;
+
+ // - 瀹氫箟涓�涓渶灏忕殑闂磋窛
+ __block CGFloat minMargin = CGFLOAT_MAX;
+ // - 瀹氫箟涓�涓储寮�,鐢ㄦ潵璁板綍鏈�杩戦偅涓猘ttr鐨勫湪鏁扮粍涓�!绱㈠紩!
+ __block NSInteger index = -1;
+
+ [visibleAttrs enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+
+ CGFloat distance = screenCenterX - obj.center.x;
+
+ if (ABS(distance) < minMargin) {
+ minMargin = ABS(distance);
+ index = idx;
+ }
+
+ }];
+
+ // 5.璁$畻闇�瑕佸亸绉荤殑璺濈!
+ CGFloat offsetX = screenCenterX - visibleAttrs[index].center.x;
+
+ // 2.杩斿洖鐐瑰潗鏍�
+ return CGPointMake(point.x - offsetX, point.y);
+}
+
+
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.h
new file mode 100644
index 0000000..55ee85e
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.h
@@ -0,0 +1,161 @@
+//
+// HDLCurtainSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/4.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLCurtainSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+///**
+// 鑳屾櫙棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+///**
+// 鎷栧姩鎸夐挳棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+/**
+ 杩涘害棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mCurtainProgressBarColor;
+
+
+///**
+// 杈规棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mCurtainBorderColor;
+
+/**
+ 鍦嗚澶у皬
+ */
+@property (nonatomic, assign) int mCornerRadius;
+
+/**
+ 椤堕儴鍥剧墖琛ュ伩鍊�
+ */
+@property (nonatomic, assign) int topCompensatePadding;
+
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLCurtainSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+
+///**
+// 璁剧疆娓愬彉鏁堟灉 棰滆壊鏁扮粍
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors;
+
+///**
+// 璁剧疆娓愬彉鏁堟灉
+//
+// @param startColor 寮�濮嬮鑹�
+// @param endColor 缁撴潫棰滆壊
+// */
+//-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+/**
+ 璁剧疆杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor;
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding;
+
+///**
+// 璁剧疆鑳屾櫙杈规瀹藉害
+// */
+//-(void)setBorderWidth:(int)borderWidth;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.m
new file mode 100644
index 0000000..6b4cee7
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLCurtainSeekBar.m
@@ -0,0 +1,485 @@
+//
+// HDLCurtainSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/4.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLCurtainSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_BG HEXCOLOR(0xE5E5ED)
+//#define APP_DEFAULT_BG_LINE [UIColor colorWithRed:73/255.0f green:87/255.0f blue:128/255.0f alpha:1.0f]
+#define APP_DEFAULT_BAR HEXCOLOR(0xCBCEE5)
+
+
+@interface HDLCurtainSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mCurtainProgressBarColors;
+
+///**
+// 鑳屾櫙绾垮
+// */
+//@property (nonatomic, assign) int mBackLineWidth;
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int CurtainPadding;
+
+
+
+@end
+
+
+@implementation HDLCurtainSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInCurtainProgress;
+
+ CGFloat _mCurtainHeight;
+ CGFloat _mCurtainWidth;
+
+ CGFloat _mCurtainStartX;
+ CGFloat _mCurtainEndX;
+
+ float _mPercent;
+
+ CGFloat _mCurtainPadding;
+ CGFloat _mButtonWidth;
+ CGFloat _mCurtainY;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 2;
+ _CurtainPadding = 30;
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ _topCompensatePadding = 5;
+ [self setProgressBarColor:APP_DEFAULT_BAR];
+ [self refreshFrame];
+ self.backgroundColor = [UIColor clearColor];
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onCurtainSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onCurtainSizeChange{
+ _mCurtainPadding = _CurtainPadding;
+ _mCurtainHeight = self.frame.size.height - _mCurtainPadding*2;
+ _mCurtainWidth = self.frame.size.width - _mCurtainPadding*2;
+ _mCurtainStartX = _mCurtainPadding;
+ _mCurtainEndX = _mCurtainWidth + _mCurtainStartX;
+ _mButtonWidth = _mCurtainWidth/4;
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+// //*********缁樺埗杈规鑳屾櫙*********
+// [self drawBorderPath:ctx];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+//
+///**
+// 缁樺埗杈规
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawBorderPath:(CGContextRef)ctx{
+// CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth};
+//
+// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+// path.lineWidth = _mBackLineWidth; //绾垮
+// path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+// path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+// [_mCurtainBorderColor set];
+//
+// CGContextSetLineWidth(ctx, _mBackLineWidth);
+// CGContextAddPath(ctx, path.CGPath);
+// CGContextDrawPath(ctx, kCGPathStroke);
+// // [path stroke]; //杈规绾块鑹�
+//}
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(_mCurtainStartX, _mCurtainPadding , _mCurtainWidth, _mCurtainHeight );
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:_mCornerRadius];
+// [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:_mCornerRadius];
+ [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+
+
+ _mCurtainY = _mPercent * _mCurtainHeight + _mCurtainPadding;
+
+ CGContextBeginPath( ctx );
+ //1銆佹坊鍔犵涓�鐐�
+ CGContextMoveToPoint( ctx, _mCurtainStartX, _mCurtainPadding);
+ CGContextAddLineToPoint( ctx, _mCurtainEndX, _mCurtainPadding);
+ CGContextAddLineToPoint( ctx, _mCurtainEndX, _mCurtainY );
+ CGContextAddLineToPoint( ctx, _mCurtainStartX, _mCurtainY );
+
+ CGContextClosePath(ctx);
+
+ CGContextSetFillColorWithColor( ctx, _mCurtainProgressBarColor.CGColor );
+
+ CGContextDrawPath( ctx, kCGPathFill );
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+
+/**
+缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+@param ctx 鐢诲竷
+*/
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+ //缁樺埗椤堕儴鍥剧墖
+ UIImage *imageTop = [UIImage imageNamed:@"ic_wd_curtain_bg_top"];
+
+ CGRect rectImageTop = CGRectMake(_CurtainPadding - _topCompensatePadding , 0 , _mCurtainWidth+_topCompensatePadding*2, _CurtainPadding+2);
+ [imageTop drawInRect:rectImageTop];
+
+
+ //缁樺埗鎸夐挳鐨勫浘鐗�
+ UIImage *image = [UIImage imageNamed:@"ic_wd_curtain_open"];
+ CGRect rectImage = CGRectMake(_mCenterPoint.x-_mButtonWidth/2, _mCurtainY-_mButtonWidth/2 , _mButtonWidth, _mButtonWidth);
+ [image drawInRect:rectImage];
+}
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+ _bIsInCurtainProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInCurtainProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y - _mCurtainPadding ) / _mCurtainHeight;
+ // NSLog(@"point.y:%f _mCurtainHeight:%f",point.y,_mCurtainHeight);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = _mPercent * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param mColors 棰滆壊鏁扮粍
+ */
+-(void)setProgressBarColors:(NSArray *)mColors{
+
+ // NSArray * colors = [NSArray arrayWithObjects锛氾紙id锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+
+}
+
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mCurtainProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor{
+ // // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ // _mCurtainProgressBarColors = @[
+ // (id)oneColor.CGColor,
+ // (id)oneColor.CGColor
+ // ];
+
+ _mCurtainProgressBarColor = oneColor;
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding{
+ _CurtainPadding = Padding;
+ [self onCurtainSizeChange];
+}
+//
+///**
+// 璁剧疆鑳屾櫙杈规瀹藉害
+// */
+//-(void)setBorderWidth:(int)borderWidth{
+// _mBackLineWidth = borderWidth;
+// [self onCurtainSizeChange];
+//}
+
+
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.h
new file mode 100644
index 0000000..59efb64
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.h
@@ -0,0 +1,132 @@
+//
+// HDLOACCurtainSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLOACCurtainSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+///**
+// 鑳屾櫙棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+///**
+// 鎷栧姩鎸夐挳棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLOACCurtainSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding;
+
+
+/**
+ 璁剧疆椤堕儴杈硅窛
+ */
+-(void)setCurtainPaddingTop:(int)Padding;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 鑾峰彇楂樺害 X鍊�
+ */
+-(CGFloat)getProgressX;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.m
new file mode 100644
index 0000000..bf8cf2c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLOACCurtainSeekBar.m
@@ -0,0 +1,502 @@
+//
+// HDLOACCurtainSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLOACCurtainSeekBar.h"
+#import "HDLUtlisXM.h"
+//
+//#define APP_DEFAULT_BG HEXCOLOR(0xE5E5ED)
+////#define APP_DEFAULT_BG_LINE [UIColor colorWithRed:73/255.0f green:87/255.0f blue:128/255.0f alpha:1.0f]
+//#define APP_DEFAULT_BAR HEXCOLOR(0xCBCEE5)
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLOACCurtainSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int CurtainPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+/**
+ 椤堕儴padding
+ */
+@property (nonatomic, assign) int mCurtainPaddingTop;
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+
+@end
+
+
+@implementation HDLOACCurtainSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInCurtainProgress;
+
+ CGFloat _mTopImageHeight;
+ CGFloat _mCurtainHeight;
+ CGFloat _mCurtainWidth;
+ CGFloat _mCurtainWidthHalf;
+
+ CGFloat _mCurtainStartX;
+ CGFloat _mCurtainEndX;
+
+ float _mPercent;
+
+ CGFloat _mCurtainPadding;
+ CGFloat _mButtonWidth;
+ CGFloat _mCurtainX;
+ CGFloat _mCornerRadius;
+ UIImage *_curtainImage;
+ UIImage *_bgImage;
+ UIImage *_bgTopImage;
+ BOOL bDownLeft;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+ _CurtainPadding = 15;
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ _mCurtainPaddingTop = 5;
+// _mTopImageHeight = 18;
+
+ [self refreshFrame];
+ _curtainImage = [UIImage imageNamed:@"ic_wd_curtain_h_progress"];
+ self.backgroundColor = [UIColor clearColor];
+ // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_curtain_h_bg"]];
+ // [self addSubview:_bgImageView];
+
+ _bgImage = [UIImage imageNamed:@"ic_wd_curtain_h_bg"];
+ _bgTopImage =[UIImage imageNamed:@"ic_wd_curtain_h_top"];
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onCurtainSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onCurtainSizeChange{
+ _mCurtainPadding = _CurtainPadding;
+
+ _mCurtainWidth = self.frame.size.width - _mCurtainPadding*2;
+ _mCurtainStartX = _mCurtainPadding;
+ _mCurtainEndX = _mCurtainWidth + _mCurtainStartX;
+ _mButtonWidth = _mCurtainWidth / 6;
+ _mCurtainWidthHalf = _mCurtainWidth/2;
+
+ _mCurtainHeight = self.frame.size.height - _mCurtainPaddingTop;
+
+ _mTopImageHeight = self.frame.size.width*18/396;
+
+
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鑳屾櫙*********
+ [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ //*********缁樺埗Top鍥剧墖*********
+ [self drawTopImage];
+
+ //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ [self drawOfflineView:ctx];
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+}
+
+/**
+ 缁樺埗鑳屾櫙鍥�
+ */
+-(void)drawBackIamge{
+ //缁樺埗鑳屾櫙鍥�
+ CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ [_bgImage drawInRect:rectBgImage];
+}
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(_mCurtainStartX, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:0];
+ // [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ _mCurtainX = _mPercent * _mCurtainWidthHalf + _mCurtainPadding;
+
+ //缁樺埗鎸夐挳鐨勫浘鐗�
+
+ if(_mPercent == 1){
+ CGRect rectImage = CGRectMake(_mCurtainPadding, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ [_curtainImage drawInRect:rectImage];
+ }else{
+
+ CGRect rectImage = CGRectMake(_mCurtainX - _mCurtainWidth , _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ [_curtainImage drawInRect:rectImage];
+
+
+ CGRect rectImageRight = CGRectMake(self.frame.size.width - _mCurtainX, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ [_curtainImage drawInRect:rectImageRight];
+ }
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+
+/**
+缁樺埗鎸夐挳鐨勫浘鐗�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+ //缁樺埗鎸夐挳鐨勫浘鐗�
+ UIImage *image = [UIImage imageNamed:@"ic_wd_curtain_h_open"];
+ CGRect rectImage = CGRectMake(_mCurtainX - _mButtonWidth/2, self.frame.size.height/2 - _mButtonWidth/2, _mButtonWidth, _mButtonWidth);
+ [image drawInRect:rectImage];
+
+
+}
+
+
+/**
+ 缁樺埗Top鐨勫浘鐗�
+ */
+-(void)drawTopImage{
+ CGRect rectImage = CGRectMake(0, 0, self.frame.size.width, _mTopImageHeight);
+ [_bgTopImage drawInRect:rectImage];
+
+}
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2 - _mButtonWidth);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+ CGPoint startPoint = [touch locationInView:self];
+ bDownLeft = (startPoint.x- self.frame.size.width/2) < 0;
+
+ _bIsInCurtainProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInCurtainProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ if(bDownLeft){
+ float progressX = point.x - _mCurtainPadding;
+ _mPercent = progressX / _mCurtainWidthHalf;
+
+ }else{
+ float progressX = point.x - self.frame.size.width/2;
+ _mPercent = 1 - progressX / _mCurtainWidthHalf;
+
+ }
+
+
+ // NSLog(@"point.y:%f _mCurtainHeight:%f",point.x, _mCurtainWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (1 -_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding{
+ _CurtainPadding = Padding;
+ [self onCurtainSizeChange];
+}
+
+
+/**
+ 璁剧疆椤堕儴杈硅窛
+ */
+-(void)setCurtainPaddingTop:(int)Padding{
+ _mCurtainPaddingTop = Padding;
+ [self onCurtainSizeChange];
+}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇鍧愭爣 X鍊�
+ */
+-(CGFloat)getProgressX{
+ return _mCurtainX;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.h
new file mode 100644
index 0000000..750abb4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.h
@@ -0,0 +1,134 @@
+//
+// HDLRollCurtainSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/7.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLRollCurtainSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+///**
+// 鑳屾櫙棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+///**
+// 鎷栧姩鎸夐挳棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLRollCurtainSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding;
+
+
+/**
+ 璁剧疆椤堕儴杈硅窛
+ */
+-(void)setCurtainPaddingTop:(int)Padding;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY;
+
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.m
new file mode 100644
index 0000000..6ba6b50
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/HDLRollCurtainSeekBar.m
@@ -0,0 +1,498 @@
+//
+// HDLRollCurtainSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/7.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLRollCurtainSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLRollCurtainSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int CurtainPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+/**
+ 椤堕儴padding
+ */
+@property (nonatomic, assign) int mCurtainPaddingTop;
+
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+@end
+
+
+@implementation HDLRollCurtainSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInCurtainProgress;
+
+ CGFloat _mCurtainHeight;
+ CGFloat _mCurtainWidth;
+ // CGFloat _mCurtainWidthHalf;
+
+ // CGFloat _mCurtainStartX;
+ // CGFloat _mCurtainEndX;
+
+ float _mPercent;
+
+ CGFloat _mCurtainPadding;
+ CGFloat _mButtonWidth;
+ CGFloat _mCurtainY;
+ CGFloat _mCornerRadius;
+ UIImage *_curtainImage;
+ UIImage *_buttonImage;
+ UIImage *_bgImage;
+
+ // BOOL bDownLeft;
+ CGFloat _mCurtainPaddingHeight;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ _mCurtainPaddingTop = 45;
+ _CurtainPadding = 5;
+ _mCurtainPaddingHeight = 5;
+
+ [self refreshFrame];
+
+ self.backgroundColor = [UIColor clearColor];
+ // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_curtain_roll_bg"]];
+ // [self addSubview:_bgImageView];
+
+ _curtainImage = [UIImage imageNamed:@"ic_wd_curtain_roll_progress"];
+ _buttonImage = [UIImage imageNamed:@"ic_wd_curtain_open"];
+
+ _bgImage = [UIImage imageNamed:@"ic_wd_curtain_roll_bg"];
+
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onCurtainSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onCurtainSizeChange{
+ _mCurtainPadding = _CurtainPadding;
+ _mCurtainWidth = self.frame.size.width - _mCurtainPadding*2;
+ _mButtonWidth = _mCurtainWidth / 5;
+ _mCurtainHeight = self.frame.size.height - _mCurtainPaddingTop;
+
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鑳屾櫙*********
+ [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ [self drawOfflineView:ctx];
+
+
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+//
+///**
+// 缁樺埗杈规
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawBorderPath:(CGContextRef)ctx{
+// CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth};
+//
+// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+// path.lineWidth = _mBackLineWidth; //绾垮
+// path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+// path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+// [_mCurtainBorderColor set];
+//
+// CGContextSetLineWidth(ctx, _mBackLineWidth);
+// CGContextAddPath(ctx, path.CGPath);
+// CGContextDrawPath(ctx, kCGPathStroke);
+// // [path stroke]; //杈规绾块鑹�
+//}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+
+}
+
+/**
+ 缁樺埗鑳屾櫙鍥�
+ */
+-(void)drawBackIamge{
+ //缁樺埗鑳屾櫙鍥�
+ CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ [_bgImage drawInRect:rectBgImage];
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(0, _mCurtainPaddingTop, self.frame.size.width, _mCurtainHeight);
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:0];
+ // [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ _mCurtainY = _mPercent * _mCurtainHeight + _mCurtainPaddingTop;
+
+
+
+ CGRect rectImage = CGRectMake(_mCurtainPadding, _mCurtainY - _mCurtainHeight - _mCurtainPaddingHeight , _mCurtainWidth, _mCurtainHeight+_mCurtainPaddingHeight);
+ [_curtainImage drawInRect:rectImage];
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring]];
+ }
+}
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+
+ CGRect rectImage = CGRectMake(_mCenterPoint.x-_mButtonWidth/2, _mCurtainY-_mButtonWidth/2 , _mButtonWidth, _mButtonWidth);
+
+ [_buttonImage drawInRect:rectImage];
+}
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ */
+- (void) drawString:(NSString *)mText {
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ if(_mPercent > 0.3){
+ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY-_mButtonWidth/2 - textSize.height-5);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+ }else{
+ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY+_mButtonWidth/2 + 5);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+ }
+
+
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+
+ _bIsInCurtainProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInCurtainProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y - _mCurtainPaddingTop ) / _mCurtainHeight;
+
+ // NSLog(@"point.y:%f _mCurtainHeight:%f",point.x, _mCurtainWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (1 -_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+// [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setCurtainPadding:(int)Padding{
+ _CurtainPadding = Padding;
+ [self onCurtainSizeChange];
+}
+
+
+/**
+ 璁剧疆椤堕儴杈硅窛
+ */
+-(void)setCurtainPaddingTop:(int)Padding{
+ _mCurtainPaddingTop = Padding;
+ [self onCurtainSizeChange];
+}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY{
+ return _mCurtainY;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.h
new file mode 100644
index 0000000..4d4593b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.h
@@ -0,0 +1,32 @@
+//
+// SeekBarDelegate.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+@protocol HDLSeekBarProgressChangedDelegate <NSObject>
+
+//鎵嬫寚鎸変笅锛屽紑濮嬬偣鍑�
+-(void)onStartTrackingTouch;
+
+//婊戝姩瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onProgressChanged:(int)mProgress;
+
+//鍋滄婊戝姩鎴栫粨鏉熺偣鍑伙紝瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onStopTrackingTouch:(int)mProgress;
+
+
+@end
+
+@interface SeekBarDelegate : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.m
new file mode 100644
index 0000000..3752f0f
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/SeekBarDelegate.m
@@ -0,0 +1,13 @@
+//
+// SeekBarDelegate.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/11/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "SeekBarDelegate.h"
+
+@implementation SeekBarDelegate
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_bg_top.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_bg_top.png
new file mode 100755
index 0000000..389b0c3
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_bg_top.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_bg.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_bg.png
new file mode 100755
index 0000000..fa90dab
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_bg.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_open.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_open.png
new file mode 100755
index 0000000..4093bea
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_open.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_progress.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_progress.png
new file mode 100755
index 0000000..2ebc0a1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_progress.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_top.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_top.png
new file mode 100755
index 0000000..5fd6883
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_h_top.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_open.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_open.png
new file mode 100755
index 0000000..24240d0
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_open.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_bg.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_bg.png
new file mode 100755
index 0000000..ba5c502
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_bg.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_progress.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_progress.png
new file mode 100755
index 0000000..217760a
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLCurtainSeekBar/ic_wd_curtain_roll_progress.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.h
new file mode 100644
index 0000000..bd5cf21
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.h
@@ -0,0 +1,132 @@
+//
+// HDLDiyImageSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/12/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLDiyImageSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+/**
+ 鑳屾櫙棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+/**
+ 鎷栧姩鎸夐挳棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressBarColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+#pragma mark HDLRollSeekBarSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding;
+
+
+/**
+ 璁剧疆杩涘害鏉¢珮
+ */
+-(void)setProgressBarHeight:(int)mHeight;
+
+/**
+ 璁剧疆鎸夐挳楂樺害
+ */
+-(void)setBitmapButtonHeight:(int)mHeight;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setBgBitmapButton:(UIImage*) mImage;
+
+/**
+ 鑾峰彇楂樺害 X鍊�
+ */
+-(CGFloat)getProgressX;
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.m
new file mode 100644
index 0000000..97a73d9
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageSeekBar.m
@@ -0,0 +1,520 @@
+//
+// HDLDiyImageSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/12/6.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLDiyImageSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLDiyImageSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int DiyBarPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+///**
+// 椤堕儴padding
+// */
+//@property (nonatomic, assign) int mDiyBarPaddingTop;
+
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+@end
+
+
+@implementation HDLDiyImageSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInDiyBarProgress;
+
+ CGFloat _mDiyBarHeight;
+ CGFloat _mDiyBarWidth;
+ // CGFloat _mDiyBarWidthHalf;
+
+ // CGFloat _mDiyBarStartX;
+ // CGFloat _mDiyBarEndX;
+
+ float _mPercent;
+
+ CGFloat _mDiyBarPadding;
+ CGFloat _mButtonWidth;
+ CGFloat _mDiyBarX;
+ CGFloat _mCornerRadius;
+ UIImage *_buttonImage;
+
+
+ int _mDiyBarPaddingTop;
+ int _mDiyBarPaddingBottom;
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ // mDiyBarPaddingTop = 45;
+ _DiyBarPadding = 15;
+
+ self.mArcBackBarColor = APP_DEFAULT_OFFLINE_COLOR;
+ self.mProgressBarColor = UIColor.yellowColor;
+ _mDiyBarHeight = 10;
+ _mButtonWidth = _mDiyBarHeight * 2;
+ [self refreshFrame];
+
+ self.backgroundColor = [UIColor clearColor];
+ // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_DiyBar_roll_bg"]];
+ // [self addSubview:_bgImageView];
+
+ // _DiyBarImage = [UIImage imageNamed:@"ic_wd_DiyBar_roll_progress"];
+ _buttonImage = [UIImage imageNamed:@"ic_wd_curtain_h_open"];
+
+ // _bgImage = [UIImage imageNamed:@"ic_wd_DiyBar_roll_bg"];
+
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onDiyBarSizeChange{
+ _mDiyBarPadding = _DiyBarPadding;
+ _mDiyBarWidth = self.frame.size.width - _mDiyBarPadding*2;
+ _mDiyBarPaddingTop = (self.frame.size.height - _mDiyBarHeight)/2;
+ _mDiyBarPaddingBottom = (self.frame.size.height + _mDiyBarHeight)/2;
+
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ // //*********缁樺埗鑳屾櫙*********
+ // [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ [self drawOfflineView:ctx];
+
+
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+//
+///**
+// 缁樺埗杈规
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawBorderPath:(CGContextRef)ctx{
+// CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth};
+//
+// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+// path.lineWidth = _mBackLineWidth; //绾垮
+// path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+// path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+// [_mDiyBarBorderColor set];
+//
+// CGContextSetLineWidth(ctx, _mBackLineWidth);
+// CGContextAddPath(ctx, path.CGPath);
+// CGContextDrawPath(ctx, kCGPathStroke);
+// // [path stroke]; //杈规绾块鑹�
+//}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+
+}
+
+///**
+// 缁樺埗鑳屾櫙鍥�
+// */
+//-(void)drawBackIamge{
+// //缁樺埗鑳屾櫙鍥�
+// CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+// [_bgImage drawInRect:rectBgImage];
+//}
+
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+
+ _mDiyBarX = _mPercent * _mDiyBarWidth + _mDiyBarPadding;
+ //*******缁樺埗杩涘害鏉¤儗鏅�*********
+ CGRect rectB = CGRectMake(_mDiyBarPadding, _mDiyBarPaddingTop, _mDiyBarWidth, _mDiyBarHeight);
+ CGContextSaveGState(ctx);
+ UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:rectB cornerRadius:rectB.size.height/2];
+ CGContextSetFillColorWithColor(ctx, self.mArcBackBarColor.CGColor);
+ [roundedRect fill];
+
+ UIBezierPath *roundedClipPath = [UIBezierPath bezierPathWithRect:rectB];
+ [roundedClipPath appendPath:roundedRect];
+ [roundedRect addClip];
+
+ //*******缁樺埗杩涘害鏉�*********
+ if(_mPercent <= 0) return;
+
+ CGRect drawRect = CGRectMake(_mDiyBarPadding, _mDiyBarPaddingTop, _mDiyBarX - _mDiyBarPadding, _mDiyBarHeight);
+ UIBezierPath *roundedRect2 = [UIBezierPath bezierPathWithRoundedRect:drawRect byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii: CGSizeMake(drawRect.size.height/2, drawRect.size.height/2)];
+ CGContextSetFillColorWithColor(ctx, self.mProgressBarColor.CGColor);
+ [roundedRect2 fill];
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+
+ CGPoint mP = CGPointMake(_mDiyBarX , _mDiyBarPaddingTop -15);
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:mP];
+ }
+}
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+
+ CGRect rectImage = CGRectMake(_mDiyBarX - _mButtonWidth/2, _mCenterPoint.y - _mButtonWidth/2 , _mButtonWidth, _mButtonWidth);
+
+ [_buttonImage drawInRect:rectImage];
+}
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+
+ _bIsInDiyBarProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInDiyBarProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.x - _mDiyBarPadding ) / _mDiyBarWidth;
+
+ // NSLog(@"point.y:%f _mDiyBarHeight:%f",point.x, _mDiyBarWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ _mDiyBarX = _mPercent * _mDiyBarWidth + _mDiyBarPadding;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+// [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding{
+ _DiyBarPadding = Padding;
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 璁剧疆杩涘害鏉¢珮
+ */
+-(void)setProgressBarHeight:(int)mHeight{
+ _mDiyBarHeight = mHeight;
+ [self onDiyBarSizeChange];
+
+}
+
+/**
+ 璁剧疆鎸夐挳楂樺害
+ */
+-(void)setBitmapButtonHeight:(int)mHeight{
+ _mButtonWidth = mHeight;
+
+}
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setBgBitmapButton:(UIImage*) mImage{
+ _buttonImage = mImage;
+}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇鍧愭爣 X鍊�
+ */
+-(CGFloat)getProgressX{
+ return _mDiyBarX;
+}
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.h
new file mode 100644
index 0000000..8780035
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.h
@@ -0,0 +1,130 @@
+//
+// HDLDiyImageVerticalSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/3/14.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface HDLDiyImageVerticalSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+/**
+ 鑳屾櫙棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+/**
+ 鎷栧姩鎸夐挳棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressBarColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+#pragma mark HDLRollSeekBarSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding;
+
+
+/**
+ 璁剧疆杩涘害鏉¢珮
+ */
+-(void)setProgressBarHeight:(int)mHeight;
+
+/**
+ 璁剧疆鎸夐挳楂樺害
+ */
+-(void)setBitmapButtonHeight:(int)mHeight;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setBgBitmapButton:(UIImage*) mImage;
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.m
new file mode 100644
index 0000000..c103db8
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLDiyImageSeekBar/HDLDiyImageVerticalSeekBar.m
@@ -0,0 +1,525 @@
+//
+// HDLDiyImageVerticalSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/3/14.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import "HDLDiyImageVerticalSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLDiyImageVerticalSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int DiyBarPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+///**
+// 椤堕儴padding
+// */
+//@property (nonatomic, assign) int mDiyBarPaddingTop;
+
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+@end
+
+
+@implementation HDLDiyImageVerticalSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInDiyBarProgress;
+
+ CGFloat _mDiyBarHeight;
+ CGFloat _mDiyBarWidth;
+ // CGFloat _mDiyBarWidthHalf;
+
+ // CGFloat _mDiyBarStartX;
+ // CGFloat _mDiyBarEndX;
+
+ float _mPercent;
+
+ CGFloat _mDiyBarPadding;
+ CGFloat _mButtonWidth;
+// CGFloat _mDiyBarX;
+ CGFloat _mDiyBarY;
+ CGFloat _mCornerRadius;
+ UIImage *_buttonImage;
+
+ int _mDiyBarPaddingLeft;
+ int _mDiyBarPaddingTop;
+ int _mDiyBarPaddingBottom;
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 1;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 12;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ // mDiyBarPaddingTop = 45;
+ _DiyBarPadding = 15;
+
+ self.mArcBackBarColor = APP_DEFAULT_OFFLINE_COLOR;
+ self.mProgressBarColor = UIColor.yellowColor;
+ _mDiyBarHeight = 10;
+ _mButtonWidth = _mDiyBarHeight * 2;
+ [self refreshFrame];
+
+ self.backgroundColor = [UIColor clearColor];
+ // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_DiyBar_roll_bg"]];
+ // [self addSubview:_bgImageView];
+
+ // _DiyBarImage = [UIImage imageNamed:@"ic_wd_DiyBar_roll_progress"];
+ _buttonImage = [UIImage imageNamed:@"ic_wd_curtain_h_open"];
+
+ // _bgImage = [UIImage imageNamed:@"ic_wd_DiyBar_roll_bg"];
+
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onDiyBarSizeChange{
+
+ _mDiyBarPadding = _DiyBarPadding;
+ _mDiyBarWidth = self.frame.size.height - _mDiyBarPadding*2;
+ _mDiyBarPaddingTop = _mDiyBarPadding;
+ _mDiyBarPaddingBottom = self.frame.size.height - _mDiyBarPadding;
+ _mDiyBarPaddingLeft = (self.frame.size.width - _mDiyBarHeight)/2;
+
+
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ // //*********缁樺埗鑳屾櫙*********
+ // [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ [self drawOfflineView:ctx];
+
+
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+//
+///**
+// 缁樺埗杈规
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawBorderPath:(CGContextRef)ctx{
+// CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth};
+//
+// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+// path.lineWidth = _mBackLineWidth; //绾垮
+// path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+// path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+// [_mDiyBarBorderColor set];
+//
+// CGContextSetLineWidth(ctx, _mBackLineWidth);
+// CGContextAddPath(ctx, path.CGPath);
+// CGContextDrawPath(ctx, kCGPathStroke);
+// // [path stroke]; //杈规绾块鑹�
+//}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+
+}
+
+///**
+// 缁樺埗鑳屾櫙鍥�
+// */
+//-(void)drawBackIamge{
+// //缁樺埗鑳屾櫙鍥�
+// CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+// [_bgImage drawInRect:rectBgImage];
+//}
+
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+
+ _mDiyBarY = _mPercent * _mDiyBarWidth + _mDiyBarPadding;
+ //*******缁樺埗杩涘害鏉¤儗鏅�*********
+ CGRect rectB = CGRectMake(_mDiyBarPaddingLeft, _mDiyBarPaddingTop, _mDiyBarHeight, _mDiyBarWidth);
+ CGContextSaveGState(ctx);
+ UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:rectB cornerRadius:rectB.size.height/2];
+ CGContextSetFillColorWithColor(ctx, self.mArcBackBarColor.CGColor);
+ [roundedRect fill];
+
+ UIBezierPath *roundedClipPath = [UIBezierPath bezierPathWithRect:rectB];
+ [roundedClipPath appendPath:roundedRect];
+ [roundedRect addClip];
+
+ //*******缁樺埗杩涘害鏉�*********
+ if(_mPercent >= 1) return;
+
+ CGRect drawRect = CGRectMake(_mDiyBarPaddingLeft, _mDiyBarY, _mDiyBarHeight, self.frame.size.height -_mDiyBarY-_mDiyBarPadding );
+
+// CGRect drawRect = CGRectMake(_mDiyBarPaddingLeft, _mDiyBarPaddingTop, _mDiyBarHeight, _mDiyBarY - _mDiyBarPadding);
+ UIBezierPath *roundedRect2 = [UIBezierPath bezierPathWithRoundedRect:drawRect byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii: CGSizeMake(drawRect.size.width/2, drawRect.size.width/2)];
+ CGContextSetFillColorWithColor(ctx, self.mProgressBarColor.CGColor);
+ [roundedRect2 fill];
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+
+ CGPoint mP = CGPointMake(_mCenterPoint.x + _mButtonWidth/2 + 5 ,_mDiyBarY);
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:mP];
+ }
+}
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+
+ CGRect rectImage = CGRectMake(_mCenterPoint.x - _mButtonWidth/2, _mDiyBarY - _mButtonWidth/2, _mButtonWidth, _mButtonWidth);
+
+ [_buttonImage drawInRect:rectImage];
+}
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+
+ _bIsInDiyBarProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInDiyBarProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y - _mDiyBarPadding ) / _mDiyBarWidth;
+
+ // NSLog(@"point.y:%f _mDiyBarHeight:%f",point.x, _mDiyBarWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (1 - _mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ _mDiyBarY = _mPercent * _mDiyBarWidth + _mDiyBarPadding;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setSeekBarPadding:(int)Padding{
+ _DiyBarPadding = Padding;
+ [self onDiyBarSizeChange];
+}
+
+/**
+ 璁剧疆杩涘害鏉¢珮
+ */
+-(void)setProgressBarHeight:(int)mHeight{
+ _mDiyBarHeight = mHeight;
+ [self onDiyBarSizeChange];
+
+}
+
+/**
+ 璁剧疆鎸夐挳楂樺害
+ */
+-(void)setBitmapButtonHeight:(int)mHeight{
+ _mButtonWidth = mHeight;
+
+}
+
+/**
+ 璁剧疆鎷栧姩鎸夐挳鍥剧墖
+ */
+-(void)setBgBitmapButton:(UIImage*) mImage{
+ _buttonImage = mImage;
+}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY{
+ return _mDiyBarY;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.h
new file mode 100644
index 0000000..dd3f40c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.h
@@ -0,0 +1,135 @@
+//
+// HDLOnOACCurtainSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+/**
+ 寮�鍚堝笜
+ */
+@interface HDLOnOACCurtainSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+///**
+// 鑳屾櫙棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+///**
+// 鎷栧姩鎸夐挳棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+
+
+///**
+// 璁剧疆杈硅窛
+// */
+//-(void)setCurtainPadding:(int)Padding;
+//
+//
+///**
+// 璁剧疆椤堕儴杈硅窛
+// */
+//-(void)setCurtainPaddingTop:(int)Padding;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 鑾峰彇楂樺害 X鍊�
+ */
+-(CGFloat)getProgressX;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.m
new file mode 100644
index 0000000..e757675
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnOACCurtainSeekBar.m
@@ -0,0 +1,501 @@
+//
+// HDLOnOACCurtainSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import "HDLOnOACCurtainSeekBar.h"
+#import "HDLUtlisXM.h"
+//
+//#define APP_DEFAULT_BG HEXCOLOR(0xE5E5ED)
+////#define APP_DEFAULT_BG_LINE [UIColor colorWithRed:73/255.0f green:87/255.0f blue:128/255.0f alpha:1.0f]
+//#define APP_DEFAULT_BAR HEXCOLOR(0xCBCEE5)
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLOnOACCurtainSeekBar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int mCurtainPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+/**
+ 椤堕儴padding
+ */
+@property (nonatomic, assign) int mCurtainPaddingTop;
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+
+@end
+
+
+@implementation HDLOnOACCurtainSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInCurtainProgress;
+
+ CGFloat _mTopImageHeight;
+ CGFloat _mCurtainHeight;
+ CGFloat _mCurtainWidth;
+ CGFloat _mCurtainWidthHalf;
+
+ CGFloat _mCurtainStartX;
+ CGFloat _mCurtainEndX;
+
+ float _mPercent;
+ // CGFloat _mCurtainPadding;
+ CGFloat _mButtonWidth;
+ CGFloat _mCurtainX;
+ CGFloat _mCornerRadius;
+ UIImage *_curtainImage;
+ UIImage *_curtainImage_close;
+ UIImage *_bgImage;
+ // UIImage *_bgTopImage;
+ BOOL bDownLeft;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ _mCurtainPaddingTop = 6;
+ _mCurtainPaddingTop = 14;
+ [self refreshFrame];
+ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_h_progress"];
+ _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_h_progress_close"];
+ self.backgroundColor = [UIColor clearColor];
+ _bgImage = [UIImage imageNamed:@"ic_wd_on_curtain_h_bg"];
+ // _bgTopImage =[UIImage imageNamed:@"ic_wd_on_curtain_h_top"];
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onCurtainSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onCurtainSizeChange{
+ _mCurtainPadding = self.frame.size.width * 6 / 248 - 1;
+ _mCurtainPaddingTop = self.frame.size.height * 14 / 146;
+ _mCurtainWidth = self.frame.size.width - _mCurtainPadding*2;
+ _mCurtainStartX = _mCurtainPadding;
+ _mCurtainEndX = _mCurtainWidth + _mCurtainStartX;
+ _mButtonWidth = self.frame.size.width * 56/ 250;
+ _mCurtainWidthHalf = _mCurtainWidth/2;
+ _mCurtainHeight = self.frame.size.height - _mCurtainPaddingTop;
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鑳屾櫙*********
+ [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ // //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ // [self drawOfflineView:ctx];
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+}
+
+/**
+ 缁樺埗鑳屾櫙鍥�
+ */
+-(void)drawBackIamge{
+ //缁樺埗鑳屾櫙鍥�
+ CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ [_bgImage drawInRect:rectBgImage];
+}
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(_mCurtainStartX, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:0];
+ // [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ _mCurtainX = _mPercent * _mCurtainWidthHalf + _mCurtainPadding;
+
+ //缁樺埗鎸夐挳鐨勫浘鐗�
+ if(_mPercent == 1){
+ CGRect rectImage = CGRectMake(_mCurtainPadding, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ if(_isOffline){
+ [_curtainImage_close drawInRect:rectImage];
+ }else{
+ [_curtainImage drawInRect:rectImage];
+ }
+
+ }else{
+
+ CGRect rectImage = CGRectMake(_mCurtainX - _mCurtainWidth , _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ if(_isOffline){
+ [_curtainImage_close drawInRect:rectImage];
+ }else{
+ [_curtainImage drawInRect:rectImage];
+ }
+
+ CGRect rectImageRight = CGRectMake(self.frame.size.width - _mCurtainX, _mCurtainPaddingTop, _mCurtainWidth, _mCurtainHeight);
+ if(_isOffline){
+ [_curtainImage_close drawInRect:rectImageRight];
+ }else{
+ [_curtainImage drawInRect:rectImageRight];
+ }
+ }
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+
+/**
+ 缁樺埗鎸夐挳鐨勫浘鐗�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+ //缁樺埗鎸夐挳鐨勫浘鐗�
+ UIImage *image = [UIImage imageNamed:@"ic_wd_on_curtain_h_open"];
+ CGRect rectImage = CGRectMake(_mCurtainX - _mButtonWidth/2, self.frame.size.height/2 - _mButtonWidth/2, _mButtonWidth, _mButtonWidth);
+ [image drawInRect:rectImage];
+
+
+}
+
+
+///**
+// 缁樺埗Top鐨勫浘鐗�
+// */
+//-(void)drawTopImage{
+// CGRect rectImage = CGRectMake(0, 0, self.frame.size.width, _mTopImageHeight);
+// [_bgTopImage drawInRect:rectImage];
+//
+//}
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2 - _mButtonWidth/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+ CGPoint startPoint = [touch locationInView:self];
+ bDownLeft = (startPoint.x- self.frame.size.width/2) < 0;
+
+ _bIsInCurtainProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInCurtainProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ if(bDownLeft){
+ float progressX = point.x - _mCurtainPadding;
+ _mPercent = progressX / _mCurtainWidthHalf;
+
+ }else{
+ float progressX = point.x - self.frame.size.width/2;
+ _mPercent = 1 - progressX / _mCurtainWidthHalf;
+
+ }
+
+
+ // NSLog(@"point.y:%f _mCurtainHeight:%f",point.x, _mCurtainWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (1 -_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+///**
+// 璁剧疆杈硅窛
+// */
+//-(void)setCurtainPadding:(int)Padding{
+// _mCurtainPadding = Padding;
+// [self onCurtainSizeChange];
+//}
+//
+//
+///**
+// 璁剧疆椤堕儴杈硅窛
+// */
+//-(void)setCurtainPaddingTop:(int)Padding{
+// _mCurtainPaddingTop = Padding;
+// [self onCurtainSizeChange];
+//}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇鍧愭爣 X鍊�
+ */
+-(CGFloat)getProgressX{
+ return _mCurtainX;
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.h
new file mode 100644
index 0000000..b63693e
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.h
@@ -0,0 +1,127 @@
+//
+// HDLOnRollCurtainSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+/**
+ 鍗峰笜
+*/
+@interface HDLOnRollCurtainSeekBar : UIControl
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+
+
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLRollCurtainSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect;
+
+
+
+
+///**
+// 璁剧疆杈硅窛
+// */
+//-(void)setCurtainPadding:(int)Padding;
+//
+//
+///**
+// 璁剧疆椤堕儴杈硅窛
+// */
+//-(void)setCurtainPaddingTop:(int)Padding;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY;
+
+/**
+ 璁剧疆鐧惧彾绐楃被鍨�
+*/
+-(void)setBlindsType:(BOOL)isBlindsType;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.m
new file mode 100644
index 0000000..8394717
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/HDLOnRollCurtainSeekBar.m
@@ -0,0 +1,517 @@
+//
+// HDLOnRollCurtainSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/6/15.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import "HDLOnRollCurtainSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8)
+
+@interface HDLOnRollCurtainSeekBar ()
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int mCurtainPadding;
+
+/**
+
+ */
+//@property (nonatomic, strong) UIImageView *bgImageView;
+
+
+
+/**
+ 椤堕儴padding
+ */
+@property (nonatomic, assign) int mCurtainPaddingTop;
+
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+/**
+ 鏄惁鐧惧彾绐楃被鍨�
+ */
+@property (nonatomic, assign) BOOL isBlindsType;
+
+@end
+
+
+@implementation HDLOnRollCurtainSeekBar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+ bool _bIsInCurtainProgress;
+ CGFloat _mCurtainHeight;
+ CGFloat _mCurtainWidth;
+ float _mPercent;
+ CGFloat _mButtonWidth;
+ CGFloat _mCurtainY;
+ CGFloat _mCornerRadius;
+ UIImage *_curtainImage;
+ UIImage *_curtainImage_close;
+ UIImage *_buttonImage;
+ UIImage *_bgImage;
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mCornerRadius = 0;
+
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ // _mCurtainPaddingTop = 45;
+ _mCurtainPadding = self.frame.size.width*12/130;
+ _mCurtainPaddingTop = self.frame.size.height*14/172;
+
+ [self refreshFrame];
+
+ self.backgroundColor = [UIColor clearColor];
+ // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_curtain_roll_bg"]];
+ // [self addSubview:_bgImageView];
+
+ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress"];
+ _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress_close"];
+ _buttonImage = [UIImage imageNamed:@"ic_wd_on_curtain_open"];
+ _bgImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_bg"];
+
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ [self onCurtainSizeChange];
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onCurtainSizeChange{
+ // _mCurtainPadding = _CurtainPadding;
+
+ if(!_isBlindsType){
+ _mCurtainPadding = self.frame.size.width * 12 / 149 - 1;
+ }else{ //鐧惧彾绐楁晥鏋�
+ _mCurtainPadding = self.frame.size.width * 2 / 149 - 1;
+ }
+ _mCurtainPaddingTop = self.frame.size.height * 14 / 172;
+ _mCurtainWidth = self.frame.size.width - _mCurtainPadding * 2;
+ _mButtonWidth = self.frame.size.width * 56 / 149;
+ _mCurtainHeight = self.frame.size.height - _mCurtainPaddingTop;
+
+}
+
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗鑳屾櫙*********
+ [self drawBackIamge];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //*********缁樺埗鎸夐挳鍥剧墖*********
+ [self drawImageButton:ctx];
+ // //*********濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�*********
+ // [self drawOfflineView:ctx];
+
+
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+//
+///**
+// 缁樺埗杈规
+//
+// @param ctx 鐢诲竷
+// */
+//-(void)drawBorderPath:(CGContextRef)ctx{
+// CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth};
+//
+// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+// path.lineWidth = _mBackLineWidth; //绾垮
+// path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+// path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+// [_mCurtainBorderColor set];
+//
+// CGContextSetLineWidth(ctx, _mBackLineWidth);
+// CGContextAddPath(ctx, path.CGPath);
+// CGContextDrawPath(ctx, kCGPathStroke);
+// // [path stroke]; //杈规绾块鑹�
+//}
+
+/**
+ 濡傛灉绂荤嚎缁樺埗绂荤嚎鑳屾櫙閬尅灞�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawOfflineView:(CGContextRef)ctx{
+ if(_isOffline){
+ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5];
+ [APP_DEFAULT_OFFLINE_COLOR set];
+ CGContextAddPath(ctx, path3.CGPath);
+ CGContextDrawPath(ctx, kCGPathFill);
+ }
+
+}
+
+/**
+ 缁樺埗鑳屾櫙鍥�
+ */
+-(void)drawBackIamge{
+ //缁樺埗鑳屾櫙鍥�
+ CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
+ [_bgImage drawInRect:rectBgImage];
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(0, _mCurtainPaddingTop, self.frame.size.width, _mCurtainHeight);
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:0];
+ // [APP_DEFAULT_BG set];
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+
+ _mCurtainY = _mPercent * _mCurtainHeight + _mCurtainPaddingTop;
+
+ CGRect rectImage = CGRectMake(_mCurtainPadding, _mCurtainY - _mCurtainHeight, _mCurtainWidth, _mCurtainHeight);
+ // [_curtainImage drawInRect:rectImage];
+
+ if(_isOffline){
+ [_curtainImage_close drawInRect:rectImage];
+ }else{
+ [_curtainImage drawInRect:rectImage];
+ }
+
+}
+
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring]];
+ }
+}
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawImageButton:(CGContextRef)ctx {
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+
+
+ CGRect rectImage = CGRectMake(_mCenterPoint.x-_mButtonWidth/2, _mCurtainY-_mButtonWidth/2 , _mButtonWidth, _mButtonWidth);
+
+ [_buttonImage drawInRect:rectImage];
+}
+
+
+
+
+
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ */
+- (void) drawString:(NSString *)mText {
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ if(_mPercent > 0.3){
+ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY-_mButtonWidth/4 - textSize.height-5);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+ }else{
+ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY+_mButtonWidth/4 + 5);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+ }
+
+
+
+}
+
+
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+
+ _bIsInCurtainProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInCurtainProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y - _mCurtainPaddingTop ) / _mCurtainHeight;
+
+ // NSLog(@"point.y:%f _mCurtainHeight:%f",point.x, _mCurtainWidthHalf);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+
+ _mProgress = (1 -_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ // [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+///**
+// 璁剧疆杈硅窛
+// */
+//-(void)setCurtainPadding:(int)Padding{
+// _mCurtainPadding = Padding;
+// [self onCurtainSizeChange];
+//}
+//
+//
+///**
+// 璁剧疆椤堕儴杈硅窛
+// */
+//-(void)setCurtainPaddingTop:(int)Padding{
+// _mCurtainPaddingTop = Padding;
+// [self onCurtainSizeChange];
+//}
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY{
+ return _mCurtainY;
+}
+
+/**
+ 璁剧疆鐧惧彾绐楃被鍨�
+ */
+-(void)setBlindsType:(BOOL)isBlindsType{
+ _isBlindsType = isBlindsType;
+ if(!_isBlindsType){
+ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress"];
+ _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress_close"];
+ }else{
+ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_blinds_progress"];
+ _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_blinds_progress_close"];
+ }
+
+ [self onCurtainSizeChange];
+ [self setNeedsDisplay];
+}
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress.png
new file mode 100644
index 0000000..bd50e09
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress2.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress2.png
new file mode 100644
index 0000000..89c2247
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress2.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close.png
new file mode 100644
index 0000000..07ee534
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close2.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close2.png
new file mode 100644
index 0000000..1af41ea
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_blinds_progress_close2.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_bg.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_bg.png
new file mode 100644
index 0000000..9d1a94c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_bg.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_open.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_open.png
new file mode 100644
index 0000000..4a773d1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_open.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress.png
new file mode 100755
index 0000000..d74a5d5
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress_close.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress_close.png
new file mode 100755
index 0000000..9d997e2
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_h_progress_close.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_open.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_open.png
new file mode 100644
index 0000000..59971f1
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_open.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_bg.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_bg.png
new file mode 100755
index 0000000..bc2e71b
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_bg.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress.png
new file mode 100755
index 0000000..7a4f5d4
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress_close.png b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress_close.png
new file mode 100755
index 0000000..7d83fe7
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLONCurtainSeekBar/ic_wd_on_curtain_roll_progress_close.png
Binary files differ
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.h
new file mode 100644
index 0000000..8eca75c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.h
@@ -0,0 +1,123 @@
+//
+// HDLTouchID.h
+// TDTouchID
+//
+// Created by HDL on 2019/8/22.
+// Copyright 漏 2019 TuDou. All rights reserved.
+//
+
+
+#import <LocalAuthentication/LocalAuthentication.h>
+
+/**
+ * TouchID 鐘舵��
+ */
+typedef NS_ENUM(NSUInteger, HDLTouchIDState) {
+ /**
+ * 褰撳墠璁惧涓嶆敮鎸乀ouchID
+ */
+ HDLTouchIDStateNotSupport = 0,
+ /**
+ * TouchID 楠岃瘉鎴愬姛
+ */
+ HDLTouchIDStateSuccess = 1,
+ /**
+ * TouchID 楠岃瘉澶辫触
+ */
+ HDLTouchIDStateFail = 2,
+ /**
+ * TouchID 琚敤鎴锋墜鍔ㄥ彇娑�
+ */
+ HDLTouchIDStateUserCancel = 3,
+ /**
+ * 鐢ㄦ埛涓嶄娇鐢═ouchID,閫夋嫨鎵嬪姩杈撳叆瀵嗙爜
+ */
+ HDLTouchIDStateInputPassword = 4,
+ /**
+ * TouchID 琚郴缁熷彇娑� (濡傞亣鍒版潵鐢�,閿佸睆,鎸変簡Home閿瓑)
+ */
+ HDLTouchIDStateSystemCancel = 5,
+ /**
+ * TouchID 鏃犳硶鍚姩,鍥犱负鐢ㄦ埛娌℃湁璁剧疆瀵嗙爜
+ */
+ HDLTouchIDStatePasswordNotSet = 6,
+ /**
+ * TouchID 鏃犳硶鍚姩,鍥犱负鐢ㄦ埛娌℃湁璁剧疆TouchID
+ */
+ HDLTouchIDStateTouchIDNotSet = 7,
+ /**
+ * TouchID 鏃犳晥
+ */
+ HDLTouchIDStateTouchIDNotAvailable = 8,
+ /**
+ * TouchID 琚攣瀹�(杩炵画澶氭楠岃瘉TouchID澶辫触,绯荤粺闇�瑕佺敤鎴锋墜鍔ㄨ緭鍏ュ瘑鐮�)
+ */
+ HDLTouchIDStateTouchIDLockout = 9,
+ /**
+ * 褰撳墠杞欢琚寕璧峰苟鍙栨秷浜嗘巿鏉� (濡侫pp杩涘叆浜嗗悗鍙扮瓑)
+ */
+ HDLTouchIDStateAppCancel = 10,
+ /**
+ * 褰撳墠杞欢琚寕璧峰苟鍙栨秷浜嗘巿鏉� (LAContext瀵硅薄鏃犳晥)
+ */
+ HDLTouchIDStateInvalidContext = 11,
+ /**
+ * 绯荤粺鐗堟湰涓嶆敮鎸乀ouchID (蹇呴』楂樹簬iOS 8.0鎵嶈兘浣跨敤)
+ */
+ HDLTouchIDStateVersionNotSupport = 12
+};
+
+
+/**
+ * 璁惧鏀寔鐨勭敓鐗╅獙璇佹柟寮�
+ */
+typedef enum : NSUInteger {
+ /**
+ * 鏀寔TouchID楠岃瘉
+ */
+ HDLTouchIDSupperTypeTouchID = 1,
+ /**
+ * 鏀寔FaceID楠岃瘉
+ */
+ HDLTouchIDSupperTypeFaceID,
+ /**
+ * 涓嶆敮鎸佹敮鎸侀獙璇�
+ */
+ HDLTouchIDSupperTypeNone,
+}HDLTouchIDSupperType;
+
+
+typedef NS_ENUM(NSUInteger, HDLFaceIDState) {
+
+ HDLFaceIDStateSuccess = 0,
+
+ HDLFaceIDStateFail= 1
+};
+
+@interface HDLTouchID : LAContext
+
+typedef void (^StateBlock)(HDLTouchIDState state, NSError *error);
+
+typedef void (^faceIDStateBlock)(HDLFaceIDState state, NSError *error);
+
++ (HDLTouchID *)sharedInstance;
+
+/**
+ * 鍚姩TouchID杩涜楠岃瘉
+ * @param descTitle 杈撳叆瀵嗙爜鎸夐挳鐨勬爣棰�
+ * @param mlocalizedReason Touch鏄剧ず鐨勬弿杩�
+ * @param block 鍥炶皟鐘舵�佺殑block
+ */
+- (void)HDL_showTouchIDWithDescribe:(NSString *)descTitle mlocalizedReason:(NSString *)mlocalizedReason blockState:(StateBlock)block;
+
+/**
+ * 鍚姩FaceID
+ * @param mlocalizedReason FaceID鏄剧ず鐨勬弿杩�
+ * @param block 楠岃瘉鐘舵��
+ */
+- (void)HDL_showFaceIDWithDescribe:(NSString *)mlocalizedReason blockState:(faceIDStateBlock)block;
+
+
+// 鍒ゆ柇璁惧鏀寔鍝璁よ瘉鏂瑰紡 TouchID & FaceID
+- (HDLTouchIDSupperType)HDL_canSupperBiometrics;
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.m
new file mode 100644
index 0000000..7a8d18c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLTouchID/HDLTouchID.m
@@ -0,0 +1,190 @@
+//
+// HDLTouchID.m
+// TDTouchID
+//
+// Created by HDL on 2019/8/22.
+// Copyright 漏 2019 TuDou. All rights reserved.
+//
+
+#import "HDLTouchID.h"
+
+
+
+@implementation HDLTouchID
+
++ (instancetype)sharedInstance {
+ static HDLTouchID *instance = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ instance = [[HDLTouchID alloc] init];
+ });
+ return instance;
+}
+
+- (void)HDL_showTouchIDWithDescribe:(NSString *)descTitle mlocalizedReason:(NSString *)mlocalizedReason blockState:(StateBlock)block {
+
+ if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"绯荤粺鐗堟湰涓嶆敮鎸乀ouchID锛堝繀椤婚珮浜巌OS 8.0鎵嶈兘浣跨敤锛�");
+ block(HDLTouchIDStateVersionNotSupport, nil);
+ });
+
+ return;
+ }
+
+
+ LAContext *context = [[LAContext alloc] init];
+
+ context.localizedFallbackTitle = descTitle == nil ? @"杈撳叆瀵嗙爜楠岃瘉":descTitle;
+ NSError *error = nil;
+
+ if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
+ [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:mlocalizedReason == nil ? @"閫氳繃Home閿獙璇佸凡鏈夋寚绾�":mlocalizedReason reply:^(BOOL success, NSError * _Nullable error) {
+ if (success) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 楠岃瘉鎴愬姛");
+ block(HDLTouchIDStateSuccess, error);
+ });
+ } else if (error) {
+
+ switch (error.code) {
+ case LAErrorAuthenticationFailed: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 楠岃瘉澶辫触");
+ block(HDLTouchIDStateFail, error);
+ });
+ break;
+ }
+ case LAErrorUserCancel: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 琚敤鎴锋墜鍔ㄥ彇娑�");
+ block(HDLTouchIDStateUserCancel, error);
+ });
+ }
+ break;
+ case LAErrorUserFallback: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"鐢ㄦ埛涓嶄娇鐢═ouchID锛岄�夋嫨鎵嬪姩杈撳叆瀵嗙爜");
+ block(HDLTouchIDStateInputPassword, error);
+ });
+ }
+ break;
+ case LAErrorSystemCancel: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 琚郴缁熷彇娑堬紙濡傞亣鍒版潵鐢�,閿佸睆,鎸変簡Home閿瓑锛�");
+ block(HDLTouchIDStateSystemCancel, error);
+ });
+ }
+ break;
+ case LAErrorPasscodeNotSet: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 鏃犳硶鍚姩锛屽洜涓虹敤鎴锋病鏈夎缃瘑鐮�");
+ block(HDLTouchIDStatePasswordNotSet, error);
+ });
+ }
+ break;
+ case LAErrorTouchIDNotEnrolled: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 鏃犳硶鍚姩锛屽洜涓虹敤鎴锋病鏈夎缃甌ouchID");
+ block(HDLTouchIDStateTouchIDNotSet, error);
+ });
+ }
+ break;
+ case LAErrorTouchIDNotAvailable: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 鏃犳晥");
+ block(HDLTouchIDStateTouchIDNotAvailable, error);
+ });
+ }
+ break;
+ case LAErrorTouchIDLockout: {
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"TouchID 鏃犳晥");
+ block(HDLTouchIDStateTouchIDLockout, error);
+ });
+
+ }
+ break;
+ case LAErrorAppCancel: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"褰撳墠杞欢琚寕璧峰苟鍙栨秷浜嗘巿鏉冿紙濡侫pp杩涘叆浜嗗悗鍙扮瓑锛�");
+ block(HDLTouchIDStateAppCancel, error);
+ });
+ }
+ break;
+ case LAErrorInvalidContext: {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"褰撳墠杞欢琚寕璧峰苟鍙栨秷浜嗘巿鏉冿紙LAContext瀵硅薄鏃犳晥锛�");
+ block(HDLTouchIDStateInvalidContext, error);
+ });
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }];
+ } else {
+// [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:@"鐢ㄦ潵楠岃瘉鎸囩汗锛�" reply:^(BOOL success, NSError * _Nullable error) {
+// if (success) {
+// dispatch_async(dispatch_get_main_queue(), ^{
+// block(HDLTouchIDStateSuccess,error);
+// });
+// } else {
+// dispatch_async(dispatch_get_main_queue(), ^{
+// block(HDLTouchIDStateFail,error);
+// });
+// }
+// }];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"褰撳墠璁惧涓嶆敮鎸乀ouchID");
+ block(HDLTouchIDStateNotSupport,error);
+ });
+
+ }
+}
+
+- (void)HDL_showFaceIDWithDescribe:(NSString *)mlocalizedReason blockState:(faceIDStateBlock)block {
+ NSError *error;
+
+ LAContext *context = [[LAContext alloc] init];
+
+ BOOL canAuthentication = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
+ if (canAuthentication) {
+ [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:mlocalizedReason reply:^(BOOL success, NSError * _Nullable error) {
+ //娉ㄦ剰iOS 11.3涔嬪悗闇�瑕侀厤缃甀nfo.plist鏉冮檺鎵嶅彲浠ラ�氳繃Face ID楠岃瘉鍝�!涓嶇劧鍙兘杈撳瘑鐮佸暒...
+ if (success) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ block(HDLFaceIDStateSuccess,error);
+ });
+ } else {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"褰撳墠杞欢琚寕璧峰苟鍙栨秷浜嗘巿鏉冿紙濡侫pp杩涘叆浜嗗悗鍙扮瓑锛�");
+ block(HDLFaceIDStateFail,error);
+ });
+ }
+ }];
+ }
+}
+
+
+// 鍒ゆ柇璁惧鏀寔鍝璁よ瘉鏂瑰紡 TouchID & FaceID
+- (HDLTouchIDSupperType) HDL_canSupperBiometrics {
+ LAContext *context = [[LAContext alloc] init];
+ NSError *error;
+ if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
+ if (error != nil) {
+ return HDLTouchIDSupperTypeNone;
+ }
+ if (@available(iOS 11.0, *)) {
+ return context.biometryType == LABiometryTypeFaceID ? HDLTouchIDSupperTypeFaceID : HDLTouchIDSupperTypeTouchID;
+ }
+ }
+ return HDLTouchIDSupperTypeNone;
+}
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.h
new file mode 100644
index 0000000..c011356
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.h
@@ -0,0 +1,33 @@
+//
+// HDLUtlisXM.h
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/10/30.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+// Color
+#define HEXCOLORA(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:a]
+#define HEXCOLOR(rgbValue) HEXCOLORA(rgbValue, 1.0)
+
+#define RGBACOLOR(r,g,b,a) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:(a)]
+#define RGBCOLOR(r,g,b) RGBACOLOR(r,g,b,1)
+
+//鍧愭爣瑙掑害绛夎绠楀叕寮�
+#define GETEndAngle(X) ( ((90-X) < 0) ? ((90-X)+360) : (90-X) )
+#define GETStartAngle(X) ( 90 + X)
+#define ToRad(deg) ( (M_PI * (deg)) / 180.0 )
+#define ToDeg(rad) ( (180.0 * (rad)) / M_PI )
+#define SQR(x) ( (x) * (x) )
+#define APP_UIFont @"PingFangSC-Regular"
+
+
+@interface HDLUtlisXM : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.m
new file mode 100644
index 0000000..31e0e8c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLUtlisXM.m
@@ -0,0 +1,13 @@
+//
+// HDLUtlisXM.m
+// HDLWidgetLibrary
+//
+// Created by HDL on 2019/10/30.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLUtlisXM.h"
+
+@implementation HDLUtlisXM
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.h
new file mode 100644
index 0000000..bf0f16a
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.h
@@ -0,0 +1,149 @@
+//
+// HDLOnWaveSeekbar.h
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/7/2.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "SeekBarDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HDLOnWaveSeekbar : UIControl
+
+
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+/**
+ 榛樿鑳屾櫙棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mWaveBackgroundColor;
+
+/**
+ 鍦嗚澶у皬
+ */
+@property (nonatomic, assign) int mCornerRadius;
+
+/**
+ 鎷栧姩鎸夐挳楂樺害
+ */
+@property (nonatomic, assign) int thumbBtnHeight;
+
+/**
+ 鎷栧姩鎸夐挳棰滆壊
+ */
+@property (nonatomic, strong) UIColor* thumbBtnColor;
+
+
+#pragma mark HDLSeekBarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLSeekBarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameWaveSeekBar:(CGRect) mCGRect;
+
+///**
+// 璁剧疆娓愬彉鏁堟灉 棰滆壊鏁扮粍
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors;
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+/**
+ 璁剧疆杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor;
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY;
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline;
+
+/**
+ 璁剧疆鏄剧ず鎷栧姩鎸夐挳
+ */
+-(void)setThumbBtnShow:(BOOL)isShow;
+
+/**
+ 璁剧疆绂荤嚎鏃� 杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setOfflineProgressBarColor:(UIColor *)oneColor;
+
+@end
+NS_ASSUME_NONNULL_END
+
+
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.m
new file mode 100644
index 0000000..30834b6
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLOnWaveSeekbar.m
@@ -0,0 +1,508 @@
+//
+// HDLOnWaveSeekbar.m
+// HDL_Widget_iOS
+//
+// Created by 闄堝槈涔� on 2020/7/2.
+// Copyright 漏 2020 JLChen. All rights reserved.
+//
+
+#import "HDLOnWaveSeekbar.h"
+#import "HDLUtlisXM.h"
+
+//#define DEFAULT_WAVE_COLOR HEXCOLOR(0xFD692E)
+//#define DEFAULT_WAVE_END_COLOR HEXCOLOR(0xFB3140)
+
+@interface HDLOnWaveSeekbar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mWaveProgressBarColors;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mOfflineProgressBarColors;
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isOffline;
+
+/**
+ 鏄惁绂荤嚎
+ */
+@property (nonatomic, assign) BOOL isShowThumbBtn;
+
+
+@end
+
+
+@implementation HDLOnWaveSeekbar{
+
+ int _mMoveCount;
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+ bool _bIsInWaveProgress;
+ CGFloat _mWaveHeight;
+ CGFloat _mWaveWidth;
+ CGFloat _mWaveStartX;
+ CGFloat _mWaveEndX;
+ CGFloat _mThumbBtnStartX;
+ CGFloat _mThumbBtnEndX;
+ float _mPercent;
+ CGFloat _mCurtainY;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ //鍦嗚
+ _mCornerRadius = 20;
+ //杩涘害鏂囧瓧
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _isProgressTextShow = YES;
+ //鎷栧姩鎸夐挳
+ _thumbBtnColor = [UIColor whiteColor];
+ _thumbBtnHeight = 10;
+ _isShowThumbBtn = YES;
+ //棰滆壊閰嶇疆
+ _mWaveBackgroundColor = HEXCOLOR(0xF2F3F7);
+ [self setProgressBarColor:HEXCOLOR(0xFC9C04)];
+ [self setOfflineProgressBarColor:HEXCOLOR(0xDFE1E6)];
+
+ [self refreshFrame];
+ self.backgroundColor = [UIColor clearColor];
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ _mWaveHeight = self.frame.size.height;
+ _mWaveWidth = self.frame.size.width;
+ _mWaveStartX = 0;
+ _mWaveEndX = _mWaveWidth;
+ _mThumbBtnStartX = _mWaveWidth * 3 / 8;
+ _mThumbBtnEndX = _mWaveWidth * 5 / 8;
+}
+
+///**
+// 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+//
+// */
+//-(void)onWaveSizeChange{
+// _mWaveHeight = self.frame.size.height;
+// _mWaveWidth = self.frame.size.width;
+// _mWaveStartX = 0;
+// _mWaveEndX = _mWaveWidth;
+// _mThumbBtnStartX = _mWaveWidth * 3 / 8;
+// _mThumbBtnEndX = _mWaveWidth * 5 / 8;
+//}
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ // //*********缁樺埗杈规鑳屾櫙*********
+ // [self drawBorderPath:ctx];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鎷栧姩鎸夐挳*********
+ [self drawThumbBtn:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(0, 0 , _mWaveWidth, _mWaveHeight );
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:_mCornerRadius];;
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ //缁樺埗鑳屾櫙棰滆壊璁剧疆
+ [_mWaveBackgroundColor set];
+ CGContextFillRect(ctx, drawRect2);
+ //缁樺埗杩涘害鐭╁舰
+ CGFloat y = _mWaveHeight - _mPercent * _mWaveHeight;
+ _mCurtainY = y;
+ CGContextBeginPath( ctx );
+ //璧风偣-缁堢偣
+ CGPoint pointsRect[4] = {CGPointMake(_mWaveStartX, _mCurtainY),CGPointMake(_mWaveStartX, _mWaveHeight), CGPointMake(_mWaveEndX,_mWaveHeight),CGPointMake(_mWaveEndX, _mCurtainY)};
+ CGContextAddLines(ctx, pointsRect, 4);
+ //缁樺埗娓愬彉棰滆壊
+ [self drawArcWithGradient:ctx rect:drawRect2];
+}
+
+/**
+ 缁樺埗鎷栧姩鎸夐挳
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawThumbBtn:(CGContextRef)ctx{
+ if(_isShowThumbBtn){
+ //鐢荤嚎
+ CGContextSetLineWidth(ctx, _thumbBtnHeight);
+ CGContextSetLineCap(ctx, kCGLineCapRound);
+ CGContextSetStrokeColorWithColor(ctx,_thumbBtnColor.CGColor);
+ CGPoint aPoints[2];//鍧愭爣鐐�
+ aPoints[0] =CGPointMake(_mThumbBtnStartX, _mCurtainY);//鍧愭爣1
+ aPoints[1] =CGPointMake(_mThumbBtnEndX, _mCurtainY);//鍧愭爣2
+ //points[]鍧愭爣鏁扮粍锛屽拰count澶у皬
+ CGContextAddLines(ctx, aPoints, 2);//娣诲姞绾�
+ CGContextStrokePath(ctx);
+ }
+}
+
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ if(_mPercent > 0.6){
+ _mProgressTextColor = [UIColor whiteColor];
+ }else{
+ _mProgressTextColor = [UIColor blackColor];
+ }
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+/**
+ 缁樺埗娓愬彉鏁堟灉
+ */
+-(void)drawArcWithGradient:(CGContextRef)ctx rect:(CGRect)rect{
+ // 鍒涘缓涓�涓笎鍙樿壊
+ // 鍒涘缓RGB鑹插僵绌洪棿锛屽垱寤鸿繖涓互鍚庯紝context閲岄潰鐢ㄧ殑棰滆壊閮芥槸鐢≧GB琛ㄧず
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGGradientRef gradient;
+ if(_isOffline){
+ gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mOfflineProgressBarColors, NULL);
+ }else{
+ gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mWaveProgressBarColors, NULL);
+ }
+
+ // 閲婃斁鑹插僵绌洪棿
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+ // 鍓璺緞
+ CGContextClip(ctx);
+ // 鐢ㄦ笎鍙樿壊濉厖
+ CGContextDrawLinearGradient(ctx, gradient, CGPointMake(rect.origin.x, rect.origin.y), CGPointMake(rect.origin.x+rect.size.width, rect.origin.y+rect.size.height), 0);
+ // 閲婃斁娓愬彉鑹�
+ CGGradientRelease(gradient);
+ gradient = NULL;
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+}
+
+///**
+// 璁$畻2鐐瑰潗鏍囦箣闂寸殑璺濈
+//
+// @param startPoint 璧风偣鍧愭爣
+// @param endPonit 缁堢偣鍧愭爣
+// @return 璺濈
+// */
+//-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
+// CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
+// float d = sqrt(SQR(v.x) + SQR(v.y));
+// NSLog(@"2鐐硅窛绂�:%f ", d);
+// return d;
+//
+//}
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+ _bIsInWaveProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInWaveProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+///**
+// 鍒ゆ柇鏈�鍚庣寮�鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+//
+// @param lastPoint 鏈�鍚庣殑鍧愭爣
+// */
+//-(void)getEndPointIsInArcProgress:(CGPoint)lastPoint {
+// [self getCurrentProgressWithLastPoint:lastPoint];
+//}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y) / _mWaveHeight;
+
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+ _mPercent = 1 - _mPercent;
+ _mProgress = _mPercent * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ // [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameWaveSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mWaveProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor{
+ _mWaveProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+}
+
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY{
+ return _mCurtainY;
+}
+
+
+
+/**
+ 璁剧疆鏄惁绂荤嚎
+ */
+-(void)setOffline:(BOOL)isOffline{
+ _isOffline = isOffline;
+ _isClickable = !_isOffline;
+ [self setNeedsDisplay];
+}
+
+/**
+ 璁剧疆鏄剧ず鎷栧姩鎸夐挳
+ */
+-(void)setThumbBtnShow:(BOOL)isShow{
+ _isShowThumbBtn = isShow;
+ [self setNeedsDisplay];
+}
+
+/**
+ 璁剧疆绂荤嚎杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setOfflineProgressBarColor:(UIColor *)oneColor{
+ _mOfflineProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+}
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.h
new file mode 100755
index 0000000..630ad6c
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.h
@@ -0,0 +1,187 @@
+//
+// HDLwaveSeekBar.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/8/27.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+
+
+
+
+@protocol HDLWaveSeekbarProgressChangedDelegate <NSObject>
+
+//鎵嬫寚鎸変笅锛屽紑濮嬬偣鍑�
+-(void)onStartTrackingTouch;
+
+//婊戝姩瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onProgressChanged:(int)mProgress;
+
+//鍋滄婊戝姩鎴栫粨鏉熺偣鍑伙紝瀵艰嚧鐨勮繘搴﹀�煎彂鐢熸敼鍙�
+-(void)onStopTrackingTouch:(int)mProgress;
+
+
+@end
+
+@interface HDLWaveSeekbar : UIControl
+
+
+
+/**
+ 鏄惁鍙互鐐瑰嚮
+ */
+@property (nonatomic, assign) BOOL isClickable;
+
+
+///**
+// 鑳屾櫙棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mArcBackBarColor;
+
+///**
+// 鎷栧姩鎸夐挳棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mThumbColor;
+
+/**
+ 褰撳墠鍊�
+ */
+@property (nonatomic, assign) int mProgress;
+
+
+/**
+ 杩涘害鍊兼枃瀛楁槸鍚︽樉绀�
+ */
+@property (nonatomic, assign) BOOL isProgressTextShow;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mProgressTextColor;
+
+/**
+ 鏄剧ず杩涘害鏂囧瓧澶у皬
+ */
+@property (nonatomic, assign) int mProgressTextSize;
+
+///**
+// 杩涘害棰滆壊
+// */
+//@property (nonatomic, strong) UIColor* mWaveProgressBarColor;
+
+
+/**
+ 杈规棰滆壊
+ */
+@property (nonatomic, strong) UIColor* mWaveBorderColor;
+
+/**
+ 鍦嗚澶у皬
+ */
+@property (nonatomic, assign) int mCornerRadius;
+
+
+
+///**
+// 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+// */
+//@property (nonatomic, assign) int mTextDefaultDistance;
+
+
+#pragma mark HDLWaveSeekbarProgressChangedDelegate
+/**
+ 杩涘害鍊兼敼鍙樹唬鐞嗕簨浠�
+ */
+@property (nonatomic,weak) id<HDLWaveSeekbarProgressChangedDelegate> mProgressChangedDelegate;
+
+#pragma mark 瀵瑰鎺ュ彛鏂规硶
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress;
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString;
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue;
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameWaveSeekBar:(CGRect) mCGRect;
+
+
+
+///**
+// 璁剧疆娓愬彉鏁堟灉 棰滆壊鏁扮粍
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors;
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor;
+
+/**
+ 璁剧疆杩涘害鏉¢鑹�
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor;
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setWavePadding:(int)Padding;
+
+/**
+ 璁剧疆鑳屾櫙杈规瀹藉害
+ */
+-(void)setBorderWidth:(int)borderWidth;
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY;
+
+@end
+NS_ASSUME_NONNULL_END
+
+
+
+//*****V1.0.1*****
+//# HDLWaveSeekbar(娉㈡氮鏁堟灉鎷栧姩鏉�)
+//- [x] 鏀寔杩涘害搴︾姸鎬佹樉绀哄��,鍜岃嚜瀹氫箟鏄剧ず鍗曚綅
+//- [x] 鏀寔杩涘害鏄剧ず鏉�
+//- [x] 澧炲姞绂佹鐐瑰嚮鎺ュ彛
+//
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.m
new file mode 100755
index 0000000..29235f2
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/HDLWaveSeekbar/HDLWaveSeekBar.m
@@ -0,0 +1,568 @@
+//
+// HDLwaveSeekBar.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/8/27.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLWaveSeekBar.h"
+#import "HDLUtlisXM.h"
+
+#define APP_DEFAULT_BG [UIColor colorWithRed:72/255.0f green:72/255.0f blue:73/255.0f alpha:1.0f]
+
+#define APP_DEFAULT_BG_LINE [UIColor colorWithRed:73/255.0f green:87/255.0f blue:128/255.0f alpha:1.0f]
+
+//#define APP_DEFAULT_BAR [UIColor colorWithRed:252/255.0f green:59/255.0f blue:62/255.0f alpha:0.8f]
+
+#define DEFAULT_WAVE_COLOR HEXCOLOR(0xFD692E)
+#define DEFAULT_WAVE_END_COLOR HEXCOLOR(0xFB3140)
+
+
+#define ToRad(deg) ( (M_PI * (deg)) / 180.0 )
+#define ToDeg(rad) ( (180.0 * (rad)) / M_PI )
+#define SQR(x) ( (x) * (x) )
+#define GETEndAngle(X) ( ((90-X) < 0) ? ((90-X)+360) : (90-X) )
+#define GETStartAngle(X) ( 90 + X)
+//#define DEFAULT_DISTANCE_BETWEEN_TEXTPOINT_AND_ARC 30 // 杩涘害鏄剧ず鏂囧瓧鍧愭爣涓庤繘搴﹀渾寮х殑璺濈
+#define DEFAULT_PADDING 5 //鍦嗗姬鑷甫PADDING鍊硷紝涓轰簡鏄剧ず杩涘害test鏂囧瓧
+#define DEFAULT_OPEN_ANGLE 30.0f // 寮�鍙h搴�
+
+
+@interface HDLWaveSeekbar ()
+
+
+
+/**
+ 鏄惁姝e湪绉诲姩
+ */
+@property (nonatomic, assign) BOOL bTouchMove;
+
+/**
+ 杩涘害鍗曚綅绗﹀彿
+ */
+@property (nonatomic, strong) NSString *mProgressBarUnitSring;
+
+/**
+ 鏈�灏忓��
+ */
+@property (nonatomic, assign) float mMinValue;
+
+/**
+ 鏈�澶у��
+ */
+@property (nonatomic, assign) float mMaxValue;
+
+/**
+ 杩涘害娓愬彉棰滆壊鏁扮粍
+ */
+@property (nonatomic, strong) NSArray *mWaveProgressBarColors;
+
+/**
+ 鑳屾櫙绾垮
+ */
+@property (nonatomic, assign) int mBackLineWidth;
+
+/**
+ 杈硅窛
+ */
+@property (nonatomic, assign) int WavePadding;
+
+
+
+@end
+
+
+@implementation HDLWaveSeekbar{
+
+ int _mMoveCount;
+
+ CGPoint _mCenterPoint; //鍦嗗績鍧愭爣
+
+ bool _bIsInWaveProgress;
+
+ CGFloat _mWaveHeight;
+ CGFloat _mWaveWidth;
+
+ CGFloat _mWaveStartX;
+ CGFloat _mWaveEndX;
+
+
+ CGFloat _waveA; // A
+ CGFloat _waveW; // 蠅
+ // CGFloat _offsetF; // 蠁 firstLayer
+ // CGFloat _offsetS; // 蠁 secondLayer
+ CGFloat _currentK; // k
+
+ float _mPercent;
+
+ CGFloat _mWavePadding;
+ CGFloat _mCurtainY;
+
+}
+
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _isClickable = YES;
+ _mMoveCount = 0;
+
+ _mProgress = 0;
+ _mPercent = 0;
+ _mMaxValue = 100.0f;
+ _mMinValue = 0.0f;
+ _mBackLineWidth = 2;
+ _mCornerRadius = 10;
+ _WavePadding = 10;
+ _mProgressTextColor = [UIColor blackColor];
+ _mProgressTextSize = 15;
+ _mProgressBarUnitSring = @"%";
+ _mWaveBorderColor = APP_DEFAULT_BG_LINE;
+
+ _isProgressTextShow = YES;
+ // _mWaveProgressBarColor = APP_DEFAULT_BAR;
+ _waveA = 6.0f;
+
+
+// [self setProgressBarColor:APP_DEFAULT_BAR];
+ _mWaveProgressBarColors = @[
+ (id) DEFAULT_WAVE_COLOR.CGColor,
+ (id)DEFAULT_WAVE_END_COLOR.CGColor
+ ];
+
+ [self refreshFrame];
+
+
+ self.backgroundColor = [UIColor clearColor];
+ }
+
+ return self;
+}
+
+
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)refreshFrame{
+ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ _mWavePadding = _WavePadding*2 + _mBackLineWidth;
+ _mWaveHeight = self.frame.size.height - _mWavePadding*2;
+ _mWaveWidth = self.frame.size.width - _mWavePadding*2;
+ _mWaveStartX = _mWavePadding;
+ _mWaveEndX = _mWaveWidth + _mWaveStartX;
+}
+
+#pragma mark drawRect 缁樺埗鍥惧舰
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+ //灏嗗綋鍓嶅浘褰㈢姸鎬佹帹鍏ュ爢鏍�
+ CGContextSaveGState(ctx);
+ //*********缁樺埗杈规鑳屾櫙*********
+ [self drawBorderPath:ctx];
+ //*********缁樺埗鍔ㄦ�佺殑杩涘害鏉�*********
+ [self drawProgressBar:ctx];
+ //*********缁樺埗鏄剧ず杩涘害鍊兼枃瀛�*********
+ [self drawProgressText:ctx];
+
+ // [self drawArcWithGradient:ctx rect:rect];//缁樺埗娓愬彉鏁堟灉
+
+ //鎶婂爢鏍堥《閮ㄧ殑鐘舵�佸脊鍑�
+ CGContextRestoreGState(ctx);
+
+}
+
+/**
+ 缁樺埗杈规
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawBorderPath:(CGContextRef)ctx{
+ CGRect drawRect = {_WavePadding+_mBackLineWidth/2, _WavePadding+_mBackLineWidth/2, self.frame.size.width-_WavePadding*2-_mBackLineWidth, self.frame.size.height-_WavePadding*2-_mBackLineWidth};
+
+ UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius];
+ path.lineWidth = _mBackLineWidth; //绾垮
+ path.lineCapStyle = kCGLineCapRound; //寮鏍峰紡
+ path.lineJoinStyle = kCGLineJoinBevel; //浜ょ偣鐨勬牱寮�
+ [_mWaveBorderColor set];
+
+ CGContextSetLineWidth(ctx, _mBackLineWidth);
+ CGContextAddPath(ctx, path.CGPath);
+ CGContextDrawPath(ctx, kCGPathStroke);
+ // [path stroke]; //杈规绾块鑹�
+}
+
+
+
+/*
+ y = Asin(蠅x+蠁)+k
+ A琛ㄧず鎸箙锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鐨勯珮搴�
+ 蠅琛ㄧず棰戠巼锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮瀵嗛泦搴�
+ 蠁琛ㄧず鍒濈浉锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鍒濆浣嶇疆
+ k琛ㄧず楂樺害锛屼娇鐢ㄨ繖涓彉閲忔潵璋冩暣娉㈡氮鍦ㄥ睆骞曚腑y杞寸殑浣嶇疆銆�
+ */
+
+/**
+ 缁樺埗杩涘害鏉�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressBar:(CGContextRef)ctx{
+
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+ CGRect drawRect2 = CGRectMake(_mWaveStartX, _mWavePadding , _mWaveWidth, _mWaveHeight );
+ UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:_mCornerRadius];;
+ CGContextAddPath(ctx, path2.CGPath);
+ // 鍓璺緞
+ CGContextClip(ctx);
+ //*******缁樺埗鍓闄愬埗鏄剧ず鍖哄煙*********
+
+
+ CGFloat y = _mWaveHeight - _mPercent * _mWaveHeight + _mWavePadding;
+ _mCurtainY = y;
+ CGContextBeginPath( ctx );
+ //1銆佹坊鍔犵涓�鐐�
+ CGContextMoveToPoint( ctx, _mWaveStartX, y );
+ CGFloat h = y;
+
+ if(_mPercent>0 && _mPercent<1){
+ //2銆佹坊鍔犳按娉㈡氮鏁堟灉锛屾鐜勫嚱鏁� 鏉ヨ绠楁瘡涓�涓儚绱犵殑鍧愭爣
+ for (int i = _mWaveStartX; i <= _mWaveEndX; ++i) {
+ y= h + _waveA * sin((i+h)*M_PI/60);
+ CGContextAddLineToPoint(ctx, i, y);
+ }
+ CGContextAddLineToPoint(ctx, _mWaveEndX, _mWavePadding + _mWaveHeight);
+ CGContextAddLineToPoint(ctx, _mWaveStartX, _mWavePadding + _mWaveHeight);
+ }else{
+ //璧风偣-缁堢偣
+ CGPoint pointsRect[4] = {CGPointMake(_mWaveStartX, h),CGPointMake(_mWaveStartX, _mWavePadding + _mWaveHeight), CGPointMake(_mWaveEndX, _mWavePadding + _mWaveHeight),CGPointMake(_mWaveEndX, h)};
+ CGContextAddLines(ctx, pointsRect, 4);
+ }
+
+ [self drawArcWithGradient:ctx rect:drawRect2];
+
+ // CGContextClosePath(ctx);
+ //
+ // CGContextSetFillColorWithColor( ctx, _mWaveProgressBarColor.CGColor );
+ //
+ //// CGContextSetStrokeColorWithColor( ctx, APP_DEFAULT_BAR.CGColor );
+ //
+ //// CGContextSetLineWidth( ctx, 1 );
+ //
+ // CGContextDrawPath( ctx, kCGPathFill );
+
+}
+
+/**
+ 缁樺埗杩涘害鏄剧ず鍊兼枃瀛�
+
+ @param ctx 鐢诲竷
+ */
+-(void)drawProgressText:(CGContextRef)ctx{
+ if(_isProgressTextShow){
+ if(_mPercent > 0.6){
+ _mProgressTextColor = [UIColor whiteColor];
+ }else{
+ _mProgressTextColor = [UIColor blackColor];
+ }
+ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring] outsidePoint:_mCenterPoint];
+ }
+}
+
+/**
+ drawString 鐜板湪褰撳墠杩涘害鍊�
+ @param mText 鏄剧ず鏂囨湰
+ @param outsidePoint 鍧愭爣
+ */
+- (void) drawString:(NSString *)mText outsidePoint:(CGPoint)outsidePoint{
+ NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
+ paragraph.alignment = NSTextAlignmentCenter;
+ NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize],
+ NSForegroundColorAttributeName : _mProgressTextColor,
+ NSParagraphStyleAttributeName : paragraph
+ };
+
+ // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20);
+ // [mText drawInRect:textRect withAttributes:dic];
+
+ //2019-08-15 淇敼鏂囧瓧缁樺埗鏂规硶锛屾渶缁堝疄鐜版枃鏈眳涓晥鏋�
+ CGSize textSize = [mText sizeWithAttributes:dic];
+ CGPoint textPoint = CGPointMake(outsidePoint.x - textSize.width/2, outsidePoint.y - textSize.height/2);//鏍规嵁涓偣鍧愭爣缁樺埗
+ [mText drawAtPoint:textPoint withAttributes:dic];
+
+}
+
+
+/**
+ 缁樺埗娓愬彉鏁堟灉
+ */
+-(void)drawArcWithGradient:(CGContextRef)ctx rect:(CGRect)rect{
+ // 鍒涘缓涓�涓笎鍙樿壊
+ // 鍒涘缓RGB鑹插僵绌洪棿锛屽垱寤鸿繖涓互鍚庯紝context閲岄潰鐢ㄧ殑棰滆壊閮芥槸鐢≧GB琛ㄧず
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)_mWaveProgressBarColors, NULL);
+ // 閲婃斁鑹插僵绌洪棿
+ CGColorSpaceRelease(colorSpace);
+ colorSpace = NULL;
+ // 鍓璺緞
+ CGContextClip(ctx);
+ // 鐢ㄦ笎鍙樿壊濉厖
+ CGContextDrawLinearGradient(ctx, gradient, CGPointMake(rect.origin.x, rect.origin.y), CGPointMake(rect.origin.x+rect.size.width, rect.origin.y+rect.size.height), 0);
+ // 閲婃斁娓愬彉鑹�
+ CGGradientRelease(gradient);
+ gradient = NULL;
+
+ CGContextRestoreGState(ctx);// 鎭㈠鍒颁箣鍓嶇殑context
+ CGContextSaveGState(ctx);
+}
+
+///**
+// 璁$畻2鐐瑰潗鏍囦箣闂寸殑璺濈
+//
+// @param startPoint 璧风偣鍧愭爣
+// @param endPonit 缁堢偣鍧愭爣
+// @return 璺濈
+// */
+//-(float) getTwoPointDistance:(CGPoint)startPoint endPonit:(CGPoint)endPonit{
+// CGPoint v = CGPointMake(startPoint.x - endPonit.x, startPoint.y - endPonit.y);
+// float d = sqrt(SQR(v.x) + SQR(v.y));
+// NSLog(@"2鐐硅窛绂�:%f ", d);
+// return d;
+//
+//}
+
+
+
+#pragma mark Touch Event 鐐瑰嚮浜嬩欢
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super beginTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ _bTouchMove = NO;
+ _mMoveCount = 0;
+ // CGPoint startPoint = [touch locationInView:self];
+ // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//鍒ゆ柇寮�濮嬪潗鏍囨槸鍚﹀湪鍙偣鍑诲尯鍩�
+
+ _bIsInWaveProgress = YES;//涓嶉檺鍒剁偣鍑诲尯鍩�
+ [self.mProgressChangedDelegate onStartTrackingTouch];
+ return YES;
+}
+
+-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
+ [super endTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return;//绂佹鐐瑰嚮
+ if(!_bTouchMove){//娌$Щ鍔紝浠呯偣鍑�
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ }
+ [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress];
+}
+
+
+-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+ [super continueTrackingWithTouch:touch withEvent:event];
+ if(!_isClickable) return YES;//绂佹鐐瑰嚮
+ if(_mMoveCount < 2){
+ _mMoveCount++;
+ }else{
+ _bTouchMove = YES; //寮�濮嬬Щ鍔�
+ }
+
+ if(_bIsInWaveProgress){//濡傛灉鍒氬紑濮嬬偣鍑荤殑鍧愭爣鍦ㄥ彲鐐瑰嚮鍖哄煙
+ CGPoint lastPoint = [touch locationInView:self];
+ [self getCurrentProgressWithLastPoint:lastPoint];
+ }
+ [self sendActionsForControlEvents:UIControlEventValueChanged];
+ return YES;
+}
+
+
+///**
+// 鍒ゆ柇鏈�鍚庣寮�鍧愭爣鏄惁鍦ㄥ彲鐐瑰嚮鍖哄煙
+//
+// @param lastPoint 鏈�鍚庣殑鍧愭爣
+// */
+//-(void)getEndPointIsInArcProgress:(CGPoint)lastPoint {
+// [self getCurrentProgressWithLastPoint:lastPoint];
+//}
+
+
+/**
+ 鏍规嵁鍧愭爣璁$畻鍑哄綋鍓嶈繘搴︾櫨鍒嗘瘮鍜屽搴旂殑杩涘害鍊�
+
+ @param point 褰撳墠鍧愭爣
+ */
+-(void)getCurrentProgressWithLastPoint:(CGPoint)point {
+
+ _mPercent = (point.y - 10 - _mBackLineWidth ) / _mWaveHeight;
+ // NSLog(@"point.y:%f _mWaveHeight:%f",point.y,_mWaveHeight);
+ // NSLog(@"_mPercent:%f",_mPercent);
+ //
+ if(_mPercent > 1){
+ _mPercent = 1;
+ }else if(_mPercent < 0){
+ _mPercent = 0;
+ }
+ _mPercent = 1 - _mPercent;
+ _mProgress = _mPercent * (_mMaxValue - _mMinValue) + _mMinValue;
+
+ if(_bTouchMove){
+ [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+ }
+
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 鏍规嵁杩涘害鍊硷紝璁$畻褰撳墠 _mProgressAngle鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setSeekBarProgressToValue:(int)mProgress{
+ if(mProgress < _mMinValue){
+ mProgress = _mMinValue;
+ }
+ if(mProgress > _mMaxValue){
+ mProgress = _mMaxValue;
+ }
+ _mProgress = mProgress;
+ _mPercent = (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue);
+ // [self.mProgressChangedDelegate onProgressChanged:_mProgress];
+}
+
+#pragma mark 璁剧疆杩涘害鏉′綅缃�
+/**
+ 璁剧疆杩涘害鍊�
+
+ @param mProgress 杩涘害鍊�
+ */
+-(void)setProgress:(int)mProgress{
+ [self setSeekBarProgressToValue:mProgress];
+ [self setNeedsDisplay];
+}
+
+
+/**
+ 璁剧疆杩涘害鏄剧ず鍊煎崟浣�
+
+ @param mString 鍗曚綅瀛楃
+ */
+-(void)setProgressBarUnitSring:(NSString *)mString{
+ _mProgressBarUnitSring = mString;
+}
+
+
+/**
+ 璁剧疆鏈�澶у�兼渶灏忓��
+
+ @param mMinValue 鏈�灏忓��
+ @param mMaxValue 鏈�澶у��
+ */
+-(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{
+ if(mMinValue < mMaxValue){
+ _mMinValue = mMinValue;
+ _mMaxValue = mMaxValue;
+ }else{
+ _mMinValue = mMaxValue;
+ _mMaxValue = mMinValue;
+ }
+ _mProgress = _mMinValue;
+ _mPercent = 0.0f;
+}
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameWaveSeekBar:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ [self refreshFrame];
+}
+
+
+//
+///**
+// 璁剧疆娓愬彉鏁堟灉
+//
+// @param mColors 棰滆壊鏁扮粍
+// */
+//-(void)setProgressBarColors:(NSArray *)mColors{
+//
+// // NSArray * colors = [NSArray arrayWithObjects锛氾紙id锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+//
+//}
+
+
+
+/**
+ 璁剧疆娓愬彉鏁堟灉
+
+ @param startColor 寮�濮嬮鑹�
+ @param endColor 缁撴潫棰滆壊
+ */
+-(void)setProgressBarColors:(UIColor *)startColor endColor:(UIColor*)endColor{
+ // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mWaveProgressBarColors = @[
+ (id)startColor.CGColor,
+ (id)endColor.CGColor
+ ];
+}
+
+
+/**
+ 璁剧疆杩涘害鏉¢鑹� 鍗曚竴棰滆壊
+
+ @param oneColor 鍗曚竴棰滆壊
+ */
+-(void)setProgressBarColor:(UIColor *)oneColor{
+ // // _mArcProgressBarColors = [NSArray arrayWithObjects锛坕d锛塻tartColor.CGColor锛岋紙id锛塭ndColor.CGColor锛宯il];
+ _mWaveProgressBarColors = @[
+ (id)oneColor.CGColor,
+ (id)oneColor.CGColor
+ ];
+
+// _mWaveProgressBarColor = oneColor;
+}
+
+
+/**
+ 璁剧疆杈硅窛
+ */
+-(void)setWavePadding:(int)Padding{
+ _WavePadding = Padding;
+ [self onWaveSizeChange];
+}
+
+/**
+ 璁剧疆鑳屾櫙杈规瀹藉害
+ */
+-(void)setBorderWidth:(int)borderWidth{
+ _mBackLineWidth = borderWidth;
+ [self onWaveSizeChange];
+}
+
+/**
+ 鑾峰彇楂樺害 Y鍊�
+ */
+-(CGFloat)getProgressY{
+ return _mCurtainY;
+}
+
+/**
+ 鍒锋柊甯冨眬锛屾洿鏂板叧閿��
+
+ */
+-(void)onWaveSizeChange{
+ _mWavePadding = _WavePadding*2 + _mBackLineWidth;
+ _mWaveHeight = self.frame.size.height - _mWavePadding*2;
+ _mWaveWidth = self.frame.size.width - _mWavePadding*2;
+ _mWaveStartX = _mWavePadding;
+ _mWaveEndX = _mWaveWidth + _mWaveStartX;
+}
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.h
new file mode 100644
index 0000000..8a40b96
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.h
@@ -0,0 +1,61 @@
+//
+// HDLPickerView.h
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/9/25.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol HDLPickerviewChangedDelegate<NSObject>
+
+//閫変腑鍊兼敼鍙�
+-(void)onOptionsSelectChangeListener:(NSInteger)selectIndex1 selectIndex2:(NSInteger)selectIndex2 selectIndex3:(NSInteger)selectIndex3;
+
+
+@end
+
+@interface HDLPickerView : UIView
+
+#pragma mark HDLPickerviewChangedDelegate
+/**
+閫変腑鍊兼敼鍙�
+ */
+@property (nonatomic,weak) id<HDLPickerviewChangedDelegate> mChangedDelegate;
+
+
+- (void)setNPicker:(nonnull NSArray *)dataList
+ mSecondList:(nullable NSArray *)mSecondList
+ mThirdList:(nullable NSArray *)mThirdList;
+
+-(void)setCurrentItems:(NSInteger)selectIndex1 selectIndex2:(NSInteger)selectIndex2 selectIndex3:(NSInteger)selectIndex3;
+
+
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameArc:(CGRect) mCGRect;
+
+
+/**
+ 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ */
+-(void)setTextColorCenter:(UIColor *)mColor optionId:(NSInteger)optionId;
+-(void)setTextColorCenterAll:(UIColor *)mColor;
+-(void)setTextColorCenterAlone:(UIColor *)mColor0 mColor1:(UIColor *)mColor1 mColor2:(UIColor *)mColor2;
+
+/**
+ 澧炲姞鑱斿姩鏁堟灉
+ */
+-(void)setPicker:(nonnull NSArray *)dataList;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.m
new file mode 100644
index 0000000..6b9f47a
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/HDLPickerView.m
@@ -0,0 +1,418 @@
+//
+// HDLPickerView.m
+// HDL_Widget_iOS
+//
+// Created by HDL on 2019/9/25.
+// Copyright 漏 2019 JLChen. All rights reserved.
+//
+
+#import "HDLPickerView.h"
+@interface HDLPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
+
+@property (nonatomic, strong) UIPickerView *pickerView;
+
+//2019-9-5 鏂板榛樿閫夋嫨椤癸紝鍜屽洖璋冮�変腑鐨勭储寮�
+@property (nonatomic, assign) NSInteger selectIndex1;
+@property (nonatomic, assign) NSInteger selectIndex2;
+@property (nonatomic, assign) NSInteger selectIndex3;
+//@property (nonatomic, strong) UIColor *btnColor;
+
+@property (nonatomic, assign) BOOL isLinked; //鏄惁涓嶈仈鍔�
+
+@property (nonatomic, assign) NSUInteger component; // component numbers, default 0
+@property (nonatomic, assign) CGFloat pickerViewHeight; // pickerView height, default 224 pt
+@property (nonatomic, assign) CGFloat oneComponentRowHeight; // one component row height, default 32 pt
+// property
+@property (nonatomic, strong) NSMutableArray *dataList; // data list
+@property (nonatomic, strong) NSMutableArray *mSecondDataList; // 浜岀骇 list
+@property (nonatomic, strong) NSMutableArray *mThirdDataList; // 涓夌骇 list
+//@property (nonatomic, strong) NSDictionary *selectRowTitleAttribute; // select row titlt attribute
+
+@property (nonatomic, strong) NSDictionary *selectRowTitleAttribute0; // select row titlt attribute
+@property (nonatomic, strong) NSDictionary *selectRowTitleAttribute1; // select row titlt attribute
+@property (nonatomic, strong) NSDictionary *selectRowTitleAttribute2; // select row titlt attribute
+
+
+
+
+@end
+
+@implementation HDLPickerView
+
+
+
+/*
+ // Only override drawRect: if you perform custom drawing.
+ // An empty implementation adversely affects performance during animation.
+ - (void)drawRect:(CGRect)rect {
+ // Drawing code
+ }
+ */
+-(instancetype)initWithFrame:(CGRect)frame{
+ self = [super initWithFrame:frame];
+ if (self) {
+
+ // self.selectRowTitleAttribute = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute0 = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute1 = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute2 = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+
+
+ self.pickerViewHeight = 224.0f;
+ self.oneComponentRowHeight = 32.0f;
+ _dataList = [NSMutableArray array];
+ _mSecondDataList = [NSMutableArray array];
+ _mThirdDataList = [NSMutableArray array];
+// self.isLinked = NO;
+ [self addSubview:self.pickerView];
+ self.backgroundColor = [UIColor whiteColor];
+ }
+ return self;
+}
+
+
+#pragma mark- 鎳掑姞杞�
+- (UIPickerView *)pickerView{
+ if (_pickerView == nil) {
+ _pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
+ _pickerView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+ _pickerView.dataSource = self;
+ _pickerView.delegate = self;
+
+ }
+ return _pickerView;
+}
+
+
+
+#pragma mark - UIPickerView DataSource & Delegate
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+ return self.component;
+}
+
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+
+ if(self.isLinked){
+ return [self getDataWithComponent:component].count;
+// return 0;
+ }else{
+ return [self getDataWithComponentNoLinked:component].count;
+ }
+
+}
+
+- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ NSArray *componentArray;
+ if(self.isLinked){
+ componentArray = [self getDataWithComponent:component];
+ }else{
+ componentArray = [self getDataWithComponentNoLinked:component];
+ }
+
+ if (componentArray.count) {
+ if (row < componentArray.count) {
+ id titleData = componentArray[row];
+ if ([titleData isKindOfClass:[NSString class]]) {
+ return titleData;
+ } else if ([titleData isKindOfClass:[NSNumber class]]) {
+ return [NSString stringWithFormat:@"%@", titleData];
+ }
+ }
+ }
+ return @"";
+}
+
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+ if(self.isLinked){
+ if(component == 0){
+ self.selectIndex1 = row;
+ self.selectIndex2 = 0;
+ }else if(component == 1){
+ self.selectIndex2 = row;
+ self.selectIndex3 = 0;
+ }else if(component == 2){
+ self.selectIndex3 = row;
+ }
+
+ [pickerView reloadAllComponents];
+ for (NSUInteger i = 0; i < self.component; i++) {
+ if (i > component) {
+ [pickerView selectRow:0 inComponent:i animated:YES];
+ }
+ }
+ }else{
+ // [pickerView selectRow:row inComponent:component animated:YES];
+ if(component == 0){
+ self.selectIndex1 = row;
+
+ }else if(component == 1){
+ self.selectIndex2 = row;
+ }else if(component == 2){
+ self.selectIndex3 = row;
+ }
+ }
+
+ if(self.mChangedDelegate != nil){
+ [self.mChangedDelegate onOptionsSelectChangeListener:_selectIndex1 selectIndex2:_selectIndex2 selectIndex3:_selectIndex3];
+ }
+
+}
+
+- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
+{
+ return self.oneComponentRowHeight;
+}
+
+- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
+{
+ // set separateline color
+ // if (NO == self.isSettedSelectRowLineBackgroundColor) {
+ // UIView *topSeparateLine = [pickerView.subviews objectAtIndex:1];
+ // UIView *bottomSeparateLine = [pickerView.subviews objectAtIndex:2];
+ // if (topSeparateLine.frame.size.height < 1.0f &&
+ // bottomSeparateLine.frame.size.height < 1.0f) {
+ // topSeparateLine.backgroundColor = self.selectRowLineBackgroundColor;
+ // bottomSeparateLine.backgroundColor = self.selectRowLineBackgroundColor;
+ // self.isSettedSelectRowLineBackgroundColor = YES;
+ // } else {
+ // for (UIView *singleLine in pickerView.subviews) {
+ // if (singleLine.frame.size.height < 1.0f) {
+ // singleLine.backgroundColor = self.selectRowLineBackgroundColor;
+ // self.isSettedSelectRowLineBackgroundColor = YES;
+ // }
+ // }
+ // }
+ // }
+
+ // custom pickerView content label
+ UILabel *pickerLabel = (UILabel *)view;
+
+ // discussion: this is always nil, not Reusing, it's an iOS System bug.
+ // reference: https://stackoverflow.com/questions/20635949/reusing-view-in-uipickerview-with-ios-7/21039321#21039321
+ if (!pickerLabel) {
+ pickerLabel = [[UILabel alloc] init];
+ pickerLabel.textAlignment = NSTextAlignmentCenter;
+ pickerLabel.adjustsFontSizeToFitWidth = YES;
+ pickerLabel.backgroundColor = [UIColor clearColor];
+ }
+ pickerLabel.attributedText = [self pickerView:pickerView attributedTitleForRow:row forComponent:component];
+
+ return pickerLabel;
+}
+//
+- (nullable NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ NSString *normalRowString = [self pickerView:pickerView titleForRow:row forComponent:component];
+
+ if(component == 1){
+ return [[NSAttributedString alloc] initWithString:normalRowString attributes:self.selectRowTitleAttribute1];
+ }else if(component == 2){
+ return [[NSAttributedString alloc] initWithString:normalRowString attributes:self.selectRowTitleAttribute2];
+ }else{
+ return [[NSAttributedString alloc] initWithString:normalRowString attributes:self.selectRowTitleAttribute0];
+ }
+
+}
+
+- (NSArray *)getDataWithComponentNoLinked:(NSInteger)component
+{
+
+ // NSMutableArray *arrayM = [NSMutableArray array];
+ if(component == 0){
+ return self.dataList;
+ }else if(component == 1){
+ return self.mSecondDataList;
+ }else if(component == 2){
+ return self.mThirdDataList;
+ }else{
+ NSMutableArray *arrayM = [NSMutableArray array];
+ return arrayM;
+ }
+}
+
+
+- (NSArray *)getDataWithComponent:(NSInteger)component
+{
+ NSMutableArray *tempArray = [NSMutableArray arrayWithArray:self.dataList];
+ NSMutableArray *arrayM = [NSMutableArray array];
+ for (NSInteger i = 0; i <= component; i++) {
+ if (i == component) {
+ id data = tempArray.firstObject;
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ NSMutableArray *tempTitleArray = [NSMutableArray arrayWithArray:tempArray];
+ [tempArray removeAllObjects];
+ [tempTitleArray enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL * _Nonnull stop) {
+ [tempArray addObjectsFromArray:dict.allKeys];
+ }];
+ [arrayM addObjectsFromArray:tempArray];
+ } else if ([data isKindOfClass:[NSString class]] ||
+ [data isKindOfClass:[NSNumber class]]){
+ [arrayM addObjectsFromArray:tempArray];
+ }
+ } else {
+ NSInteger selectRow = [self.pickerView selectedRowInComponent:i];
+ if (selectRow < tempArray.count) {
+ id data = tempArray[selectRow];
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ [tempArray removeAllObjects];
+ NSDictionary *dict = data;
+ [dict.allValues enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ if ([obj isKindOfClass:[NSArray class]]) {
+ [tempArray addObjectsFromArray:obj];
+ } else {
+ [tempArray addObject:obj];
+ }
+ }];
+ }
+ }
+ }
+ }
+ return arrayM;
+}
+
+-(void)setCurrentItems:(NSInteger)selectIndex1 selectIndex2:(NSInteger)selectIndex2 selectIndex3:(NSInteger)selectIndex3{
+
+ self.selectIndex1 = selectIndex1;
+ self.selectIndex2 = selectIndex2;
+ self.selectIndex3 = selectIndex3;
+ [self.pickerView reloadAllComponents];
+ [self scrollToSelectedRow];
+
+}
+
+
+/*
+ * 2019-09-05 鏍规嵁绱㈠紩閫変腑锛屾浛鎹㈠師鏉ユ牴鎹紶鍏ュ瓧绗﹂�変腑鏂规
+ */
+- (void)scrollToSelectedRow
+{
+ for (NSUInteger i = 0; i < self.component; i++) {
+ if(i == 0){
+ [self.pickerView selectRow:self.selectIndex1 inComponent:i animated:NO];
+ }else if(i == 1){
+ [self.pickerView selectRow:self.selectIndex2 inComponent:i animated:NO];
+ }else if(i == 2){
+ [self.pickerView selectRow:self.selectIndex3 inComponent:i animated:NO];
+ }
+
+ }
+}
+
+/**
+ 閲嶇疆甯冨眬
+
+ @param mCGRect 甯冨眬
+
+ */
+-(void)initWithFrameArc:(CGRect) mCGRect{
+ self.frame = mCGRect;
+ _pickerView.frame = self.frame;
+ _pickerView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
+}
+
+
+/**
+ 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ */
+-(void)setTextColorCenter:(UIColor *)mColor optionId:(NSInteger)optionId{
+ if(optionId == 0){
+ self.selectRowTitleAttribute0 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ }else if(optionId == 1){
+ self.selectRowTitleAttribute1 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ }else if(optionId == 2){
+ self.selectRowTitleAttribute2 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ }
+}
+
+/**
+ 璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ */
+-(void)setTextColorCenterAll:(UIColor *)mColor{
+ self.selectRowTitleAttribute0 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute1 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute2 = @{NSForegroundColorAttributeName : mColor, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+}
+
+
+/**
+ 鍗曠嫭璁剧疆鎸囧畾浣嶇疆 鍒嗗壊绾夸箣闂寸殑鏂囧瓧鐨勯鑹�
+ */
+-(void)setTextColorCenterAlone:(UIColor *)mColor0 mColor1:(UIColor *)mColor1 mColor2:(UIColor *)mColor2 {
+ self.selectRowTitleAttribute0 = @{NSForegroundColorAttributeName : mColor0, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute1 = @{NSForegroundColorAttributeName : mColor1, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowTitleAttribute2 = @{NSForegroundColorAttributeName : mColor2, NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+}
+
+- (void)setNPicker:(nonnull NSArray *)dataList
+ mSecondList:(nullable NSArray *)mSecondList
+ mThirdList:(nullable NSArray *)mThirdList{
+ self.isLinked = NO;
+ //閰嶇疆鍏抽敭鏁版嵁
+ if (dataList && dataList.count > 0) {
+ self.component = 1;
+ [_dataList removeAllObjects];
+ [_dataList addObjectsFromArray:dataList];
+ }
+
+
+
+ if (mSecondList && mSecondList.count > 0) {
+ self.component = 2;
+ [_mSecondDataList removeAllObjects];
+ [_mSecondDataList addObjectsFromArray:mSecondList];
+ }
+
+
+ if (mThirdList && mThirdList.count > 0) {
+ self.component = 3;
+ [_mThirdDataList removeAllObjects];
+ [_mThirdDataList addObjectsFromArray:mThirdList];
+ }
+
+}
+
+-(void)setPicker:(nonnull NSArray *)dataList{
+
+ // no data
+ if (!dataList || dataList.count == 0) {
+ return;
+ }
+
+ [_dataList removeAllObjects];
+ [_dataList addObjectsFromArray:dataList];
+ // calculate component num
+ id data = dataList.firstObject;
+ if ([data isKindOfClass:[NSString class]] ||
+ [data isKindOfClass:[NSNumber class]] ) {
+ self.component = 1;
+ } else if ([data isKindOfClass:[NSDictionary class]]) {
+ self.component ++;
+ [self handleDictDataList:dataList];
+ } else {
+ NSLog(@"ZJPickerView error tip锛歕"Unsupported data type\"");
+ return;
+ }
+
+ self.isLinked = YES;
+}
+
+#pragma mark - private method
+- (void)handleDictDataList:(NSArray *)list{
+ id data = list.firstObject;
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *dict = data;
+ id value = dict.allValues.firstObject;
+ if ([value isKindOfClass:[NSArray class]]) {
+ self.component++;
+ [self handleDictDataList:value];
+ }
+ }
+
+}
+
+
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.h b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.h
new file mode 100755
index 0000000..46b8639
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.h
@@ -0,0 +1,78 @@
+//
+// ZJPickerView.h
+// ZJPickerView <https://github.com/Abnerzj/ZJPickerView>
+//
+// Created by Abnerzj on 2018/1/12.
+// Copyright 漏 2017骞� Abnerzj. All rights reserved.
+//
+// This source code is licensed under the MIT-style license found in the
+// LICENSE file in the root directory of this source tree.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ZJPickerView : UIView
+
+#pragma mark - Customization
+
+// content: NSString type
+extern NSString * _Nonnull const ZJPickerViewPropertyCanceBtnTitleKey; // cance button Title锛堝彇娑堟寜閽級
+extern NSString * _Nonnull const ZJPickerViewPropertySureBtnTitleKey; // sure button Title锛堢‘瀹氭寜閽級
+extern NSString * _Nonnull const ZJPickerViewPropertyTipLabelTextKey; // tipLabel text锛堥�夋嫨鎻愮ず鏍囩锛宼ips: When multi component, recommended the selected content be separated by commas. 閲嶈鎻愮ず锛氬鍒楁椂寤鸿宸查�夋嫨鐨勫唴瀹圭敤鑻辨枃閫楀彿闅斿紑锛屽弬鑰僠ZJPickerViewPropertyIsDividedSelectContentKey`杩欎釜key锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyDividedSymbolKey; // divided symbol, default commas 锛堥�変腑鍐呭鐨勫垎闅旂锛岄粯璁よ嫳鏂囬�楀彿锛�
+
+// color: UIColor type
+extern NSString * _Nonnull const ZJPickerViewPropertyCanceBtnTitleColorKey; // cance button Title color锛堝彇娑堟寜閽枃瀛楅鑹诧級
+extern NSString * _Nonnull const ZJPickerViewPropertySureBtnTitleColorKey; // sure button Title color锛堢‘瀹氭寜閽枃瀛楅鑹诧級
+extern NSString * _Nonnull const ZJPickerViewPropertyTipLabelTextColorKey; // tipLabel text color锛堥�夋嫨鎻愮ず鏍囩鏂囧瓧棰滆壊锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyLineViewBackgroundColorKey; // lineView backgroundColor锛堥《閮ㄥ伐鍏锋潯鍒嗗壊绾胯儗鏅鑹诧級
+
+// font: UIFont type
+extern NSString * _Nonnull const ZJPickerViewPropertyCanceBtnTitleFontKey; // cance button label font, default 17.0f锛堝彇娑堟寜閽瓧浣撳ぇ灏忥級
+extern NSString * _Nonnull const ZJPickerViewPropertySureBtnTitleFontKey; // sure button label font, default 17.0f锛堢‘瀹氭寜閽瓧浣撳ぇ灏忥級
+extern NSString * _Nonnull const ZJPickerViewPropertyTipLabelTextFontKey; // tipLabel font, default 17.0f锛堥�夋嫨鎻愮ず鏍囬瀛椾綋澶у皬锛�
+
+// pickerView:
+// CGFloat type
+extern NSString * _Nonnull const ZJPickerViewPropertyPickerViewHeightKey; // pickerView height, default 224 pt锛坧ickerView楂樺害锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyOneComponentRowHeightKey; // one component row height, default 32 pt锛坧ickerView涓�琛岀殑楂樺害锛�
+// NSDictionary type
+extern NSString * _Nonnull const ZJPickerViewPropertySelectRowTitleAttrKey; // select row titlt attribute锛坧ickerView褰撳墠閫変腑鐨勬枃瀛楅鑹诧級
+extern NSString * _Nonnull const ZJPickerViewPropertyUnSelectRowTitleAttrKey; // unSelect row titlt attribute锛坧ickerView褰撳墠娌℃湁閫変腑鐨勬枃瀛楅鑹诧級
+// UIColor type
+extern NSString * _Nonnull const ZJPickerViewPropertySelectRowLineBackgroundColorKey; // select row top and bottom line backgroundColor锛堥�変腑琛岄《閮ㄥ拰搴曢儴鍒嗗壊绾胯儗鏅鑹诧級
+
+// other:
+// BOOL type
+extern NSString * _Nonnull const ZJPickerViewPropertyIsTouchBackgroundHideKey; // touch background is hide, default NO锛堟槸鍚︾偣鍑昏儗鏅殣钘忥級
+extern NSString * _Nonnull const ZJPickerViewPropertyIsShowTipLabelKey; // is show tipLabel, default NO. note: if the value of this key`ZJPickerViewPropertyIsShowSelectContentKey` is YES, the value of ZJPickerViewPropertyIsShowTipLabelKey is ignored.锛堟槸鍚︽樉绀烘彁绀烘爣绛俱�傛敞鎰忥紝濡傛灉杩欎釜key`ZJPickerViewPropertyIsShowSelectContentKey`鐨勫�间负YES锛屽拷鐣JPickerViewPropertyIsShowTipLabelKey鐨勫�硷級
+extern NSString * _Nonnull const ZJPickerViewPropertyIsShowSelectContentKey; // scroll component is update and show select content in tipLabel, default NO锛堥�夋嫨鍐呭鍚庢槸鍚︽洿鏂伴�夋嫨鎻愮ず鏍囩锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyIsScrollToSelectedRowKey; // when pickerView will show scroll to selected row, default NO. note:`ZJPickerViewPropertyTipLabelTextKey` Must pass by value锛堝皢瑕佹樉绀烘椂鏄惁婊氬姩鍒板凡閫夋嫨鍐呭閭d竴琛岋紝娉ㄦ剰锛岄�夋嫨鎻愮ず鏍囩tipLabel蹇呴』浼犲唴瀹癸紝姣斿涔嬪墠閫夋嫨浜哷鍖椾含`锛屾鏃跺氨闇�瑕佷紶鍏鍖椾含`锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyIsDividedSelectContentKey; // the select content is divided by comma symbol when pickerView before show, use string matching for every component if value is nil, default NO.锛坧ickerView鏄剧ず鍓嶏紝宸查�夋嫨鐨勫唴瀹规槸鍚﹀凡鐢ㄩ�楀彿闅斿紑锛岄粯璁ょ敤閫夋嫨鐨勫唴瀹瑰瓧绗︿覆鍘诲尮閰嶆瘡涓�鍒楅�変腑鐨勫唴瀹癸紝濡傛灉姣忎竴鍒楅�変腑鐨勫唴瀹瑰瓨鍦ㄧ浉浼硷紝浼氶�犳垚婊氬姩鍒伴�夋嫨鐨勯偅涓�琛屽嚭鐜伴棶棰樸�傛瘮濡傦紝鎬诲叡鏈変袱鍒楋紝閫夋嫨鐨勫唴瀹规槸锛歚8.2,8.2`锛岀涓�鍒楅�夋嫨鐨勫唴瀹筦8.2`鍦ㄧ储寮�2鐨勪綅缃紝绗簩鍒楅�夋嫨鐨勫唴瀹筦8.2`鍦ㄧ储寮�4鐨勪綅缃紝杩欎釜鏃跺�欏鏋滅敤榛樿鐨勫尮閰嶈鍒欙紝鍒欐瘡涓�鍒楀湪婊氬姩鍒板凡閫夋嫨閭d竴琛屾椂锛岄兘鍙細婊氬姩鍒扮储寮曚负2涔嬪锛�
+extern NSString * _Nonnull const ZJPickerViewPropertyIsAnimationShowKey; // show pickerView is need Animation, default YES锛堟樉绀簆ickerView鏃舵槸鍚﹀甫鍔ㄧ敾鏁堟灉锛�
+// CGFloat type
+extern NSString * _Nonnull const ZJPickerViewPropertyBackgroundAlphaKey; // background alpha, default 0.5(0.0~1.0)锛堣儗鏅鍥鹃�忔槑搴︼級
+
+extern NSString * _Nonnull const ZJPickerViewPropertyDefaultSelectedIndexKey; //浼犲叆榛樿閫変腑绱㈠紩
+
+
+/**
+ Show pickerView锛堟樉绀簆ickerView锛�
+
+ @param dataList Must pass by value锛� if not show. The object type of list is support NSString銆丯SNumber锛坆asic data type锛夈�丯SDictionary锛堜紶鍏ョ殑鏁版嵁锛屽繀浼狅紝鍚﹀垯涓嶆樉绀猴級
+ @param propertyDict Custom property, user default config if value is nil锛堣嚜瀹氫箟灞炴�у弬鏁帮紝濡傛灉浼犵┖鍒欑敤榛樿閰嶇疆锛�
+ @param completion Click sure button callback锛堢偣鍑荤‘瀹氭寜閽椂鍥炶皟锛�
+ */
++ (void)zj_showWithDataList:(nonnull NSArray *)dataList
+ propertyDict:(nullable NSDictionary *)propertyDict
+ completion:(nullable void(^)(NSInteger, NSInteger, NSInteger))completion;
+
+/*
+ *2019-09-12 鏂板鏀寔涓嶈仈鍔ㄦ晥鏋�
+ */
++ (void)zj_showWithDataListWithNotLinked:(nonnull NSArray *)dataList
+ mSecondList:(nonnull NSArray *)mSecondLis
+ mThirdList:(nullable NSArray *)mThirdList
+ propertyDict:(nullable NSDictionary *)propertyDict
+ completion:(nullable void(^)(NSInteger, NSInteger, NSInteger))completion;
+@end
diff --git a/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.m b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.m
new file mode 100755
index 0000000..20b13d9
--- /dev/null
+++ b/iOS/HDLWidgetLibrary/HDLWidgetLibrary/ZJPickerView/ZJPickerView.m
@@ -0,0 +1,891 @@
+//
+// ZJPickerView.m
+// ZJPickerView <https://github.com/Abnerzj/ZJPickerView>
+//
+// Created by Abnerzj on 2018/1/12.
+// Copyright 漏 2017骞� Abnerzj. All rights reserved.
+//
+// This source code is licensed under the MIT-style license found in the
+// LICENSE file in the root directory of this source tree.
+//
+
+#import "ZJPickerView.h"
+#import "HDLUtlisXM.h"
+
+// content: NSString type
+NSString * const ZJPickerViewPropertyCanceBtnTitleKey = @"ZJPickerViewPropertyCanceBtnTitleKey";
+NSString * const ZJPickerViewPropertySureBtnTitleKey = @"ZJPickerViewPropertySureBtnTitleKey";
+NSString * const ZJPickerViewPropertyTipLabelTextKey = @"ZJPickerViewPropertyTipLabelTextKey";
+NSString * const ZJPickerViewPropertyDividedSymbolKey = @"ZJPickerViewPropertyDividedSymbolKey";
+
+// color: UIColor type
+NSString * const ZJPickerViewPropertyCanceBtnTitleColorKey = @"ZJPickerViewPropertyCanceBtnTitleColorKey";
+NSString * const ZJPickerViewPropertySureBtnTitleColorKey = @"ZJPickerViewPropertySureBtnTitleColorKey";
+NSString * const ZJPickerViewPropertyTipLabelTextColorKey = @"ZJPickerViewPropertyTipLabelTextColorKey";
+NSString * const ZJPickerViewPropertyLineViewBackgroundColorKey = @"ZJPickerViewPropertyLineViewBackgroundColorKey";
+
+// font: UIFont type
+NSString * const ZJPickerViewPropertyCanceBtnTitleFontKey = @"ZJPickerViewPropertyCanceBtnTitleFontKey";
+NSString * const ZJPickerViewPropertySureBtnTitleFontKey = @"ZJPickerViewPropertySureBtnTitleFontKey";
+NSString * const ZJPickerViewPropertyTipLabelTextFontKey = @"ZJPickerViewPropertyTipLabelTextFontKey";
+
+// pickerView:
+// CGFloat type
+NSString * const ZJPickerViewPropertyPickerViewHeightKey = @"ZJPickerViewPropertyPickerViewHeightKey";
+NSString * const ZJPickerViewPropertyOneComponentRowHeightKey = @"ZJPickerViewPropertyOneComponentRowHeightKey";
+// NSDictionary type
+NSString * const ZJPickerViewPropertySelectRowTitleAttrKey = @"ZJPickerViewPropertySelectRowTitleAttrKey";
+NSString * const ZJPickerViewPropertyUnSelectRowTitleAttrKey = @"ZJPickerViewPropertyUnSelectRowTitleAttrKey";
+// UIColor type
+NSString * const ZJPickerViewPropertySelectRowLineBackgroundColorKey = @"ZJPickerViewPropertySelectRowLineBackgroundColorKey";
+
+// other:
+// BOOL type
+NSString * const ZJPickerViewPropertyIsTouchBackgroundHideKey = @"ZJPickerViewPropertyIsTouchBackgroundHideKey";
+NSString * const ZJPickerViewPropertyIsShowTipLabelKey = @"ZJPickerViewPropertyIsShowTipLabelKey";
+NSString * const ZJPickerViewPropertyIsShowSelectContentKey = @"ZJPickerViewPropertyIsShowSelectContentKey";
+NSString * const ZJPickerViewPropertyIsScrollToSelectedRowKey = @"ZJPickerViewPropertyIsScrollToSelectedRowKey";
+NSString * const ZJPickerViewPropertyIsDividedSelectContentKey = @"ZJPickerViewPropertyIsDividedSelectContentKey";
+NSString * const ZJPickerViewPropertyIsAnimationShowKey = @"ZJPickerViewPropertyIsAnimationShowKey";
+// CGFloat type
+NSString * const ZJPickerViewPropertyBackgroundAlphaKey = @"ZJPickerViewPropertyBackgroundAlphaKey";
+
+//2019-09-05
+NSString * const ZJPickerViewPropertyDefaultSelectedIndexKey = @"ZJPickerViewPropertyDefaultSelectedIndexKey";
+
+
+static const CGFloat toolViewHeight = 44.0f; // tool view height
+static const CGFloat canceBtnWidth = 68.0f; // cance button or sure button height
+static NSString * const kDividedSymbol = @","; // divided symbol
+
+@interface ZJPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
+
+// property
+@property (nonatomic, strong) NSMutableArray *dataList; // data list
+@property (nonatomic, strong) NSMutableArray *mSecondDataList; // 浜岀骇 list
+@property (nonatomic, strong) NSMutableArray *mThirdDataList; // 涓夌骇 list
+
+
+@property (nonatomic, strong) NSMutableDictionary *propertyDict; // property dictionary
+
+// pickerView
+@property (nonatomic, assign) NSUInteger component; // component numbers, default 0
+@property (nonatomic, assign) CGFloat pickerViewHeight; // pickerView height, default 224 pt
+@property (nonatomic, assign) CGFloat oneComponentRowHeight; // one component row height, default 32 pt
+@property (nonatomic, strong) NSDictionary *selectRowTitleAttribute; // select row titlt attribute
+@property (nonatomic, strong) NSDictionary *unSelectRowTitleAttribute; // unSelect row titlt attribute
+@property (nonatomic, strong) UIColor *selectRowLineBackgroundColor; // select row top and bottom line backgroundColor
+@property (nonatomic, copy) NSString *dividedSymbol; // divided symbol, default commas
+
+@property (nonatomic, assign) BOOL isTouchBackgroundHide; // touch background is hide, default NO
+@property (nonatomic, assign) BOOL isShowTipLabel; // is show tipLabel, default NO.
+@property (nonatomic, assign) BOOL isShowSelectContent; // scroll component is update and show select content in tipLabel, default NO
+@property (nonatomic, assign) BOOL isScrollToSelectedRow; // pickerView will show scroll to selected row, default NO
+@property (nonatomic, assign) BOOL isDividedSelectContent; // select content is divided, default NO
+@property (nonatomic, assign) BOOL isAnimationShow; // show pickerView is need Animation, default YES
+@property (nonatomic, assign) BOOL isSettedSelectRowLineBackgroundColor; // is setted select row top and bottom line backgroundColor, default NO
+@property (nonatomic, assign) CGFloat backgroundAlpha; // background alpha, default 0.5(0.0~1.0)
+//@property (nonatomic, copy) void(^completion)(NSString * _Nullable selectContent); // select content
+@property (nonatomic, copy) void(^completion)(NSInteger, NSInteger, NSInteger); //2019-09-05 select content
+
+// subviews
+@property (nonatomic, strong) UIView *backgroundView;
+@property (nonatomic, strong) UIView *contentView;
+@property (nonatomic, strong) UIPickerView *pickerView;
+@property (nonatomic, strong) UIButton *canceBtn;
+@property (nonatomic, strong) UIButton *sureBtn;
+@property (nonatomic, strong) UILabel *tipLabel;
+@property (nonatomic, strong) UIView *lineView;
+
+//2019-9-5 鏂板榛樿閫夋嫨椤癸紝鍜屽洖璋冮�変腑鐨勭储寮�
+@property (nonatomic, assign) NSInteger selectIndex1;
+@property (nonatomic, assign) NSInteger selectIndex2;
+@property (nonatomic, assign) NSInteger selectIndex3;
+@property (nonatomic, strong) UIColor *btnColor;
+
+@property (nonatomic, assign) BOOL isLinked; //鏄惁涓嶈仈鍔�
+
+@end
+
+@implementation ZJPickerView
+
++ (ZJPickerView *)sharedView {
+ static dispatch_once_t once;
+ static ZJPickerView *sharedView;
+ dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; });
+ return sharedView;
+}
+
+#pragma mark - Instance Methods
+- (instancetype)initWithFrame:(CGRect)frame {
+ if((self = [super initWithFrame:frame])) {
+ [self initDefaultConfig];
+ self.dataList = [NSMutableArray array];
+ self.mSecondDataList = [NSMutableArray array];
+ self.mThirdDataList = [NSMutableArray array];
+ self.propertyDict = [NSMutableDictionary dictionary];
+ [self initSubViews];
+ }
+ return self;
+}
+
+- (void)initDefaultConfig
+{
+
+ self.isLinked = YES;
+ self.selectIndex1 = 0;
+ self.selectIndex2 = 0;
+ self.selectIndex3 = 0;
+ self.component = 0;
+ self.pickerViewHeight = 224.0f;
+ self.oneComponentRowHeight = 32.0f;
+ self.selectRowTitleAttribute = @{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.unSelectRowTitleAttribute = @{NSForegroundColorAttributeName : [UIColor lightGrayColor], NSFontAttributeName : [UIFont systemFontOfSize:20.0f]};
+ self.selectRowLineBackgroundColor = [UIColor colorWithRed:222.0/255.0 green:222.0/255.0 blue:222.0/255.0 alpha:1.0];
+ self.btnColor = [UIColor colorWithRed:255.0/255.0 green:87.0/255.0 blue:34.0/255.0 alpha:1.0];
+ self.dividedSymbol = kDividedSymbol;
+
+ self.isTouchBackgroundHide = NO;
+ self.isShowTipLabel = NO;
+ self.isShowSelectContent = NO;
+ self.isScrollToSelectedRow = NO;
+ self.isDividedSelectContent = NO;
+ self.isAnimationShow = YES;
+ self.isSettedSelectRowLineBackgroundColor = NO;
+ self.backgroundAlpha = 0.5f;
+}
+
+-(void)setRadiusWithView:(UIView *)mView{
+ //椤堕儴鍦嗚
+ UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;
+ if (@available(iOS 11.0, *)) {
+ mView.layer.cornerRadius = 20;
+ mView.layer.maskedCorners = (CACornerMask)corners; // 宸︿笂鍦嗚
+ }else{
+ UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:mView.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(20,20)];
+ //鍒涘缓 layer
+ CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
+ maskLayer.frame = mView.bounds;
+ //璧嬪��
+ maskLayer.path = maskPath.CGPath;
+ mView.layer.mask = maskLayer;
+ }
+}
+
+
+- (void)initSubViews
+{
+ // background view
+ UIView *backgroundView = [[UIView alloc] initWithFrame:self.bounds];
+ backgroundView.backgroundColor = [UIColor blackColor];
+ backgroundView.alpha = self.backgroundAlpha;
+ [self addSubview:backgroundView];
+
+ // add tap Gesture
+ UITapGestureRecognizer *tapbgGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchBackgroundView)];
+ [backgroundView addGestureRecognizer:tapbgGesture];
+
+ // content view
+ UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - toolViewHeight - self.pickerViewHeight, self.frame.size.width, toolViewHeight + self.pickerViewHeight)];
+ contentView.backgroundColor = [UIColor whiteColor];
+ [self setRadiusWithView:contentView];
+ [self addSubview:contentView];
+
+ // tool view
+ UIView *toolView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, toolViewHeight)];
+ toolView.backgroundColor = [UIColor whiteColor];
+ [self setRadiusWithView:toolView];
+ [contentView addSubview:toolView];
+
+ // UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 1)];
+ // lineView.backgroundColor = [UIColor lightGrayColor];
+ // [contentView addSubview:lineView];
+ //
+ // cance button
+ NSArray *diffLanguageTitles = [self getDiffLanguageCanceAndSureBtnTitles];
+ UIButton *canceBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+ canceBtn.frame = CGRectMake(0, 0, canceBtnWidth, toolView.frame.size.height);
+ [canceBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
+ [canceBtn setTitle:diffLanguageTitles.firstObject forState:UIControlStateNormal];
+ // [canceBtn.titleLabel setFont:[UIFont systemFontOfSize:17.0]];
+ canceBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:14];
+ [canceBtn setTag:0];
+ [canceBtn addTarget:self action:@selector(userAction:) forControlEvents:UIControlEventTouchUpInside];
+ [toolView addSubview:canceBtn];
+
+ // sure button
+ UIButton *sureBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+ sureBtn.frame = CGRectMake(toolView.frame.size.width - canceBtnWidth, 0, canceBtnWidth, toolView.frame.size.height);
+ [sureBtn setTitleColor:self.btnColor forState:UIControlStateNormal];
+ [sureBtn setTitle:diffLanguageTitles.lastObject forState:UIControlStateNormal];
+ // [sureBtn.titleLabel setFont:[UIFont systemFontOfSize:17.0]];
+ sureBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:14];
+ [sureBtn setTag:1];
+ [sureBtn addTarget:self action:@selector(userAction:) forControlEvents:UIControlEventTouchUpInside];
+ [toolView addSubview:sureBtn];
+
+ // center title
+ UILabel *tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(canceBtn.frame.size.width, 0, toolView.frame.size.width - canceBtn.frame.size.width*2, toolView.frame.size.height)];
+ tipLabel.text = @"";
+ tipLabel.textColor = [UIColor darkTextColor];
+ // tipLabel.font = [UIFont systemFontOfSize:17.0];
+ tipLabel.font = [UIFont fontWithName:APP_UIFont size:16];
+ tipLabel.textAlignment = NSTextAlignmentCenter;
+ tipLabel.hidden = !self.isShowTipLabel;
+ [toolView addSubview:tipLabel];
+
+ // line view
+ UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, toolView.frame.size.height - 0.5f, self.frame.size.width, 0.5f)];
+ lineView.backgroundColor = [UIColor colorWithRed:222.0/255.0 green:222.0/255.0 blue:222.0/255.0 alpha:1.0];
+ [toolView addSubview:lineView];
+
+ // pickerView
+ UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, toolView.frame.size.height, self.frame.size.width, self.pickerViewHeight)];
+ pickerView.dataSource = self;
+ pickerView.delegate = self;
+ [contentView addSubview:pickerView];
+
+ // global variable
+ self.backgroundView = backgroundView;
+ self.contentView = contentView;
+ self.canceBtn = canceBtn;
+ self.sureBtn = sureBtn;
+ self.lineView = lineView;
+ self.tipLabel = tipLabel;
+ self.pickerView = pickerView;
+}
+
+#pragma mark - UIPickerView DataSource & Delegate
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+ // if(self.isLinked){
+ // return self.component;
+ // }else{
+ // return 2;
+ // }
+ return self.component;
+}
+
+- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+ if(self.isLinked){
+ return [self getDataWithComponent:component].count;
+ }else{
+ return [self getDataWithComponentNoLinked:component].count;
+ }
+}
+
+- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ NSArray *componentArray;
+ if(self.isLinked){
+ componentArray = [self getDataWithComponent:component];
+ }else{
+ componentArray = [self getDataWithComponentNoLinked:component];
+ }
+
+ if (componentArray.count) {
+ if (row < componentArray.count) {
+ id titleData = componentArray[row];
+ if ([titleData isKindOfClass:[NSString class]]) {
+ return titleData;
+ } else if ([titleData isKindOfClass:[NSNumber class]]) {
+ return [NSString stringWithFormat:@"%@", titleData];
+ }
+ }
+ }
+ return @"";
+}
+
+- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+ if(self.isLinked){
+ if(component == 0){
+ self.selectIndex1 = row;
+ self.selectIndex2 = 0;
+ }else if(component == 1){
+ self.selectIndex2 = row;
+ self.selectIndex3 = 0;
+ }else if(component == 2){
+ self.selectIndex3 = row;
+ }
+ NSLog(@"component:%ld row: %ld",(long)component,(long)row);
+ [pickerView reloadAllComponents];
+ for (NSUInteger i = 0; i < self.component; i++) {
+ if (i > component) {
+ [pickerView selectRow:0 inComponent:i animated:YES];
+ }
+ }
+ }else{
+ // [pickerView selectRow:row inComponent:component animated:YES];
+ if(component == 0){
+ self.selectIndex1 = row;
+
+ }else if(component == 1){
+ self.selectIndex2 = row;
+ }else if(component == 2){
+ self.selectIndex3 = row;
+ }
+ }
+
+
+ // // show select content
+ // NSMutableString *selectString = [[NSMutableString alloc] init];
+
+ // reload all component and scroll to top for sub component
+ // [pickerView reloadAllComponents];
+ // for (NSUInteger i = 0; i < self.component; i++) {
+ // if (i > component) {
+ // [pickerView selectRow:0 inComponent:i animated:YES];
+ // }
+ //
+ // if (self.isShowSelectContent) {
+ // [selectString appendString:[self pickerView:pickerView titleForRow:[pickerView selectedRowInComponent:i] forComponent:i]];
+ // if (i == self.component - 1) {
+ // self.tipLabel.text = selectString;
+ // }
+ // }
+ // }
+}
+
+- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
+{
+ return self.oneComponentRowHeight;
+}
+
+- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
+{
+ // set separateline color
+ if (NO == self.isSettedSelectRowLineBackgroundColor) {
+ UIView *topSeparateLine = [pickerView.subviews objectAtIndex:1];
+ UIView *bottomSeparateLine = [pickerView.subviews objectAtIndex:2];
+ if (topSeparateLine.frame.size.height < 1.0f &&
+ bottomSeparateLine.frame.size.height < 1.0f) {
+ topSeparateLine.backgroundColor = self.selectRowLineBackgroundColor;
+ bottomSeparateLine.backgroundColor = self.selectRowLineBackgroundColor;
+ self.isSettedSelectRowLineBackgroundColor = YES;
+ } else {
+ for (UIView *singleLine in pickerView.subviews) {
+ if (singleLine.frame.size.height < 1.0f) {
+ singleLine.backgroundColor = self.selectRowLineBackgroundColor;
+ self.isSettedSelectRowLineBackgroundColor = YES;
+ }
+ }
+ }
+ }
+
+ // custom pickerView content label
+ UILabel *pickerLabel = (UILabel *)view;
+
+ // discussion: this is always nil, not Reusing, it's an iOS System bug.
+ // reference: https://stackoverflow.com/questions/20635949/reusing-view-in-uipickerview-with-ios-7/21039321#21039321
+ if (!pickerLabel) {
+ pickerLabel = [[UILabel alloc] init];
+ pickerLabel.textAlignment = NSTextAlignmentCenter;
+ pickerLabel.adjustsFontSizeToFitWidth = YES;
+ pickerLabel.backgroundColor = [UIColor clearColor];
+ }
+ pickerLabel.attributedText = [self pickerView:pickerView attributedTitleForRow:row forComponent:component];
+
+ return pickerLabel;
+}
+//
+- (nullable NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+ // NSString *normalRowString = [self pickerView:pickerView titleForRow:row forComponent:component];
+ // NSString *selectRowString = [self pickerView:pickerView titleForRow:[pickerView selectedRowInComponent:component] forComponent:component];
+ //
+ // NSLog(@"selectedRowInComponent ROW :%ld selectRowString:%@", [pickerView selectedRowInComponent:component],selectRowString);
+ // if (row == [pickerView selectedRowInComponent:component]) {
+ // return [[NSAttributedString alloc] initWithString:selectRowString attributes:self.selectRowTitleAttribute];
+ // } else {
+ // return [[NSAttributedString alloc] initWithString:normalRowString attributes:self.unSelectRowTitleAttribute];
+ // }
+ //
+ NSString *normalRowString = [self pickerView:pickerView titleForRow:row forComponent:component];
+ return [[NSAttributedString alloc] initWithString:normalRowString attributes:self.selectRowTitleAttribute];
+}
+
+#pragma mark click cance/sure button
+- (void)userAction:(UIButton *)sender
+{
+ // hide
+ [self zj_hide];
+ // click sure
+ if (sender.tag == 1) {
+ // completion callback
+ if (self.completion) {
+ self.completion(self.selectIndex1, self.selectIndex2, self.selectIndex3);
+ }
+ }
+}
+
+#pragma mark touch backgroundView
+- (void)touchBackgroundView
+{
+ if (self.isTouchBackgroundHide) {
+ [self zj_hide];
+ }
+}
+
+#pragma mark - show & hide method
++ (void)zj_showWithDataList:(nonnull NSArray *)dataList
+ propertyDict:(nullable NSDictionary *)propertyDict
+ completion:(nullable void(^)(NSInteger, NSInteger, NSInteger))completion
+{
+ // no data
+ if (!dataList || dataList.count == 0) {
+ return;
+ }
+
+
+ NSDictionary *propertyDict1 = @{
+ // ZJPickerViewPropertyCanceBtnTitleKey : @"",
+ ZJPickerViewPropertyIsTouchBackgroundHideKey : @YES,
+ ZJPickerViewPropertyIsShowSelectContentKey : @YES,
+ ZJPickerViewPropertyIsScrollToSelectedRowKey: @YES,
+ ZJPickerViewPropertyIsAnimationShowKey : @YES,
+
+ };
+
+ // handle data
+ [[self sharedView] initDefaultConfig];
+ [self sharedView].tipLabel.text = @"";
+ [[self sharedView].dataList removeAllObjects];
+ [[self sharedView].dataList addObjectsFromArray:dataList];
+ [[self sharedView].propertyDict removeAllObjects];
+ [[self sharedView].propertyDict addEntriesFromDictionary:propertyDict];
+ [[self sharedView].propertyDict addEntriesFromDictionary:propertyDict1];
+ [[self sharedView] updateCustomProperiesSetter];
+
+ // calculate component num
+ id data = dataList.firstObject;
+ if ([data isKindOfClass:[NSString class]] ||
+ [data isKindOfClass:[NSNumber class]] ) {
+ [self sharedView].component = 1;
+ } else if ([data isKindOfClass:[NSDictionary class]]) {
+ [self sharedView].component++;
+ [self handleDictDataList:dataList];
+ } else {
+ NSLog(@"ZJPickerView error tip锛歕"Unsupported data type\"");
+ return;
+ }
+
+ // discussion: reload component in main queue, fix the first scroll to select line error bug.
+ // scorll all component to selectedRow/top
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[self sharedView].pickerView reloadAllComponents];
+ if ([self sharedView].isScrollToSelectedRow) {
+ [[self sharedView] scrollToSelectedRow];
+ } else {
+ for (NSUInteger i = 0; i < [self sharedView].component; i++) {
+ [[self sharedView].pickerView selectRow:0 inComponent:i animated:NO];
+ }
+ }
+ });
+
+ // complete block
+ if (completion) {
+ [self sharedView].completion = completion;
+ }
+
+ // show
+ if ([self sharedView].isAnimationShow) {
+ [[[[UIApplication sharedApplication] delegate] window] addSubview:[self sharedView]];
+
+ [self sharedView].backgroundView.alpha = 0.0f;
+
+ CGRect frame = [self sharedView].contentView.frame;
+ frame.origin.y = [self sharedView].frame.size.height;
+ [self sharedView].contentView.frame = frame;
+
+ __weak typeof(self) weakself = self;
+ [UIView animateWithDuration:0.3f animations:^{
+ CGRect frame = [weakself sharedView].contentView.frame;
+ frame.origin.y = [weakself sharedView].frame.size.height - [weakself sharedView].contentView.frame.size.height;
+ [weakself sharedView].contentView.frame = frame;
+ [weakself sharedView].backgroundView.alpha = [weakself sharedView].backgroundAlpha;
+ }];
+ } else {
+ [UIView animateWithDuration:0.3f animations:^{
+ [[[[UIApplication sharedApplication] delegate] window] addSubview:[self sharedView]];
+ }];
+ }
+}
+
+- (void)zj_hide
+{
+ __weak typeof(self) weakself = self;
+ if (self.isAnimationShow) {
+ CGRect frame = self.contentView.frame;
+ frame.origin.y = self.frame.size.height;
+ [UIView animateWithDuration:0.3f animations:^{
+ weakself.contentView.frame = frame;
+ weakself.backgroundView.alpha = 0.0f;
+ } completion:^(BOOL finished) {
+ [weakself removeFromSuperview];
+ }];
+ } else {
+ [UIView animateWithDuration:0.3f animations:^{
+ [weakself removeFromSuperview];
+ }];
+ }
+}
+
+#pragma mark - private method
++ (void)handleDictDataList:(NSArray *)list
+{
+ id data = list.firstObject;
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *dict = data;
+ id value = dict.allValues.firstObject;
+ if ([value isKindOfClass:[NSArray class]]) {
+ [self sharedView].component++;
+ [self handleDictDataList:value];
+ }
+ }
+}
+
+- (NSArray *)getDataWithComponent:(NSInteger)component
+{
+ NSMutableArray *tempArray = [NSMutableArray arrayWithArray:self.dataList];
+ NSMutableArray *arrayM = [NSMutableArray array];
+ for (NSInteger i = 0; i <= component; i++) {
+ if (i == component) {
+ id data = tempArray.firstObject;
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ NSMutableArray *tempTitleArray = [NSMutableArray arrayWithArray:tempArray];
+ [tempArray removeAllObjects];
+ [tempTitleArray enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL * _Nonnull stop) {
+ [tempArray addObjectsFromArray:dict.allKeys];
+ }];
+ [arrayM addObjectsFromArray:tempArray];
+ } else if ([data isKindOfClass:[NSString class]] ||
+ [data isKindOfClass:[NSNumber class]]){
+ [arrayM addObjectsFromArray:tempArray];
+ }
+ } else {
+ NSInteger selectRow = [self.pickerView selectedRowInComponent:i];
+ if (selectRow < tempArray.count) {
+ id data = tempArray[selectRow];
+ if ([data isKindOfClass:[NSDictionary class]]) {
+ [tempArray removeAllObjects];
+ NSDictionary *dict = data;
+ [dict.allValues enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ if ([obj isKindOfClass:[NSArray class]]) {
+ [tempArray addObjectsFromArray:obj];
+ } else {
+ [tempArray addObject:obj];
+ }
+ }];
+ }
+ }
+ }
+ }
+ return arrayM;
+}
+
+- (NSArray *)getDataWithComponentNoLinked:(NSInteger)component
+{
+ // NSMutableArray *arrayM = [NSMutableArray array];
+ if(component == 0){
+ return self.dataList;
+ }else if(component == 1){
+ return self.mSecondDataList;
+ }else if(component == 2){
+ return self.mThirdDataList;
+ }else{
+ NSMutableArray *arrayM = [NSMutableArray array];
+ return arrayM;
+ }
+}
+
+
+
+#pragma mark update property
+- (void)updateCustomProperiesSetter
+{
+ [self.propertyDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
+ if (obj) {
+ if ([key isEqualToString:ZJPickerViewPropertyCanceBtnTitleKey]) {
+ [self.canceBtn setTitle:obj forState:UIControlStateNormal];
+ } else if ([key isEqualToString:ZJPickerViewPropertySureBtnTitleKey]) {
+ [self.sureBtn setTitle:obj forState:UIControlStateNormal];
+ } else if ([key isEqualToString:ZJPickerViewPropertyTipLabelTextKey]) {
+ self.tipLabel.text = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyDividedSymbolKey]) {
+ self.dividedSymbol = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyCanceBtnTitleColorKey]) {
+ [self.canceBtn setTitleColor:obj forState:UIControlStateNormal];
+ } else if ([key isEqualToString:ZJPickerViewPropertySureBtnTitleColorKey]) {
+ [self.sureBtn setTitleColor:obj forState:UIControlStateNormal];
+ } else if ([key isEqualToString:ZJPickerViewPropertyTipLabelTextColorKey]) {
+ self.tipLabel.textColor = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyLineViewBackgroundColorKey]) {
+ self.lineView.backgroundColor = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyCanceBtnTitleFontKey]) {
+ [self.canceBtn.titleLabel setFont:obj];
+ } else if ([key isEqualToString:ZJPickerViewPropertySureBtnTitleFontKey]) {
+ [self.sureBtn.titleLabel setFont:obj];
+ } else if ([key isEqualToString:ZJPickerViewPropertyTipLabelTextFontKey]) {
+ [self.tipLabel setFont:obj];
+ } else if ([key isEqualToString:ZJPickerViewPropertyPickerViewHeightKey]) {
+ self.pickerViewHeight = [obj floatValue];
+ CGRect frame = self.pickerView.frame;
+ frame.size.height = self.pickerViewHeight;
+ self.pickerView.frame = frame;
+
+ frame = self.contentView.frame;
+ frame.size.height = toolViewHeight + self.pickerViewHeight;
+ frame.origin.y = self.frame.size.height - frame.size.height;
+ self.contentView.frame = frame;
+ } else if ([key isEqualToString:ZJPickerViewPropertyOneComponentRowHeightKey]) {
+ self.oneComponentRowHeight = [obj floatValue];
+ } else if ([key isEqualToString:ZJPickerViewPropertySelectRowTitleAttrKey]) {
+ self.selectRowTitleAttribute = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyUnSelectRowTitleAttrKey]) {
+ self.unSelectRowTitleAttribute = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertySelectRowLineBackgroundColorKey]) {
+ self.selectRowLineBackgroundColor = obj;
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsTouchBackgroundHideKey]) {
+ self.isTouchBackgroundHide = [obj boolValue];
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsShowTipLabelKey]) {
+ self.isShowTipLabel = [obj boolValue]; // NO
+ self.tipLabel.hidden = self.isShowSelectContent ? NO : !self.isShowTipLabel;
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsShowSelectContentKey]) {
+ self.isShowSelectContent = [obj boolValue]; // NO
+ if (self.isShowSelectContent) {
+ self.tipLabel.hidden = NO;
+ }
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsScrollToSelectedRowKey]) {
+ self.isScrollToSelectedRow = [obj boolValue];
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsDividedSelectContentKey]) {
+ self.isDividedSelectContent = [obj boolValue];
+ } else if ([key isEqualToString:ZJPickerViewPropertyBackgroundAlphaKey]) {
+ self.backgroundAlpha = [obj floatValue];
+ self.backgroundView.alpha = self.backgroundAlpha;
+ } else if ([key isEqualToString:ZJPickerViewPropertyIsAnimationShowKey]) {
+ self.isAnimationShow = [obj boolValue];
+ } else if ([key isEqualToString:ZJPickerViewPropertyDefaultSelectedIndexKey]) {
+
+ NSArray *array = [obj componentsSeparatedByString:@"-"]; //鍒嗗壊鏁扮粍
+ if(array.count == 1){
+ self.selectIndex1 = [array[0] intValue];
+ }else if(array.count == 2){
+ self.selectIndex1 = [array[0] intValue];
+ self.selectIndex2 = [array[1] intValue];
+ }else if(array.count == 3){
+ self.selectIndex1 = [array[0] intValue];
+ self.selectIndex2 = [array[1] intValue];
+ self.selectIndex3 = [array[2] intValue];
+ }
+ }
+ }
+ }];
+}
+
+/*
+ * 2019-09-05 鏍规嵁绱㈠紩閫変腑锛屾浛鎹㈠師鏉ユ牴鎹紶鍏ュ瓧绗﹂�変腑鏂规
+ */
+- (void)scrollToSelectedRow
+{
+ for (NSUInteger i = 0; i < self.component; i++) {
+ if(i == 0){
+ [self.pickerView selectRow:self.selectIndex1 inComponent:i animated:NO];
+ }else if(i == 1){
+ [self.pickerView selectRow:self.selectIndex2 inComponent:i animated:NO];
+ }else if(i == 2){
+ [self.pickerView selectRow:self.selectIndex3 inComponent:i animated:NO];
+ }
+
+ }
+}
+
+//- (void)scrollToSelectedRow
+//{
+//
+//
+// for (NSUInteger i = 0; i < self.component; i++) {
+// if(i == 0){
+// [self.pickerView selectRow:self.selectIndex1 inComponent:i animated:NO];
+// }else if(i == 1){
+// [self.pickerView selectRow:self.selectIndex2 inComponent:i animated:NO];
+// }else if(i == 2){
+// [self.pickerView selectRow:self.selectIndex3 inComponent:i animated:NO];
+// }
+//
+// }
+//
+// NSString *selectedContent = self.propertyDict[ZJPickerViewPropertyTipLabelTextKey];
+// NSMutableArray *selectContentList = [NSMutableArray arrayWithCapacity:self.component];
+// if (self.isDividedSelectContent) {
+// // reference: https://github.com/Abnerzj/ZJPickerView/issues/8
+// NSArray *tempSelectContentList = [selectedContent componentsSeparatedByString:self.dividedSymbol];
+// if (tempSelectContentList && tempSelectContentList.count == self.component) {
+// [selectContentList addObjectsFromArray:tempSelectContentList];
+// }
+// }
+// if (selectedContent.length && ![selectedContent isEqualToString:@""]) {
+// __weak typeof(self) weakself = self;
+// NSMutableArray *tempSelectedRowArray = [NSMutableArray arrayWithCapacity:self.component];
+// for (NSUInteger i = 0; i < self.component; i++) {
+// NSArray *componentArray = [self getDataWithComponent:i];
+// if (componentArray.count) {
+// [componentArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) {
+// NSString *title = @"";
+// if ([obj isKindOfClass:[NSString class]]) {
+// title = obj;
+// } else if ([obj isKindOfClass:[NSNumber class]]) {
+// title = [obj stringValue];
+// }
+// if (![title isEqualToString:@""]) {
+// BOOL isCanScrollToSelectePosition = NO;
+// if (selectContentList.count > 0) {
+// isCanScrollToSelectePosition = [selectContentList[i] isEqualToString:title];
+// } else {
+// // discussion: scroll to select row error when solving content similar, only appear when there is only one component.
+// // reference: https://github.com/Abnerzj/ZJPickerView/issues/4
+// // https://github.com/Abnerzj/ZJPickerView/issues/5
+// NSRange range = [selectedContent rangeOfString:title];
+// isCanScrollToSelectePosition = (self.component == 1) ? ([selectedContent isEqualToString:title]) : (range.location != NSNotFound);
+// }
+//
+// if (isCanScrollToSelectePosition) {
+// [tempSelectedRowArray addObject:@(idx)];
+// [weakself.pickerView reloadComponent:i];
+// [weakself.pickerView selectRow:idx inComponent:i animated:NO];
+// [weakself.pickerView reloadComponent:i];
+// *stop = YES;
+// }
+// }
+// }];
+// }
+// }
+//
+// if (tempSelectedRowArray.count != self.component) {
+// for (NSUInteger i = 0; i < self.component; i++) {
+// [self.pickerView selectRow:0 inComponent:i animated:NO];
+// }
+// }
+// }
+//}
+
+- (NSArray *)getDiffLanguageCanceAndSureBtnTitles
+{
+ NSString *languageName = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0];
+
+ // 绠�浣撲腑鏂�
+ if ([languageName rangeOfString:@"zh-Hans"].location != NSNotFound) {
+ return @[@"鍙栨秷", @"纭畾"];
+ }
+
+ // 绻佷綋涓枃
+ if ([languageName rangeOfString:@"zh-Hant"].location != NSNotFound) {
+ return @[@"鍙栨秷", @"纰哄畾"];
+ }
+
+ // Other language
+ return @[@"Cance", @"Sure"];
+}
+
+
+/*
+ *2019-09-12 鏂板鏀寔涓嶈仈鍔ㄦ晥鏋�
+ */
++ (void)zj_showWithDataListWithNotLinked:(nonnull NSArray *)dataList
+ mSecondList:(nonnull NSArray *)mSecondList
+ mThirdList:(nullable NSArray *)mThirdList
+ propertyDict:(nullable NSDictionary *)propertyDict
+ completion:(nullable void(^)(NSInteger, NSInteger, NSInteger))completion
+{
+ // no data
+ if (!dataList || dataList.count == 0) {
+ return;
+ }
+
+ // no data
+ if (!mSecondList || mSecondList.count == 0) {
+ return;
+ }
+
+
+
+ NSDictionary *propertyDict1 = @{
+ // ZJPickerViewPropertyCanceBtnTitleKey : @"",
+ ZJPickerViewPropertyIsTouchBackgroundHideKey : @YES,
+ ZJPickerViewPropertyIsShowSelectContentKey : @YES,
+ ZJPickerViewPropertyIsScrollToSelectedRowKey: @YES,
+ ZJPickerViewPropertyIsAnimationShowKey : @YES,
+
+ };
+
+ // handle data
+ [[self sharedView] initDefaultConfig];
+ [self sharedView].tipLabel.text = @"";
+ [[self sharedView].dataList removeAllObjects];
+ [[self sharedView].mSecondDataList removeAllObjects];
+ [[self sharedView].mThirdDataList removeAllObjects];
+ [[self sharedView].dataList addObjectsFromArray:dataList];
+ [[self sharedView].mSecondDataList addObjectsFromArray:mSecondList];
+ [[self sharedView].mThirdDataList addObjectsFromArray:mThirdList];
+ [[self sharedView].propertyDict removeAllObjects];
+ [[self sharedView].propertyDict addEntriesFromDictionary:propertyDict];
+ [[self sharedView].propertyDict addEntriesFromDictionary:propertyDict1];
+ [[self sharedView] updateCustomProperiesSetter];
+
+
+ //閰嶇疆鍏抽敭鏁版嵁
+ if (!mThirdList || mThirdList.count == 0) {
+ [self sharedView].component = 2;
+ }else{
+ [self sharedView].component = 3;
+ }
+
+ [self sharedView].isLinked = NO;
+
+
+ // discussion: reload component in main queue, fix the first scroll to select line error bug.
+ // scorll all component to selectedRow/top
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[self sharedView].pickerView reloadAllComponents];
+ if ([self sharedView].isScrollToSelectedRow) {
+ [[self sharedView] scrollToSelectedRow];
+ } else {
+ for (NSUInteger i = 0; i < [self sharedView].component; i++) {
+ [[self sharedView].pickerView selectRow:0 inComponent:i animated:NO];
+ }
+ }
+ });
+
+ // complete block
+ if (completion) {
+ [self sharedView].completion = completion;
+ }
+
+ // show
+ if ([self sharedView].isAnimationShow) {
+ [[[[UIApplication sharedApplication] delegate] window] addSubview:[self sharedView]];
+
+ [self sharedView].backgroundView.alpha = 0.0f;
+
+ CGRect frame = [self sharedView].contentView.frame;
+ frame.origin.y = [self sharedView].frame.size.height;
+ [self sharedView].contentView.frame = frame;
+
+ __weak typeof(self) weakself = self;
+ [UIView animateWithDuration:0.3f animations:^{
+ CGRect frame = [weakself sharedView].contentView.frame;
+ frame.origin.y = [weakself sharedView].frame.size.height - [weakself sharedView].contentView.frame.size.height;
+ [weakself sharedView].contentView.frame = frame;
+ [weakself sharedView].backgroundView.alpha = [weakself sharedView].backgroundAlpha;
+ }];
+ } else {
+ [UIView animateWithDuration:0.3f animations:^{
+ [[[[UIApplication sharedApplication] delegate] window] addSubview:[self sharedView]];
+ }];
+ }
+}
+
+
+
+@end
diff --git a/iOS/libHDLWidgetLibrary.a b/iOS/libHDLWidgetLibrary.a
new file mode 100644
index 0000000..186d9a9
--- /dev/null
+++ b/iOS/libHDLWidgetLibrary.a
Binary files differ
--
Gitblit v1.8.0