57个文件已添加
2个文件已删除
11个文件已修改
| | |
| | | implementation 'androidx.navigation:navigation-fragment:2.3.5' |
| | | implementation 'androidx.navigation:navigation-ui:2.3.5' |
| | | implementation 'androidx.legacy:legacy-support-v4:1.0.0' |
| | | //时间库 |
| | | implementation project(path: ':pickerview') |
| | | //图表库 |
| | | implementation project(path: ':aa_chart_core') |
| | | //国家列表和手机区号库 |
| | |
| | | implementation 'cn.jiguang.sdk:jpush-google:5.2.2' |
| | | //分析和用户标签等功能(可选,集成极光分析SDK后,即可支持行为触发推送消息、推送转化率统计,用户行为分) |
| | | implementation 'cn.jiguang.sdk:joperate:2.0.2' |
| | | |
| | | //PickerView |
| | | implementation 'com.contrarywind:Android-PickerView:4.1.9' |
| | | |
| | | |
| | | |
| | | |
| | |
| | | |
| | | import cn.jpush.android.api.JPushInterface; |
| | | import io.dcloud.common.util.RuningAcitvityUtil; |
| | | import me.jessyan.autosize.AutoSize; |
| | | import me.jessyan.autosize.AutoSizeConfig; |
| | | import me.jessyan.autosize.onAdaptListener; |
| | | import me.jessyan.autosize.utils.ScreenUtils; |
| | |
| | | @Override |
| | | public void onCreate() { |
| | | super.onCreate(); |
| | | |
| | | // 获取当前进程的PID |
| | | Log.d("进程===", android.os.Process.myPid() + ""); |
| | | mHDLApp = this; |
| | |
| | | * 旋转后高变宽,按旋转后高度适配,所以宽度不写死 |
| | | */ |
| | | private void initAutoSize() { |
| | | AutoSize.initCompatMultiProcess(this); |
| | | boolean isBaseOnWidth = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; |
| | | AutoSizeConfig.getInstance() |
| | | .setBaseOnWidth(isBaseOnWidth) |
| | | .setBaseOnWidth(true) |
| | | .setCustomFragment(true) |
| | | .setDesignWidthInDp(375) |
| | | .setDesignHeightInDp(812) |
| | | .setUseDeviceSize(false) |
| | | .setDesignWidthInDp(isBaseOnWidth ? 375 : 812) |
| | | .setDesignHeightInDp(isBaseOnWidth ? 812 : 375) |
| | | .setOnAdaptListener(new onAdaptListener() { |
| | | @Override |
| | | public void onAdaptBefore(Object target, Activity activity) { |
| | |
| | | MultiDex.install(base); |
| | | super.attachBaseContext(base); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import android.content.Intent; |
| | | import android.graphics.Color; |
| | | import android.os.Bundle; |
| | | import android.provider.Settings; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.view.WindowManager; |
| | | import android.widget.Toast; |
| | | |
| | | import androidx.appcompat.content.res.AppCompatResources; |
| | | |
| | | import com.bigkoo.pickerview.builder.TimePickerBuilder; |
| | | import com.bigkoo.pickerview.listener.OnTimeSelectListener; |
| | |
| | | import com.github.AAChartModel.AAChartCore.AAChartEnum.AAChartType; |
| | | import com.hdl.photovoltaic.R; |
| | | import com.hdl.photovoltaic.base.CustomBaseFragment; |
| | | import com.hdl.photovoltaic.config.AppConfigManage; |
| | | import com.hdl.photovoltaic.config.ConstantManage; |
| | | import com.hdl.photovoltaic.config.UserConfigManage; |
| | | import com.hdl.photovoltaic.databinding.FragmentHomePageBinding; |
| | | import com.hdl.photovoltaic.enums.HomepageTitleTabSwitch; |
| | | import com.hdl.photovoltaic.other.HdlLogLogic; |
| | | import com.hdl.photovoltaic.utils.TimeUtils; |
| | | import com.hdl.sdk.link.core.bean.eventbus.BaseEventBus; |
| | | |
| | | import org.greenrobot.eventbus.EventBus; |
| | |
| | | |
| | | FragmentHomePageBinding viewBinding; |
| | | |
| | | AAChartView aaChartView1; |
| | | AAChartView aaChartView; |
| | | |
| | | AAChartModel aaChartModel1; |
| | | AAChartView aaChartView2; |
| | | AAChartModel aaChartModel; |
| | | |
| | | AAChartModel aaChartModel2; |
| | | |
| | | private TimeType timeType = TimeType.day;//时间类型(默认:天) |
| | | |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public void onBindView(Bundle savedInstanceState) { |
| | | viewBinding.homePageStationDataTitleTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | setUpAAChartView(1); |
| | | //初始化 |
| | | initView(); |
| | | //初始化界面监听器 |
| | | initEvent(); |
| | | |
| | | } |
| | | }); |
| | | |
| | | private void initEvent() { |
| | | //时间选择器 |
| | | viewBinding.yearMonthDayTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | timeSelectedView(); |
| | | selectedTimePickerBuilder(); |
| | | |
| | | } |
| | | }); |
| | | timeSelectedView(); |
| | | // viewBinding.test2.setOnClickListener(new View.OnClickListener() { |
| | | // @Override |
| | | // public void onClick(View v) { |
| | | // setUpAAChartView(2); |
| | | // } |
| | | // }); |
| | | //日 |
| | | viewBinding.dayTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | timeType = TimeType.day; |
| | | |
| | | viewBinding.dayTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.time_selected_38c494)); |
| | | viewBinding.dayTv.setTextColor(_mActivity.getColor(R.color.text_38C494)); |
| | | |
| | | viewBinding.monthTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.monthTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.yearTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.yearTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.lifeCycleTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.lifeCycleTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.v1.setVisibility(View.GONE); |
| | | viewBinding.v2.setVisibility(View.VISIBLE); |
| | | viewBinding.v3.setVisibility(View.VISIBLE); |
| | | viewBinding.homePageStationSelectTimeLl.setVisibility(View.VISIBLE); |
| | | |
| | | |
| | | setUpAAChartView(1); |
| | | |
| | | } |
| | | }); |
| | | //月 |
| | | viewBinding.monthTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | timeType = TimeType.month; |
| | | viewBinding.dayTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.dayTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | private void timeSelectedView(){ |
| | | viewBinding.monthTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.time_selected_38c494)); |
| | | viewBinding.monthTv.setTextColor(_mActivity.getColor(R.color.text_38C494)); |
| | | |
| | | viewBinding.yearTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.yearTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.lifeCycleTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.lifeCycleTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.v1.setVisibility(View.GONE); |
| | | viewBinding.v2.setVisibility(View.GONE); |
| | | viewBinding.v3.setVisibility(View.VISIBLE); |
| | | viewBinding.homePageStationSelectTimeLl.setVisibility(View.VISIBLE); |
| | | |
| | | setUpAAChartView(2); |
| | | |
| | | |
| | | } |
| | | }); |
| | | //年 |
| | | viewBinding.yearTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | timeType = TimeType.year; |
| | | viewBinding.dayTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.dayTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.monthTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.monthTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.yearTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.time_selected_38c494)); |
| | | viewBinding.yearTv.setTextColor(_mActivity.getColor(R.color.text_38C494)); |
| | | |
| | | viewBinding.lifeCycleTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.lifeCycleTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.v1.setVisibility(View.VISIBLE); |
| | | viewBinding.v2.setVisibility(View.GONE); |
| | | viewBinding.v3.setVisibility(View.GONE); |
| | | viewBinding.homePageStationSelectTimeLl.setVisibility(View.VISIBLE); |
| | | |
| | | setUpAAChartView(2); |
| | | } |
| | | }); |
| | | //生命期 |
| | | viewBinding.lifeCycleTv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | timeType = TimeType.lifecycle; |
| | | viewBinding.dayTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.dayTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.monthTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.monthTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.yearTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.yearTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | |
| | | viewBinding.lifeCycleTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.time_selected_38c494)); |
| | | viewBinding.lifeCycleTv.setTextColor(_mActivity.getColor(R.color.text_38C494)); |
| | | |
| | | viewBinding.v1.setVisibility(View.VISIBLE); |
| | | viewBinding.v2.setVisibility(View.VISIBLE); |
| | | viewBinding.v3.setVisibility(View.GONE); |
| | | viewBinding.homePageStationSelectTimeLl.setVisibility(View.GONE); |
| | | |
| | | setUpAAChartView(2); |
| | | |
| | | } |
| | | }); |
| | | //上一步 |
| | | viewBinding.lastStepIv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | |
| | | } |
| | | }); |
| | | //下一步 |
| | | viewBinding.nextStepIv.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View v) { |
| | | |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private void initView() { |
| | | String dataStr = TimeUtils.getDateTimestamp(System.currentTimeMillis(), TimeUtils.zhDateFormat); |
| | | if (!UserConfigManage.getInstance().isZh()) { |
| | | dataStr = TimeUtils.getDateTimestamp(System.currentTimeMillis(), TimeUtils.enDateFormat); |
| | | } |
| | | viewBinding.yearMonthDayTv.setText(dataStr); |
| | | viewBinding.dayTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.drawable.time_selected_38c494)); |
| | | viewBinding.dayTv.setTextColor(_mActivity.getColor(R.color.text_38C494)); |
| | | viewBinding.monthTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.monthTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | viewBinding.yearTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.yearTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | viewBinding.lifeCycleTv.setBackground(AppCompatResources.getDrawable(_mActivity, R.color.text_00000000)); |
| | | viewBinding.lifeCycleTv.setTextColor(_mActivity.getColor(R.color.text_40000000)); |
| | | viewBinding.v1.setVisibility(View.GONE); |
| | | viewBinding.v2.setVisibility(View.VISIBLE); |
| | | viewBinding.v3.setVisibility(View.VISIBLE); |
| | | viewBinding.homePageStationSelectTimeLl.setVisibility(View.VISIBLE); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 时间选择器 |
| | | */ |
| | | private void selectedTimePickerBuilder() { |
| | | //时间选择器 |
| | | Calendar selectedDate = Calendar.getInstance(); |
| | | Calendar startDate = Calendar.getInstance(); |
| | |
| | | // tvTime.setText(getTime(date)); |
| | | } |
| | | }) |
| | | .setType(new boolean[]{true, false, false, false, false, false})// 默认全部显示 |
| | | .setCancelText("取消")//取消按钮文字 |
| | | .setSubmitText("确定")//确认按钮文字 |
| | | .setType(new boolean[]{true, true, true, false, false, false})// 默认全部显示 |
| | | .setCancelText(_mActivity.getString(R.string.loading_cancel))//取消按钮文字 |
| | | .setSubmitText(_mActivity.getString(R.string.loading_affirm))//确认按钮文字 |
| | | .setContentTextSize(18)//滚轮文字大小 |
| | | .setTitleSize(18)//标题文字大小 |
| | | .setTitleText("时间选择")//标题文字 |
| | | .setTitleText(_mActivity.getString(R.string.time_selectd))//标题文字 |
| | | .setOutSideCancelable(true)//点击屏幕,点在控件外部范围时,是否取消显示 |
| | | .isCyclic(false)//是否循环滚动 |
| | | .setTitleColor(_mActivity.getColor(R.color.text_90000000))//标题文字颜色 |
| | |
| | | .setTextColorCenter(_mActivity.getColor(R.color.text_90000000)) |
| | | .setDate(selectedDate)// 如果不设置的话,默认是系统时间*/ |
| | | .setRangDate(startDate, endDate)//起始终止年月日设定 |
| | | .setLabel("年", "月", "日", "时", "分", "秒")//默认设置为年月日时分秒 |
| | | .setLabel(_mActivity.getString(R.string.year), _mActivity.getString(R.string.month), _mActivity.getString(R.string.day), _mActivity.getString(R.string.hour), _mActivity.getString(R.string.minute), _mActivity.getString(R.string.succeed))//默认设置为年月日时分秒 |
| | | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 |
| | | .isDialog(false)//是否显示为对话框样式 |
| | | .setItemVisibleCount(17)//对话框高度 |
| | | .setItemVisibleCount(7)//对话框高度 |
| | | .setDividerColor(_mActivity.getColor(R.color.text_E1E1E1)) |
| | | .setDecorView(viewBinding.wwwwww) |
| | | // .setLineSpacingMultiplier(3f)// |
| | | .setLineSpacingMultiplier(3f)// |
| | | .build(); |
| | | pvTime.show(); |
| | | } |
| | | |
| | | private void setUpAAChartView(int value) { |
| | | if (value == 1) { |
| | | aaChartView1 = viewBinding.AAChartView; |
| | | aaChartView1.callBack = this; |
| | | aaChartModel1 = configureAAChartModel(); |
| | | aaChartView1.aa_drawChartWithChartModel(aaChartModel1); |
| | | aaChartView = viewBinding.AAChartView; |
| | | aaChartView.callBack = this; |
| | | aaChartModel = configureAAChartModel(); |
| | | aaChartView.aa_drawChartWithChartModel(aaChartModel); |
| | | } else if (value == 2) { |
| | | // aaChartView2 = viewBinding.AAChartView2; |
| | | aaChartView2.callBack = this; |
| | | aaChartModel2 = configureColorfulColumnChart();// configureTheAAChartModel("colorfulColumnChart"); |
| | | aaChartView2.aa_drawChartWithChartModel(aaChartModel2); |
| | | aaChartView = viewBinding.AAChartView; |
| | | aaChartView.callBack = this; |
| | | aaChartModel = configureColorfulColumnChart();// configureTheAAChartModel("colorfulColumnChart"); |
| | | aaChartView.aa_drawChartWithChartModel(aaChartModel); |
| | | } |
| | | } |
| | | |
| | | private AAChartModel configureAAChartModel() { |
| | | // Intent intent = getIntent(); |
| | | String chartType = AAChartType.Area; |
| | | int position = 0; |
| | | aaChartModel1 = BasicChartComposer.configureAreaChart(); |
| | | aaChartModel = BasicChartComposer.configureAreaChart(); |
| | | configureTheStyleForDifferentTypeChart(chartType, position); |
| | | // configureViewsVisibility(chartType); |
| | | return aaChartModel1; |
| | | return aaChartModel; |
| | | } |
| | | |
| | | private void configureTheStyleForDifferentTypeChart(String chartType, int position) { |
| | | if ((chartType.equals(AAChartType.Area) || chartType.equals(AAChartType.Line)) |
| | | && (position == 4 || position == 5)) { |
| | | aaChartModel1 = BasicChartComposer.configureStepAreaChartAndStepLineChart(); |
| | | aaChartModel = BasicChartComposer.configureStepAreaChartAndStepLineChart(); |
| | | } else if (chartType.equals(AAChartType.Column) || chartType.equals(AAChartType.Bar)) { |
| | | |
| | | aaChartModel1 = BasicChartComposer.configureColumnChartAndBarChart(); |
| | | aaChartModel = BasicChartComposer.configureColumnChartAndBarChart(); |
| | | } else if (chartType.equals(AAChartType.Area) || chartType.equals(AAChartType.Areaspline)) { |
| | | aaChartModel1 = BasicChartComposer.configureAreaChartAndAreasplineChartStyle(chartType); |
| | | aaChartModel = BasicChartComposer.configureAreaChartAndAreasplineChartStyle(chartType); |
| | | } else if (chartType.equals(AAChartType.Line) || chartType.equals(AAChartType.Spline)) { |
| | | aaChartModel1 = BasicChartComposer.configureLineChartAndSplineChartStyle(chartType); |
| | | aaChartModel = BasicChartComposer.configureLineChartAndSplineChartStyle(chartType); |
| | | } |
| | | aaChartModel1.chartType = chartType; |
| | | aaChartModel.chartType = chartType; |
| | | } |
| | | |
| | | private AAChartModel configureTheAAChartModel(String chartType) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | public enum TimeType { |
| | | day, |
| | | month, |
| | | year, |
| | | lifecycle |
| | | } |
| | | } |
| | |
| | | */ |
| | | public class TimeUtils { |
| | | |
| | | public static final String zhDateFormat = "yyyy/MM/dd"; |
| | | public static final String enDateFormat = "dd/MM/yyyy"; |
| | | |
| | | /** |
| | | * 获取分钟 |
| | | * |
| | |
| | | * 时间戳转时间(格式:yyyy-MM-dd) |
| | | * |
| | | * @param timestamp 时间戳 |
| | | * @param date_format 时间格式(例如"yyyy-MM-dd") |
| | | * @return - |
| | | */ |
| | | public static String getDateTimestamp(long timestamp) { |
| | | public static String getDateTimestamp(long timestamp, String date_format) { |
| | | try { |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd ", Locale.ENGLISH); |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat(date_format, Locale.ENGLISH); |
| | | Date date = new Date(timestamp); |
| | | return dateFormat.format(date); |
| | | } catch (Exception e) { |
| | |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 加天数 |
| | | * |
| | | * @param date 日历 |
| | | * @param daysToAdd 天数 |
| | | * @return 日历 |
| | | */ |
| | | public static Calendar addDaysToDate(Calendar date, int daysToAdd) { |
| | | Calendar newDate = (Calendar) date.clone(); |
| | | newDate.add(Calendar.DAY_OF_MONTH, daysToAdd); |
| | | return newDate; |
| | | } |
| | | |
| | | /** |
| | | * 减天数 |
| | | * |
| | | * @param date 日历 |
| | | * @param daysToSubtract 天数 |
| | | * @return 日历 |
| | | */ |
| | | public static Calendar subtractDaysFromDate(Calendar date, int daysToSubtract) { |
| | | Calendar newDate = (Calendar) date.clone(); |
| | | newDate.add(Calendar.DAY_OF_MONTH, -daysToSubtract); |
| | | return newDate; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="@color/text_1238C494" /> |
| | | <corners android:radius="@dimen/dp_6" /> |
| | | <stroke |
| | | android:width="@dimen/dp_1" |
| | | android:color="@color/text_38C494" /> |
| | | </shape> |
| | |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/home_page_station_ll" |
| | | android:layout_width="0dp" |
| | | android:layout_width="375dp" |
| | | android:layout_height="@dimen/dp_56" |
| | | android:orientation="horizontal" |
| | | app:layout_constraintEnd_toEndOf="parent" |
| | |
| | | android:layout_width="86dp" |
| | | android:layout_height="match_parent" |
| | | android:gravity="center" |
| | | android:text="Day" /> |
| | | android:text="@string/day" /> |
| | | |
| | | <View |
| | | android:id="@+id/v_1" |
| | |
| | | android:layout_width="86dp" |
| | | android:layout_height="match_parent" |
| | | android:gravity="center" |
| | | android:text="Month" /> |
| | | android:text="@string/month" /> |
| | | |
| | | <View |
| | | android:id="@+id/v_2" |
| | |
| | | android:layout_width="86dp" |
| | | android:layout_height="match_parent" |
| | | android:gravity="center" |
| | | android:text="Year" /> |
| | | android:text="@string/year" /> |
| | | |
| | | <View |
| | | android:id="@+id/v_3" |
| | |
| | | android:layout_width="86dp" |
| | | android:layout_height="match_parent" |
| | | android:gravity="center" |
| | | android:text="LifeCycle" /> |
| | | android:text="@string/life_cycle" /> |
| | | |
| | | </LinearLayout> |
| | | <!--时间切换控件--> |
| | |
| | | <TextView |
| | | android:id="@+id/social_contribution_data_1_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="13dp" |
| | | android:layout_height="22dp" |
| | | android:layout_alignParentStart="true" |
| | | android:layout_alignParentTop="true" |
| | | android:layout_marginStart="@dimen/dp_10" |
| | | android:layout_marginTop="@dimen/dp_16" |
| | | android:text="13.14" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textSize="@dimen/text_18" |
| | | android:textStyle="bold" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/social_contribution_unit_1_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="9dp" |
| | | android:layout_height="15dp" |
| | | android:layout_alignBottom="@+id/social_contribution_data_1_tv" |
| | | android:layout_marginStart="@dimen/dp_2" |
| | | android:layout_toEndOf="@+id/social_contribution_data_1_tv" |
| | | android:text="(T)" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textStyle="bold" |
| | | android:textSize="@dimen/text_12" |
| | | |
| | | |
| | | /> |
| | | |
| | |
| | | android:layout_marginTop="@dimen/dp_35" |
| | | android:text="ssss" |
| | | android:textColor="@color/text_40000000" |
| | | android:textSize="@dimen/text_14" /> |
| | | android:textSize="@dimen/text_12" /> |
| | | |
| | | |
| | | </RelativeLayout> |
| | |
| | | <TextView |
| | | android:id="@+id/social_contribution_data_2_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="13dp" |
| | | android:layout_height="22dp" |
| | | android:layout_alignParentStart="true" |
| | | android:layout_alignParentTop="true" |
| | | android:layout_marginStart="@dimen/dp_10" |
| | | android:layout_marginTop="@dimen/dp_16" |
| | | android:text="13.14" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textSize="@dimen/text_18" |
| | | android:textStyle="bold" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/social_contribution_unit_2_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="9dp" |
| | | android:layout_height="15dp" |
| | | android:layout_alignBottom="@+id/social_contribution_data_2_tv" |
| | | android:layout_marginStart="@dimen/dp_2" |
| | | android:layout_toEndOf="@+id/social_contribution_data_2_tv" |
| | | android:text="(T)" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textStyle="bold" |
| | | android:textSize="@dimen/text_12" |
| | | |
| | | /> |
| | | |
| | |
| | | android:layout_marginTop="@dimen/dp_35" |
| | | android:text="ssss" |
| | | android:textColor="@color/text_40000000" |
| | | android:textSize="@dimen/text_14" /> |
| | | android:textSize="@dimen/text_12" /> |
| | | |
| | | |
| | | </RelativeLayout> |
| | |
| | | <TextView |
| | | android:id="@+id/social_contribution_data_3_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="13dp" |
| | | android:layout_alignParentStart="true" |
| | | android:layout_height="22dp" |
| | | android:layout_alignParentTop="true" |
| | | android:layout_marginStart="@dimen/dp_10" |
| | | android:layout_marginTop="@dimen/dp_16" |
| | | android:text="13.14" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textSize="@dimen/text_18" |
| | | android:textStyle="bold" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/social_contribution_unit_3_tv" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="9dp" |
| | | android:layout_height="15dp" |
| | | android:layout_alignBottom="@+id/social_contribution_data_3_tv" |
| | | android:layout_marginStart="@dimen/dp_2" |
| | | android:layout_toEndOf="@+id/social_contribution_data_3_tv" |
| | | android:text="(T)" |
| | | android:textColor="@color/text_90000000" |
| | | android:textSize="@dimen/text_14" |
| | | android:textStyle="bold" |
| | | android:textSize="@dimen/text_12" |
| | | |
| | | /> |
| | | |
| | |
| | | android:layout_marginTop="@dimen/dp_35" |
| | | android:text="ssss" |
| | | android:textColor="@color/text_40000000" |
| | | android:textSize="@dimen/text_14" /> |
| | | android:textSize="@dimen/text_12" /> |
| | | |
| | | |
| | | </RelativeLayout> |
| | | |
| | | </androidx.constraintlayout.widget.ConstraintLayout> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/wwwwww" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="323dp" |
| | | app:layout_constraintEnd_toEndOf="parent" |
| | | app:layout_constraintStart_toStartOf="parent" |
| | | app:layout_constraintTop_toBottomOf="@+id/home_page_station_statistics_cl"> |
| | | |
| | | </LinearLayout> |
| | | </androidx.constraintlayout.widget.ConstraintLayout> |
| | | |
| | | |
| | |
| | | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:app="http://schemas.android.com/apk/res-auto" |
| | | android:id="@+id/station_status_cl" |
| | | android:layout_width="@dimen/dp_74" |
| | | android:layout_height="@dimen/dp_56" |
| | | android:layout_width="74dp" |
| | | android:layout_height="56dp" |
| | | android:background="@drawable/station_status_no_ffffff"> |
| | | |
| | | <TextView |
| | |
| | | <color name="text_38C494">#38C494</color> |
| | | <color name="text_C2EDDE">#C2EDDE</color> |
| | | <color name="text_C1C1C1">#C1C1C1</color> |
| | | <color name="text_1238C494">#1238C494</color> |
| | | |
| | | |
| | | </resources> |
| | |
| | | <string name="port_conflict">应用冲突,需要关闭onpro或者其它版本的调试软件然后再重新启动这个软件试试</string> |
| | | |
| | | |
| | | <string name="time_selectd">时间选择</string> |
| | | <string name="life_cycle">生命期</string> |
| | | <string name="year">年</string> |
| | | <string name="month">月</string> |
| | | <string name="day">日</string> |
| | | <string name="hour">时</string> |
| | | <string name="minutc">分</string> |
| | | <string name="seconds">秒</string> |
| | | |
| | | </resources> |
| | |
| | | <item name="colorOnSecondary">@color/black</item> |
| | | <!-- Status bar color. --> |
| | | <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> |
| | | |
| | | <!-- Customize your theme here. --> |
| | | </style> |
| | | |
| | | <style name="Theme.PhotovoltaicDebug.NoActionBar"> |
| | | <item name="windowActionBar">false</item> |
| | | <item name="windowNoTitle">true</item> |
| | | |
| | | </style> |
| | | |
| | | |
New file |
| | |
| | | /build
|
| | | *.idea
|
| | | /.idea/libraries
|
| | | /.idea/modules
|
| | | /.idea/compiler.xml
|
| | | /.idea/gradle.xml
|
| | | /.idea/jarRepositories.xml
|
| | | /.idea/misc.xml
|
| | | /.idea/modules.xml
|
| | | /.idea/vcs.xml
|
| | | /.idea/workspace.xml
|
| | | /release |
New file |
| | |
| | | apply plugin: 'com.android.library'
|
| | | //apply plugin: 'com.novoda.bintray-release'//添加JCenter插件
|
| | |
|
| | |
|
| | |
|
| | | android {
|
| | | compileSdkVersion 31
|
| | |
|
| | | defaultConfig {
|
| | | minSdkVersion 23
|
| | | targetSdkVersion 31
|
| | | versionCode 34
|
| | | versionName "4.1.9"
|
| | | }
|
| | | buildTypes {
|
| | | release {
|
| | | minifyEnabled false
|
| | | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
| | | }
|
| | | }
|
| | | lintOptions {
|
| | | abortOnError false
|
| | | }
|
| | | }
|
| | |
|
| | | //allprojects {
|
| | | // tasks.withType(Javadoc) {//兼容中文字符
|
| | | // options{
|
| | | // encoding "UTF-8"
|
| | | // charSet 'UTF-8'
|
| | | // links "http://docs.oracle.com/javase/7/docs/api"
|
| | | // }
|
| | | // }
|
| | | //}
|
| | | //publish {
|
| | | // userOrg = 'contrarywind'//bintray.com 用户名/组织名 user/org name
|
| | | // groupId = 'com.contrarywind'//JCenter上显示的路径 path
|
| | | // artifactId = 'Android-PickerView'//项目名称 project name
|
| | | // publishVersion = '4.1.9'//版本号 version code
|
| | | // desc = 'this is a pickerview for android'//项目描述 description
|
| | | // website = 'https://github.com/Bigkoo/Android-PickerView' //项目网址链接 link
|
| | | //}
|
| | |
|
| | | dependencies {
|
| | | // compile fileTree(include: ['*.jar'], dir: 'libs')
|
| | | api project(path: ':wheelview')
|
| | | // implementation 'com.contrarywind:wheelview:4.1.0'
|
| | | implementation 'com.android.support:support-annotations:28.0.0'
|
| | | } |
New file |
| | |
| | | # Add project specific ProGuard rules here.
|
| | | # By default, the flags in this file are appended to flags specified
|
| | | # in /Users/Sai/Documents/software/sdk/tools/proguard/proguard-android.txt
|
| | | # You can edit the include path and order by changing the proguardFiles
|
| | | # directive in build.gradle.
|
| | | #
|
| | | # For more details, see
|
| | | # http://developer.android.com/guide/developing/tools/proguard.html
|
| | |
|
| | | # Add any project specific keep options here:
|
| | |
|
| | | # 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 *;
|
| | | #}
|
New file |
| | |
| | | package com.bigkoo.pickerview;
|
| | |
|
| | | import android.app.Application;
|
| | | import android.test.ApplicationTestCase;
|
| | |
|
| | | /**
|
| | | * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
| | | */
|
| | | public class ApplicationTest extends ApplicationTestCase<Application> {
|
| | | public ApplicationTest() {
|
| | | super(Application.class);
|
| | | }
|
| | | } |
New file |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
| | | package="com.bigkoo.pickerview">
|
| | |
|
| | |
|
| | | </manifest>
|
New file |
| | |
| | | package com.bigkoo.pickerview.adapter;
|
| | |
|
| | | import com.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);
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.adapter;
|
| | |
|
| | |
|
| | | import com.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;
|
| | | }
|
| | |
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.builder;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.graphics.Typeface;
|
| | | import android.view.View;
|
| | | import android.view.ViewGroup;
|
| | |
|
| | | import com.bigkoo.pickerview.configure.PickerOptions;
|
| | | import com.bigkoo.pickerview.listener.CustomListener;
|
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener;
|
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectListener;
|
| | | import com.bigkoo.pickerview.view.OptionsPickerView;
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import androidx.annotation.ColorInt;
|
| | |
|
| | | /**
|
| | | * 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 count 建议设置为 3 ~ 9之间。
|
| | | */
|
| | | public OptionsPickerBuilder setItemVisibleCount(int count) {
|
| | | mPickerOptions.itemsVisibleCount = count;
|
| | | return this;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 透明度是否渐变
|
| | | *
|
| | | * @param isAlphaGradient true of false
|
| | | */
|
| | | public OptionsPickerBuilder isAlphaGradient(boolean isAlphaGradient) {
|
| | | mPickerOptions.isAlphaGradient = isAlphaGradient;
|
| | | 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);
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.builder;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.view.View;
|
| | | import android.view.ViewGroup;
|
| | |
|
| | | import com.bigkoo.pickerview.configure.PickerOptions;
|
| | | import com.bigkoo.pickerview.listener.CustomListener;
|
| | | import com.bigkoo.pickerview.listener.OnTimeSelectChangeListener;
|
| | | import com.bigkoo.pickerview.listener.OnTimeSelectListener;
|
| | | import com.bigkoo.pickerview.view.TimePickerView;
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.util.Calendar;
|
| | |
|
| | | import androidx.annotation.ColorInt;
|
| | |
|
| | | /**
|
| | | * 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;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置最大可见数目
|
| | | *
|
| | | * @param count suggest value: 3, 5, 7, 9
|
| | | */
|
| | | public TimePickerBuilder setItemVisibleCount(int count) {
|
| | | mPickerOptions.itemsVisibleCount = count;
|
| | | return this;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 透明度是否渐变
|
| | | *
|
| | | * @param isAlphaGradient true of false
|
| | | */
|
| | | public TimePickerBuilder isAlphaGradient(boolean isAlphaGradient) {
|
| | | mPickerOptions.isAlphaGradient = isAlphaGradient;
|
| | | return this;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从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的set方法来设置时间,月份的范围也要是从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);
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.configure;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.graphics.Typeface;
|
| | | import android.view.Gravity;
|
| | | import android.view.View;
|
| | | import android.view.ViewGroup;
|
| | |
|
| | | import com.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.listener.CustomListener;
|
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener;
|
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectListener;
|
| | | import com.bigkoo.pickerview.listener.OnTimeSelectChangeListener;
|
| | | import com.bigkoo.pickerview.listener.OnTimeSelectListener;
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.util.Calendar;
|
| | |
|
| | | /**
|
| | | * Build Options
|
| | | * Created by xiaosongzeem on 2018/3/8.
|
| | | */
|
| | |
|
| | | public class PickerOptions {
|
| | |
|
| | | //constant
|
| | | private static final int PICKER_VIEW_BTN_COLOR_NORMAL = 0xFF057dff;
|
| | | 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.pickerview_options;
|
| | | } else {
|
| | | layoutRes = R.layout.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;//取消按钮颜色
|
| | | public int textColorTitle = PICKER_VIEW_COLOR_TITLE;//标题颜色
|
| | |
|
| | | public int bgColorWheel = PICKER_VIEW_BG_COLOR_DEFAULT;//滚轮背景颜色
|
| | | public int bgColorTitle = PICKER_VIEW_BG_COLOR_DEFAULT;//标题背景颜色
|
| | |
|
| | | 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;//分隔线类型
|
| | | public int itemsVisibleCount = 9; //最大可见条目数
|
| | | public boolean isAlphaGradient = false; //透明度渐变
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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);
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.listener;
|
| | |
|
| | | /**
|
| | | * Created by zengsong on 2018/3/21.
|
| | | */
|
| | |
|
| | | public interface ISelectTimeCallback {
|
| | |
|
| | | public void onTimeSelectChanged();
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.listener;
|
| | |
|
| | | /**
|
| | | * Created by Sai on 15/8/9.
|
| | | */
|
| | | public interface OnDismissListener {
|
| | | public void onDismiss(Object o);
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.listener;
|
| | |
|
| | | /**
|
| | | * Created by xiaosong on 2018/3/20.
|
| | | */
|
| | |
|
| | | public interface OnOptionsSelectChangeListener {
|
| | |
|
| | | void onOptionsSelectChanged(int options1, int options2, int options3);
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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);
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.listener;
|
| | |
|
| | | import java.util.Date;
|
| | |
|
| | | /**
|
| | | * Created by xiaosong on 2018/3/20.
|
| | | */
|
| | |
|
| | | public interface OnTimeSelectChangeListener {
|
| | |
|
| | | void onTimeSelectChanged(Date date);
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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);
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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代表十六进制,后面的五位数是十六进制数。
|
| | | * 举个例子: 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年m月的总天数
|
| | | * @param m y年m月的总天数
|
| | | * @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 月日的offset 传回干支,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年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
|
| | | *
|
| | | * @param y 年
|
| | | * @param m 月
|
| | | * @param d 日
|
| | | * @return y年m月d日对应的农历
|
| | | */
|
| | | 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);
|
| | | }
|
| | | // 解除闰月
|
| | | 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年M月d日 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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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位bit的16进制表示,其中:
|
| | | * 1. 前4位表示该年闰哪个月;
|
| | | * 2. 5-17位表示农历年份13个月的大小月分布,0表示小,1表示大;
|
| | | * 3. 最后7位表示农历年首(正月初一)对应的公历日期。
|
| | | * <p>
|
| | | * 以2014年的数据0x955ABF为例说明:
|
| | | * 1001 0101 0101 1010 1011 1111
|
| | | * 闰九月 农历正月初一对应公历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,month1,day2,leap3
|
| | | * @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);
|
| | |
|
| | | // 用offset减去每农历年的天数计算当天是农历第几天
|
| | | // 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年month月的总天数
|
| | | *
|
| | | * @param year 要计算的年份
|
| | | * @param month 要计算的月
|
| | | * @return 传回天数
|
| | | */
|
| | | final public static int daysInMonth(int year, int month) {
|
| | | return daysInMonth(year, month, false);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 传回农历year年month月的总天数
|
| | | *
|
| | | * @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 {
|
| | | // 传入的闰月是正确的月份
|
| | | 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年month月的总天数,总共有13个月包括闰月
|
| | | *
|
| | | * @param year 将要计算的年份
|
| | | * @param month 将要计算的月份
|
| | | * @return 传回农历 year年month月的总天数
|
| | | */
|
| | | 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);
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.utils;
|
| | |
|
| | | import android.view.Gravity;
|
| | |
|
| | | import com.bigkoo.pickerview.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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.configure.PickerOptions;
|
| | | import com.bigkoo.pickerview.listener.OnDismissListener;
|
| | | import com.bigkoo.pickerview.utils.PickerViewAnimateUtil;
|
| | |
|
| | | /**
|
| | | * Created by Sai on 15/11/22.
|
| | | * 精仿iOSPickerViewController控件
|
| | | */
|
| | | public class BasePickerView {
|
| | |
|
| | | private Context context;
|
| | | protected ViewGroup contentContainer;
|
| | | private ViewGroup rootView;//附加View 的 根View
|
| | | private ViewGroup dialogView;//附加Dialog 的 根View
|
| | |
|
| | | 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.layout_basepickerview, null, false);
|
| | | //设置界面的背景为透明
|
| | | dialogView.setBackgroundColor(Color.TRANSPARENT);
|
| | | //这个是真正要加载选择器的父布局
|
| | | 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是activity的根View,包含 contentView 和 titleView
|
| | | if (mPickerOptions.decorView == null) {
|
| | | mPickerOptions.decorView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
|
| | | }
|
| | | //将控件添加到decorView中
|
| | | rootView = (ViewGroup) layoutInflater.inflate(R.layout.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);
|
| | | }
|
| | | //这个是真正要加载时间选取器的父布局
|
| | | 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 如果视图已经存在该View返回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;
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.configure.PickerOptions;
|
| | |
|
| | | import java.util.List;
|
| | |
|
| | | /**
|
| | | * 条件选择器
|
| | | * Created by Sai on 15/11/22.
|
| | | */
|
| | | public class OptionsPickerView<T> extends BasePickerView implements View.OnClickListener {
|
| | |
|
| | | private WheelOptions<T> 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);
|
| | | } 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.setItemsVisible(mPickerOptions.itemsVisibleCount);
|
| | | wheelOptions.setAlphaGradient(mPickerOptions.isAlphaGradient);
|
| | | 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 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<T> optionsItems) {
|
| | | this.setPicker(optionsItems, null, null);
|
| | | }
|
| | |
|
| | | public void setPicker(List<T> options1Items, List<List<T>> options2Items) {
|
| | | this.setPicker(options1Items, options2Items, null);
|
| | | }
|
| | |
|
| | | public void setPicker(List<T> options1Items,
|
| | | List<List<T>> options2Items,
|
| | | List<List<List<T>>> options3Items) {
|
| | |
|
| | | wheelOptions.setPicker(options1Items, options2Items, options3Items);
|
| | | reSetCurrentItems();
|
| | | }
|
| | |
|
| | |
|
| | | //不联动情况下调用
|
| | | public void setNPicker(List<T> options1Items,
|
| | | List<T> options2Items,
|
| | | List<T> 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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.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.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.configure.PickerOptions;
|
| | | import com.bigkoo.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.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);
|
| | | //这样做可以阻止子控件的点击事件穿透到父控件上,从而使得父控件响应点击事件。
|
| | | tvTitle.setClickable(true);
|
| | | tvTitle.setFocusable(true);
|
| | |
|
| | |
|
| | | 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);
|
| | | wheelTime.setItemsVisible(mPickerOptions.itemsVisibleCount);
|
| | | wheelTime.setAlphaGradient(mPickerOptions.isAlphaGradient);
|
| | | 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) {
|
| | | //没有设置默认选中时间,那就拿开始时间当默认时间
|
| | | 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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.view;
|
| | |
|
| | | import android.graphics.Typeface;
|
| | | import android.view.View;
|
| | |
|
| | | import com.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.adapter.ArrayWheelAdapter;
|
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener;
|
| | | import com.contrarywind.listener.OnItemSelectedListener;
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.util.List;
|
| | |
|
| | | 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;
|
| | |
|
| | | 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();//上一个opt2的选中位置
|
| | | //新opt2的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项
|
| | | 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() 上一个opt3的选中位置
|
| | | //新opt3的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项
|
| | | 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 setLineSpacingMultiplier() {
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置选项的单位
|
| | | *
|
| | | * @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,防止index出错导致崩溃。
|
| | | *
|
| | | * @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) {
|
| | | wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线的颜色
|
| | | *
|
| | | * @param dividerColor
|
| | | */
|
| | | public void setDividerColor(int dividerColor) {
|
| | | wv_option1.setDividerColor(dividerColor);
|
| | | wv_option2.setDividerColor(dividerColor);
|
| | | wv_option3.setDividerColor(dividerColor);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线的类型
|
| | | *
|
| | | * @param dividerType
|
| | | */
|
| | | public void setDividerType(WheelView.DividerType dividerType) {
|
| | | wv_option1.setDividerType(dividerType);
|
| | | wv_option2.setDividerType(dividerType);
|
| | | wv_option3.setDividerType(dividerType);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线之间的文字的颜色
|
| | | *
|
| | | * @param textColorCenter
|
| | | */
|
| | | public void setTextColorCenter(int textColorCenter) {
|
| | | wv_option1.setTextColorCenter(textColorCenter);
|
| | | wv_option2.setTextColorCenter(textColorCenter);
|
| | | wv_option3.setTextColorCenter(textColorCenter);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线以外文字的颜色
|
| | | *
|
| | | * @param textColorOut
|
| | | */
|
| | | public void setTextColorOut(int textColorOut) {
|
| | | wv_option1.setTextColorOut(textColorOut);
|
| | | wv_option2.setTextColorOut(textColorOut);
|
| | | wv_option3.setTextColorOut(textColorOut);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置最大可见数目
|
| | | *
|
| | | * @param itemsVisible 建议设置为 3 ~ 9之间。
|
| | | */
|
| | | public void setItemsVisible(int itemsVisible) {
|
| | | wv_option1.setItemsVisibleCount(itemsVisible);
|
| | | wv_option2.setItemsVisibleCount(itemsVisible);
|
| | | wv_option3.setItemsVisibleCount(itemsVisible);
|
| | | }
|
| | |
|
| | | public void setAlphaGradient(boolean isAlphaGradient) {
|
| | | wv_option1.setAlphaGradient(isAlphaGradient);
|
| | | wv_option2.setAlphaGradient(isAlphaGradient);
|
| | | wv_option3.setAlphaGradient(isAlphaGradient);
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.bigkoo.pickerview.view;
|
| | |
|
| | | import android.view.View;
|
| | |
|
| | | import com.bigkoo.pickerview.R;
|
| | | import com.bigkoo.pickerview.adapter.ArrayWheelAdapter;
|
| | | import com.bigkoo.pickerview.adapter.NumericWheelAdapter;
|
| | | import com.bigkoo.pickerview.listener.ISelectTimeCallback;
|
| | | import com.bigkoo.pickerview.utils.ChinaDate;
|
| | | import com.bigkoo.pickerview.utils.LunarCalendar;
|
| | | import com.contrarywind.listener.OnItemSelectedListener;
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.text.DateFormat;
|
| | | import java.text.SimpleDateFormat;
|
| | | import java.util.Arrays;
|
| | | import java.util.Calendar;
|
| | | import java.util.List;
|
| | |
|
| | |
|
| | | 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 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) {
|
| | | // 添加大小月月份并将其转换为list,方便之后的判断
|
| | | 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);
|
| | |
|
| | | boolean leapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
|
| | | 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 (leapYear) {
|
| | | 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 {
|
| | | // 闰年 29,平年 28
|
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, leapYear ? 29 : 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 (leapYear) {
|
| | | 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 {
|
| | | // 闰年 29,平年 28
|
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, leapYear ? 29 : 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);
|
| | | }
|
| | |
|
| | |
|
| | | 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) {
|
| | | wv_day.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_month.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_year.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_hours.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_minutes.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | wv_seconds.setLineSpacingMultiplier(lineSpacingMultiplier);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线的颜色
|
| | | *
|
| | | * @param dividerColor
|
| | | */
|
| | | public void setDividerColor(int dividerColor) {
|
| | | wv_day.setDividerColor(dividerColor);
|
| | | wv_month.setDividerColor(dividerColor);
|
| | | wv_year.setDividerColor(dividerColor);
|
| | | wv_hours.setDividerColor(dividerColor);
|
| | | wv_minutes.setDividerColor(dividerColor);
|
| | | wv_seconds.setDividerColor(dividerColor);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线的类型
|
| | | *
|
| | | * @param dividerType
|
| | | */
|
| | | public void setDividerType(WheelView.DividerType dividerType) {
|
| | | wv_day.setDividerType(dividerType);
|
| | | wv_month.setDividerType(dividerType);
|
| | | wv_year.setDividerType(dividerType);
|
| | | wv_hours.setDividerType(dividerType);
|
| | | wv_minutes.setDividerType(dividerType);
|
| | | wv_seconds.setDividerType(dividerType);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线之间的文字的颜色
|
| | | *
|
| | | * @param textColorCenter
|
| | | */
|
| | | public void setTextColorCenter(int textColorCenter) {
|
| | | wv_day.setTextColorCenter(textColorCenter);
|
| | | wv_month.setTextColorCenter(textColorCenter);
|
| | | wv_year.setTextColorCenter(textColorCenter);
|
| | | wv_hours.setTextColorCenter(textColorCenter);
|
| | | wv_minutes.setTextColorCenter(textColorCenter);
|
| | | wv_seconds.setTextColorCenter(textColorCenter);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 设置分割线以外文字的颜色
|
| | | *
|
| | | * @param textColorOut
|
| | | */
|
| | | public void setTextColorOut(int textColorOut) {
|
| | | wv_day.setTextColorOut(textColorOut);
|
| | | wv_month.setTextColorOut(textColorOut);
|
| | | wv_year.setTextColorOut(textColorOut);
|
| | | wv_hours.setTextColorOut(textColorOut);
|
| | | wv_minutes.setTextColorOut(textColorOut);
|
| | | wv_seconds.setTextColorOut(textColorOut);
|
| | | }
|
| | |
|
| | | /**
|
| | | * @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;
|
| | | }
|
| | |
|
| | | public void setItemsVisible(int itemsVisibleCount) {
|
| | | wv_day.setItemsVisibleCount(itemsVisibleCount);
|
| | | wv_month.setItemsVisibleCount(itemsVisibleCount);
|
| | | wv_year.setItemsVisibleCount(itemsVisibleCount);
|
| | | wv_hours.setItemsVisibleCount(itemsVisibleCount);
|
| | | wv_minutes.setItemsVisibleCount(itemsVisibleCount);
|
| | | wv_seconds.setItemsVisibleCount(itemsVisibleCount);
|
| | | }
|
| | |
|
| | | public void setAlphaGradient(boolean isAlphaGradient) {
|
| | | wv_day.setAlphaGradient(isAlphaGradient);
|
| | | wv_month.setAlphaGradient(isAlphaGradient);
|
| | | wv_year.setAlphaGradient(isAlphaGradient);
|
| | | wv_hours.setAlphaGradient(isAlphaGradient);
|
| | | wv_minutes.setAlphaGradient(isAlphaGradient);
|
| | | wv_seconds.setAlphaGradient(isAlphaGradient);
|
| | | }
|
| | | }
|
New file |
| | |
| | | <?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> |
New file |
| | |
| | | <?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> |
New file |
| | |
| | | <?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> |
New file |
| | |
| | | <?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> |
New file |
| | |
| | | <?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>
|
New file |
| | |
| | | <?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="@color/pickerview_bgColor_default">
|
| | |
|
| | | <Button
|
| | | android:id="@+id/btnCancel"
|
| | | android:layout_width="wrap_content"
|
| | | android:layout_height="match_parent"
|
| | | android:background="@android:color/transparent"
|
| | | android:gravity="left|center_vertical"
|
| | | android:paddingLeft="@dimen/pickerview_topbar_padding"
|
| | | android:text="@string/pickerview_cancel"
|
| | | android:textAllCaps="false"
|
| | | android:textColor="@drawable/selector_pickerview_btn"
|
| | | android:textSize="@dimen/pickerview_topbar_btn_textsize" />
|
| | |
|
| | | <TextView
|
| | | android:id="@+id/tvTitle"
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="wrap_content"
|
| | | android:layout_centerVertical="true"
|
| | | android:layout_toLeftOf="@+id/btnSubmit"
|
| | | android:layout_toRightOf="@+id/btnCancel"
|
| | | android:gravity="center"
|
| | | 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/transparent"
|
| | | android:gravity="right|center_vertical"
|
| | | android:paddingRight="@dimen/pickerview_topbar_padding"
|
| | | android:text="@string/pickerview_submit"
|
| | | android:textAllCaps="false"
|
| | | android:textColor="@drawable/selector_pickerview_btn"
|
| | | android:textSize="@dimen/pickerview_topbar_btn_textsize" />
|
| | | </RelativeLayout>
|
New file |
| | |
| | | <?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> |
New file |
| | |
| | | <?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/include_pickerview_topbar"
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="50dp" />
|
| | |
|
| | | <View
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="0.5dp"
|
| | | android:background="#E1E1E1" />
|
| | |
|
| | | <LinearLayout
|
| | | android:id="@+id/optionspicker"
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="match_parent"
|
| | | android:background="@android:color/white"
|
| | | android:gravity="center"
|
| | | android:minHeight="180dp"
|
| | | android:orientation="horizontal">
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/options1"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/options2"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/options3"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | | </LinearLayout>
|
| | |
|
| | |
|
| | | </LinearLayout> |
New file |
| | |
| | | <?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/include_pickerview_topbar"
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="@dimen/pickerview_topbar_height" />
|
| | |
|
| | | <View
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="0.5dp"
|
| | | android:background="#E1E1E1" />
|
| | |
|
| | | <LinearLayout
|
| | | android:id="@+id/timepicker"
|
| | | android:layout_width="match_parent"
|
| | | android:layout_height="match_parent"
|
| | | android:background="@android:color/white"
|
| | | android:gravity="center"
|
| | | android:minHeight="150dp"
|
| | | android:orientation="horizontal">
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/year"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="0.96" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/month"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/day"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/hour"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/min"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | |
|
| | | <com.contrarywind.view.WheelView
|
| | | android:id="@+id/second"
|
| | | android:layout_width="0dp"
|
| | | android:layout_height="match_parent"
|
| | | android:layout_weight="1" />
|
| | | </LinearLayout>
|
| | |
|
| | |
|
| | | </LinearLayout> |
New file |
| | |
| | | <resources>
|
| | |
|
| | | <string name="pickerview_cancel">Cancel</string>
|
| | | <string name="pickerview_submit">Confirm</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>
|
| | | </resources>
|
New file |
| | |
| | | <resources>
|
| | | <!-- 顶部按钮栏高度 -->
|
| | | <dimen name="pickerview_topbar_height">52dp</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>
|
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?>
|
| | | <resources>
|
| | |
|
| | | <integer name="animation_default_duration">300</integer>
|
| | | </resources> |
New file |
| | |
| | | <resources>
|
| | |
|
| | | <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>
|
| | | </resources>
|
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?>
|
| | | <resources>
|
| | | <style name="custom_dialog2" parent="@android:style/Theme.Dialog">
|
| | | <item name="android:windowFrame">@null</item>
|
| | | <!-- Dialog的windowFrame框为无 -->
|
| | | <item name="android:windowIsFloating">true</item>
|
| | | <!-- 是否漂现在activity上 -->
|
| | | <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>
|
| | |
| | | include ':third-zxing' |
| | | include ':countrypicker' |
| | | include ':aa_chart_core' |
| | | include ':pickerview' |
| | | include ':wheelview' |
| | |
| | |
|
| | |
|
| | | android {
|
| | | compileSdkVersion 29
|
| | | compileSdkVersion 30
|
| | | buildToolsVersion "29.0.1"
|
| | |
|
| | | defaultConfig {
|
| | | minSdkVersion 21
|
| | | targetSdkVersion 26
|
| | | minSdkVersion 23
|
| | | targetSdkVersion 30
|
| | | versionCode 1
|
| | | versionName "1.0"
|
| | |
|
New file |
| | |
| | | /build
|
| | | *.idea
|
| | | /.idea/libraries
|
| | | /.idea/modules
|
| | | /.idea/compiler.xml
|
| | | /.idea/gradle.xml
|
| | | /.idea/jarRepositories.xml
|
| | | /.idea/misc.xml
|
| | | /.idea/modules.xml
|
| | | /.idea/vcs.xml
|
| | | /.idea/workspace.xml
|
| | | /release |
New file |
| | |
| | | apply plugin: 'com.android.library'
|
| | | //apply plugin: 'com.novoda.bintray-release'//添加插件
|
| | |
|
| | |
|
| | |
|
| | | android {
|
| | | compileSdkVersion 31
|
| | |
|
| | | defaultConfig {
|
| | | minSdkVersion 23
|
| | | targetSdkVersion 31
|
| | | versionCode 31
|
| | | versionName "4.1.0"
|
| | | }
|
| | | buildTypes {
|
| | | release {
|
| | | minifyEnabled false
|
| | | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
| | | }
|
| | | }
|
| | | lintOptions {
|
| | | abortOnError false
|
| | | }
|
| | | }
|
| | |
|
| | | //allprojects {
|
| | | // tasks.withType(Javadoc) {//兼容中文字符
|
| | | // options{
|
| | | // encoding "UTF-8"
|
| | | // charSet 'UTF-8'
|
| | | // links "http://docs.oracle.com/javase/7/docs/api"
|
| | | // }
|
| | | // }
|
| | | //}
|
| | | //publish {
|
| | | // userOrg = 'contrarywind'//bintray.com 用户名/组织名 user/org name
|
| | | // groupId = 'com.contrarywind'//JCenter上显示的路径 path
|
| | | // artifactId = 'wheelview'//项目名称 project name
|
| | | // publishVersion = '4.1.0'//版本号 version code
|
| | | // desc = 'this is a wheelview for android'//项目描述 description
|
| | | // website = 'https://github.com/Bigkoo/Android-PickerView' //项目网址链接 link
|
| | | //}
|
| | |
|
| | | dependencies {
|
| | | // compile fileTree(include: ['*.jar'], dir: 'libs')
|
| | | implementation 'com.android.support:support-annotations:28.0.0'
|
| | | } |
New file |
| | |
| | | # Add project specific ProGuard rules here.
|
| | | # By default, the flags in this file are appended to flags specified
|
| | | # in C:\Users\song\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
|
| | | # You can edit the include path and order by changing the proguardFiles
|
| | | # directive in build.gradle.
|
| | | #
|
| | | # For more details, see
|
| | | # http://developer.android.com/guide/developing/tools/proguard.html
|
| | |
|
| | | # Add any project specific keep options here:
|
| | |
|
| | | # 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
|
New file |
| | |
| | | package test.wheelview;
|
| | |
|
| | | import android.content.Context;
|
| | | import android.support.test.InstrumentationRegistry;
|
| | | import android.support.test.runner.AndroidJUnit4;
|
| | |
|
| | | import org.junit.Test;
|
| | | import org.junit.runner.RunWith;
|
| | |
|
| | | import static org.junit.Assert.*;
|
| | |
|
| | | /**
|
| | | * Instrumentation test, which will execute on an Android device.
|
| | | *
|
| | | * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
| | | */
|
| | | @RunWith(AndroidJUnit4.class)
|
| | | public class ExampleInstrumentedTest {
|
| | | @Test
|
| | | public void useAppContext() throws Exception {
|
| | | // Context of the app under test.
|
| | | Context appContext = InstrumentationRegistry.getTargetContext();
|
| | |
|
| | | assertEquals("test.wheelview.test", appContext.getPackageName());
|
| | | }
|
| | | }
|
New file |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
| | | package="com.contrarywind.view">
|
| | |
|
| | | </manifest>
|
New file |
| | |
| | | package com.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);
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.interfaces;
|
| | |
|
| | | /**
|
| | | * Created by Sai on 2016/7/13.
|
| | | */
|
| | | public interface IPickerViewData {
|
| | | String getPickerViewText();
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.listener;
|
| | |
|
| | | import android.view.MotionEvent;
|
| | |
|
| | | import com.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;
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.listener;
|
| | |
|
| | |
|
| | | public interface OnItemSelectedListener {
|
| | | void onItemSelected(int index);
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.timer;
|
| | |
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.util.TimerTask;
|
| | |
|
| | | /**
|
| | | * 滚动惯性的实现
|
| | | *
|
| | | * @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;
|
| | | }
|
| | | }
|
| | |
|
| | | //发送handler消息 处理平顺停止滚动逻辑
|
| | | 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);
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.timer;
|
| | |
|
| | | import android.os.Handler;
|
| | | import android.os.Message;
|
| | |
|
| | | import com.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;
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.timer;
|
| | |
|
| | | import com.contrarywind.view.WheelView;
|
| | |
|
| | | import java.util.TimerTask;
|
| | |
|
| | | /**
|
| | | * 平滑滚动的实现
|
| | | *
|
| | | * @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;
|
| | | }
|
| | | }
|
| | | }
|
New file |
| | |
| | | package com.contrarywind.view;
|
| | |
|
| | | 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.contrarywind.adapter.WheelAdapter;
|
| | | import com.contrarywind.interfaces.IPickerViewData;
|
| | | import com.contrarywind.listener.LoopViewGestureListener;
|
| | | import com.contrarywind.listener.OnItemSelectedListener;
|
| | | import com.contrarywind.timer.InertiaTimerTask;
|
| | | import com.contrarywind.timer.MessageHandler;
|
| | | import com.contrarywind.timer.SmoothScrollTimerTask;
|
| | |
|
| | | import java.util.concurrent.Executors;
|
| | | import java.util.concurrent.ScheduledExecutorService;
|
| | | import java.util.concurrent.ScheduledFuture;
|
| | | import java.util.concurrent.TimeUnit;
|
| | |
|
| | | /**
|
| | | * 3d滚轮控件
|
| | | */
|
| | | public class WheelView extends View {
|
| | |
|
| | | public enum ACTION { // 点击,滑翔(滑到尽头),拖拽事件
|
| | | CLICK, FLING, DAGGLE
|
| | | }
|
| | |
|
| | | public enum DividerType { // 分隔线类型
|
| | | FILL, WRAP, CIRCLE
|
| | | }
|
| | |
|
| | | 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 int dividerWidth;
|
| | |
|
| | | // 条目间距倍数
|
| | | private float lineSpacingMultiplier = 1.6F;
|
| | | private boolean isLoop;
|
| | |
|
| | | // 第一条线Y坐标值
|
| | | private float firstLineY;
|
| | | //第二条线Y坐标
|
| | | private float secondLineY;
|
| | | //中间label绘制的Y坐标
|
| | | private float centerY;
|
| | |
|
| | | //当前滚动总高度y值
|
| | | private float totalScrollY;
|
| | |
|
| | | //初始化默认选中项
|
| | | private int initPosition;
|
| | |
|
| | | //选中的Item是第几个
|
| | | private int selectedItem;
|
| | | private int preCurrentIndex;
|
| | |
|
| | | // 绘制几个条目,实际上第一项和最后一项Y轴压缩成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 boolean isAlphaGradient = false; //透明度渐变
|
| | |
|
| | | 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 = 4.0F;
|
| | | } 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);
|
| | | dividerWidth = a.getDimensionPixelSize(R.styleable.pickerview_wheelview_dividerWidth, 2);
|
| | | 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);
|
| | | //控件宽度,这里支持weight
|
| | | 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的position
|
| | | if (initPosition == -1) {
|
| | | if (isLoop) {
|
| | | initPosition = (adapter.getItemsCount() + 1) / 2;
|
| | | } else {
|
| | | initPosition = 0;
|
| | | }
|
| | | }
|
| | | preCurrentIndex = initPosition;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 计算最大length的Text的宽高度
|
| | | */
|
| | | 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高度的一半,滚动到下一个Item去
|
| | | mOffset = (int) (itemHeight - (float) mOffset);
|
| | | } else {
|
| | | mOffset = -mOffset;
|
| | | }
|
| | | }
|
| | | //停止的时候,位置有偏移,不是全部都能正确停止到中间位置的,这里把文字位置挪回中间去
|
| | | 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) {
|
| | | //不添加这句,当这个wheelView不可见时,默认都是0,会导致获取到的时间错误
|
| | | this.selectedItem = currentItem;
|
| | | this.initPosition = currentItem;
|
| | | totalScrollY = 0;//回归顶部,不然重设setCurrentItem的话位置会偏移的,就会显示出不对位置的数据
|
| | | invalidate();
|
| | | }
|
| | |
|
| | | public final void setOnItemSelectedListener(OnItemSelectedListener OnItemSelectedListener) {
|
| | | this.onItemSelectedListener = OnItemSelectedListener;
|
| | | }
|
| | |
|
| | | public final void setAdapter(WheelAdapter adapter) {
|
| | | this.adapter = adapter;
|
| | | reMeasure();
|
| | | invalidate();
|
| | | }
|
| | |
|
| | | public void setItemsVisibleCount(int visibleCount) {
|
| | | if (visibleCount % 2 == 0) {
|
| | | visibleCount += 1;
|
| | | }
|
| | | this.itemsVisible = visibleCount + 2; //第一条和最后一条
|
| | | }
|
| | |
|
| | | public void setAlphaGradient(boolean alphaGradient) {
|
| | | isAlphaGradient = alphaGradient;
|
| | | }
|
| | |
|
| | | 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的值不正确
|
| | | initPosition = Math.min(Math.max(0, initPosition), adapter.getItemsCount() - 1);
|
| | |
|
| | | //滚动的Y值高度除去每行Item的高度,得到滚动了多少个item,即change数
|
| | | //滚动偏移值,用于记录滚动了多少个item
|
| | | int change = (int) (totalScrollY / itemHeight);
|
| | | // Log.d("change", "" + change);
|
| | |
|
| | | try {
|
| | | //滚动中实际的预选中的item(即经过了中间位置的item) = 滑动前的位置 + 滑动相对位置
|
| | | 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,preCurrentIndex = -1,那么preCurrentIndex按循环来说,其实是0的上面,也就是4的位置
|
| | | preCurrentIndex = adapter.getItemsCount() + preCurrentIndex;
|
| | | }
|
| | | if (preCurrentIndex > adapter.getItemsCount() - 1) {//同理上面,自己脑补一下
|
| | | preCurrentIndex = preCurrentIndex - adapter.getItemsCount();
|
| | | }
|
| | | }
|
| | | //跟滚动流畅度有关,总滑动距离与每个item高度取余,即并不是一格格的滚动,每个item不一定滚到对应Rect里的,这个item对应格子的偏移值
|
| | | float itemHeightOffset = (totalScrollY % itemHeight);
|
| | |
|
| | |
|
| | | //绘制中间两条横线
|
| | | 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) {//如果超过了WheelView的边缘
|
| | | startX = 10;
|
| | | }
|
| | | endX = measuredWidth - startX;
|
| | | canvas.drawLine(startX, firstLineY, endX, firstLineY, paintIndicator);
|
| | | canvas.drawLine(startX, secondLineY, endX, secondLineY, paintIndicator);
|
| | | } else if (dividerType == DividerType.CIRCLE) {
|
| | | //分割线为圆圈形状
|
| | | paintIndicator.setStyle(Paint.Style.STROKE);
|
| | | paintIndicator.setStrokeWidth(dividerWidth);
|
| | | float startX;
|
| | | float endX;
|
| | | if (TextUtils.isEmpty(label)) {//隐藏Label的情况
|
| | | startX = (measuredWidth - maxTextWidth) / 2f - 12;
|
| | | } else {
|
| | | startX = (measuredWidth - maxTextWidth) / 4f - 12;
|
| | | }
|
| | | if (startX <= 0) {//如果超过了WheelView的边缘
|
| | | startX = 10;
|
| | | }
|
| | | endX = measuredWidth - startX;
|
| | | //半径始终以宽高中最大的来算
|
| | | float radius = Math.max((endX - startX), itemHeight) / 1.8f;
|
| | | canvas.drawCircle(measuredWidth / 2f, measuredHeight / 2f, radius, paintIndicator);
|
| | | } else {
|
| | | canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
|
| | | canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
|
| | | }
|
| | |
|
| | | //只显示选中项Label文字的模式,并且Label文字不为空,则进行绘制
|
| | | if (!TextUtils.isEmpty(label) && isCenterLabel) {
|
| | | //绘制文字,靠右并留出空隙
|
| | | int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText, label);
|
| | | canvas.drawText(label, drawRightContentStart - CENTER_CONTENT_OFFSET, centerY, paintCenterText);
|
| | | }
|
| | |
|
| | | // 设置数组中每个元素的值
|
| | | int counter = 0;
|
| | | while (counter < itemsVisible) {
|
| | | Object showText;
|
| | | int index = preCurrentIndex - (itemsVisible / 2 - counter);//索引值,即当前在控件中间的item看作数据源的中间,计算出相对源数据源的index值
|
| | |
|
| | | //判断是否循环,如果是循环数据源也使用相对循环的position获取对应的item值,如果不是循环则超出数据源范围使用""空白字符串填充,在界面上形成空白无数据的item项
|
| | | if (isLoop) {
|
| | | index = getLoopMappingIndex(index);
|
| | | showText = adapter.getItem(index);
|
| | | } else if (index < 0) {
|
| | | showText = "";
|
| | | } else if (index > adapter.getItemsCount() - 1) {
|
| | | showText = "";
|
| | | } else {
|
| | | showText = adapter.getItem(index);
|
| | | }
|
| | |
|
| | | 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 {
|
| | | //获取内容文字
|
| | | String contentText;
|
| | |
|
| | | //如果是label每项都显示的模式,并且item内容不为空、label 也不为空
|
| | | if (!isCenterLabel && !TextUtils.isEmpty(label) && !TextUtils.isEmpty(getContentText(showText))) {
|
| | | contentText = getContentText(showText) + label;
|
| | | } else {
|
| | | contentText = getContentText(showText);
|
| | | }
|
| | | // 根据当前角度计算出偏差系数,用以在绘制时控制文字的 水平移动 透明度 倾斜程度.
|
| | | float offsetCoefficient = (float) Math.pow(Math.abs(angle) / 90f, 2.2);
|
| | |
|
| | | reMeasureTextSize(contentText);
|
| | | //计算开始绘制的位置
|
| | | measuredCenterContentStart(contentText);
|
| | | measuredOutContentStart(contentText);
|
| | | float translateY = (float) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
|
| | | //根据Math.sin(radian)来更改canvas坐标系原点,然后缩放画布,使得文字高度进行缩放,形成弧形3d视觉差
|
| | | canvas.translate(0.0F, translateY);
|
| | | 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);
|
| | | setOutPaintStyle(offsetCoefficient, angle);
|
| | | 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);
|
| | | setOutPaintStyle(offsetCoefficient, angle);
|
| | | 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);
|
| | | setOutPaintStyle(offsetCoefficient, angle);
|
| | | // 控制文字水平偏移距离
|
| | | canvas.drawText(contentText, drawOutContentStart + textXOffset * offsetCoefficient, maxTextHeight, paintOuterText);
|
| | | canvas.restore();
|
| | | }
|
| | | canvas.restore();
|
| | | paintCenterText.setTextSize(textSize);
|
| | | }
|
| | | counter++;
|
| | | }
|
| | | }
|
| | |
|
| | | //设置文字倾斜角度,透明度
|
| | | private void setOutPaintStyle(float offsetCoefficient, float angle) {
|
| | | // 控制文字倾斜角度
|
| | | float DEFAULT_TEXT_TARGET_SKEW_X = 0.5f;
|
| | | int multiplier = 0;
|
| | | if (textXOffset > 0) {
|
| | | multiplier = 1;
|
| | | } else if (textXOffset < 0) {
|
| | | multiplier = -1;
|
| | | }
|
| | | paintOuterText.setTextSkewX(multiplier * (angle > 0 ? -1 : 1) * DEFAULT_TEXT_TARGET_SKEW_X * offsetCoefficient);
|
| | |
|
| | | // 控制透明度
|
| | | int alpha = isAlphaGradient ? (int) ((90F - Math.abs(angle)) / 90f * 255) : 255;
|
| | | // Log.d("WheelView", "alpha:" + alpha);
|
| | | paintOuterText.setAlpha(alpha);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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 {//只显示中间label时,时间选择器内容偏左一点,留出空间绘制单位标签
|
| | | 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 {//只显示中间label时,时间选择器内容偏左一点,留出空间绘制单位标签
|
| | | 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])
|
| | | * 根据正弦余弦转换公式 cosα = sin(π/2-α)
|
| | | * 代入,得: 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 setDividerWidth(int dividerWidth) {
|
| | | this.dividerWidth = dividerWidth;
|
| | | paintIndicator.setStrokeWidth(dividerWidth);
|
| | | }
|
| | |
|
| | | 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;
|
| | | }
|
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?>
|
| | | <resources>
|
| | | <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_dividerWidth" format="dimension"/>
|
| | | <attr name="wheelview_lineSpacingMultiplier" format="float"/>
|
| | | </declare-styleable>
|
| | | </resources> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?>
|
| | | <resources>
|
| | | <color name="pickerview_timebtn_nor">#057dff</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>
|
| | |
|
| | | </resources>
|
New file |
| | |
| | | <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>
|
New file |
| | |
| | | <resources>
|
| | | <string name="app_name">wheelview</string>
|
| | | </resources>
|