├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app-debug.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── panghaha │ │ └── it │ │ └── timepackdemo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── panghaha │ │ │ └── it │ │ │ └── timepackdemo │ │ │ ├── MainActivity.java │ │ │ └── view │ │ │ ├── ChangeDatePopwindow.java │ │ │ ├── ChangeDatePopwindow2.java │ │ │ └── wheelview │ │ │ ├── ItemsRange.java │ │ │ ├── OnWheelChangedListener.java │ │ │ ├── OnWheelClickedListener.java │ │ │ ├── OnWheelScrollListener.java │ │ │ ├── WheelAdapter.java │ │ │ ├── WheelRecycle.java │ │ │ ├── WheelScroller.java │ │ │ ├── WheelView.java │ │ │ └── adapter │ │ │ ├── AbstractWheelAdapter.java │ │ │ ├── AbstractWheelTextAdapter.java │ │ │ ├── AbstractWheelTextAdapter1.java │ │ │ ├── AdapterWheel.java │ │ │ ├── ArrayWheelAdapter.java │ │ │ ├── EnMonthWheelAdapter.java │ │ │ ├── NumericWheelAdapter.java │ │ │ └── WheelViewAdapter.java │ └── res │ │ ├── drawable │ │ ├── popu_bg.xml │ │ ├── sfdfb.PNG │ │ ├── wheel_bg.xml │ │ └── wheel_val.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── dialog_myinfo_changebirth.xml │ │ ├── dialog_myinfo_changebirth2.xml │ │ └── item_birth_year.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── panghaha │ └── it │ └── timepackdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | TimePackdemo -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TimePackdemo 2 | a many beautiful timepick for android 高仿ios时间选择器 3 | ### 4 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/1.png) 5 | ### 6 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/2.png) 7 | ### 8 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/3.png) 9 | ### 10 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/4.png) 11 | ### 12 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/5.png) 13 | ### 14 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/6.png) 15 | ### 16 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/7.png) 17 | ### 18 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/8.png) 19 | ### 20 | ![image](https://github.com/PangHaHa12138/TimePackdemo/blob/master/screenshot/9.png) 21 | -------------------------------------------------------------------------------- /app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PangHaHa12138/TimePackdemo/ce4afd2befb3e9adcc6a53535a7b6f1441d33db6/app-debug.apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.panghaha.it.timepackdemo" 9 | minSdkVersion 15 10 | targetSdkVersion 25 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:25.3.1' 26 | compile 'com.contrarywind:Android-PickerView:3.2.4' 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\htzh1\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/panghaha/it/timepackdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.panghaha.it.timepackdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.panghaha.it.timepackdemo; 2 | 3 | import android.app.DatePickerDialog; 4 | import android.app.TimePickerDialog; 5 | import android.graphics.Color; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.os.Bundle; 8 | import android.view.Gravity; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.DatePicker; 12 | import android.widget.LinearLayout; 13 | import android.widget.TimePicker; 14 | import android.widget.Toast; 15 | 16 | import com.bigkoo.pickerview.OptionsPickerView; 17 | import com.bigkoo.pickerview.TimePickerView; 18 | import com.panghaha.it.timepackdemo.view.ChangeDatePopwindow; 19 | import com.panghaha.it.timepackdemo.view.ChangeDatePopwindow2; 20 | 21 | import java.text.SimpleDateFormat; 22 | import java.util.ArrayList; 23 | import java.util.Calendar; 24 | import java.util.Date; 25 | import java.util.List; 26 | 27 | public class MainActivity extends AppCompatActivity { 28 | 29 | private Button button1,button2,button3,button4,button5,button6,button7; 30 | private String dateStr,mouth1,day1; 31 | private LinearLayout main; 32 | 33 | private static final List options1Items = new ArrayList<>(); 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_main); 38 | 39 | button1 = (Button) findViewById(R.id.button1); 40 | button2 = (Button) findViewById(R.id.button2); 41 | button3 = (Button) findViewById(R.id.button3); 42 | button4 = (Button) findViewById(R.id.button4); 43 | button5 = (Button) findViewById(R.id.button5); 44 | button6 = (Button) findViewById(R.id.button6); 45 | button7 = (Button) findViewById(R.id.button7); 46 | main = (LinearLayout) findViewById(R.id.main); 47 | final Calendar calender = Calendar.getInstance(); 48 | final Calendar calender2 = Calendar.getInstance(); 49 | button1.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View v) { 52 | DatePickerDialog dialog = new 53 | DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() { 54 | @Override 55 | public void onDateSet(DatePicker view, int year, int monthOfYear, int 56 | dayOfMonth) { 57 | 58 | if(monthOfYear<=9){ 59 | mouth1="0"+(monthOfYear+1); 60 | }else{ 61 | mouth1=String.valueOf(monthOfYear+1); 62 | } 63 | if(dayOfMonth<=9){ 64 | day1= "0"+dayOfMonth; 65 | }else{ 66 | day1=String.valueOf(dayOfMonth); 67 | } 68 | dateStr = String.valueOf(year)+"-"+mouth1+"-"+day1; 69 | button1.setText(dateStr); 70 | 71 | 72 | } 73 | }, calender.get(Calendar.YEAR), calender.get(Calendar.MONTH), 74 | calender.get(Calendar.DAY_OF_MONTH)); 75 | dialog.show(); 76 | } 77 | }); 78 | 79 | button2.setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View v) { 82 | TimePickerDialog dialog = new TimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener() { 83 | @Override 84 | public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 85 | 86 | button2.setText(String.valueOf(hourOfDay+":"+minute)); 87 | 88 | } 89 | },calender2.get(Calendar.HOUR),calender2.get(Calendar.MINUTE),false); 90 | dialog.show(); 91 | } 92 | }); 93 | 94 | button3.setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View v) { 97 | 98 | TimePickerView pvTime = new TimePickerView.Builder(MainActivity.this, new TimePickerView.OnTimeSelectListener() { 99 | @Override 100 | public void onTimeSelect(Date date2, View v) {//选中事件回调 101 | String time = getTime(date2); 102 | button3.setText(time); 103 | } 104 | }) 105 | .setType(TimePickerView.Type.YEAR_MONTH_DAY)//默认全部显示 106 | .setCancelText("取消")//取消按钮文字 107 | .setSubmitText("确定")//确认按钮文字 108 | .setContentSize(20)//滚轮文字大小 109 | .setTitleSize(20)//标题文字大小 110 | // .setTitleText("请选择时间")//标题文字 111 | .setOutSideCancelable(true)//点击屏幕,点在控件外部范围时,是否取消显示 112 | .isCyclic(true)//是否循环滚动 113 | .setTextColorCenter(Color.BLACK)//设置选中项的颜色 114 | .setTitleColor(Color.BLACK)//标题文字颜色 115 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 116 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 117 | // .setTitleBgColor(0xFF666666)//标题背景颜色 Night mode 118 | // .setBgColor(0xFF333333)//滚轮背景颜色 Night mode 119 | // .setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR) + 20)//默认是1900-2100年 120 | // .setDate(selectedDate)// 如果不设置的话,默认是系统时间*/ 121 | // .setRangDate(startDate,endDate)//起始终止年月日设定 122 | // .setLabel("年","月","日","时","分","秒") 123 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 124 | // .isDialog(true)//是否显示为对话框样式 125 | .build(); 126 | pvTime.setDate(Calendar.getInstance());//注:根据需求来决定是否使用该方法(一般是精确到秒的情况),此项可以在弹出选择器的时候重新设置当前时间,避免在初始化之后由于时间已经设定,导致选中时间与当前时间不匹配的问题。 127 | pvTime.show(); 128 | 129 | } 130 | }); 131 | options1Items.clear(); 132 | options1Items.add("托儿索"); 133 | options1Items.add("儿童劫"); 134 | options1Items.add("小学生之手"); 135 | options1Items.add("德玛西亚大保健"); 136 | options1Items.add("面对疾风吧"); 137 | options1Items.add("天王盖地虎"); 138 | options1Items.add("我发一米五"); 139 | options1Items.add("爆刘继芬"); 140 | button4.setOnClickListener(new View.OnClickListener() { 141 | @Override 142 | public void onClick(View v) { 143 | OptionsPickerView pvOptions = new OptionsPickerView.Builder(MainActivity.this, new OptionsPickerView.OnOptionsSelectListener() { 144 | @Override 145 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 146 | //返回的分别是三个级别的选中位置 147 | String s = options1Items.get(options1); 148 | button4.setText(s); 149 | 150 | } 151 | }) 152 | // .setSubmitText("确定")//确定按钮文字 153 | // .setCancelText("取消")//取消按钮文字 154 | // .setTitleText("城市选择")//标题 155 | .setSubCalSize(20)//确定和取消文字大小 156 | // .setTitleSize(20)//标题文字大小 157 | // .setTitleColor(Color.BLACK)//标题文字颜色 158 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 159 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 160 | // .setTitleBgColor(0xFF333333)//标题背景颜色 Night mode 161 | // .setBgColor(0xFF000000)//滚轮背景颜色 Night mode 162 | // .setContentTextSize(18)//滚轮文字大小 163 | // .setTextColorCenter(Color.BLUE)//设置选中项的颜色 164 | .setTextColorCenter(Color.BLACK)//设置选中项的颜色 165 | // .setLineSpacingMultiplier(1.6f)//设置两横线之间的间隔倍数 166 | // .setLinkage(false)//设置是否联动,默认true 167 | // .setLabels("省", "市", "区")//设置选择的三级单位 168 | // .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 169 | // .setCyclic(false, false, false)//循环与否 170 | // .setSelectOptions(1, 1, 1) //设置默认选中项 171 | // .setOutSideCancelable(false)//点击外部dismiss default true 172 | // .isDialog(true)//是否显示为对话框样式 173 | .build(); 174 | pvOptions.setPicker(options1Items); 175 | pvOptions.show(); 176 | } 177 | }); 178 | 179 | 180 | button5.setOnClickListener(new View.OnClickListener() { 181 | @Override 182 | public void onClick(View v) { 183 | final String[] str = new String[10]; 184 | ChangeDatePopwindow mChangeBirthDialog = new ChangeDatePopwindow(MainActivity.this); 185 | mChangeBirthDialog.setDate("2017", "6", "20"); 186 | mChangeBirthDialog.showAtLocation(main, Gravity.BOTTOM, 0, 0); 187 | mChangeBirthDialog.setBirthdayListener(new ChangeDatePopwindow.OnBirthListener() { 188 | 189 | @Override 190 | public void onClick(String year, String month, String day) { 191 | // TODO Auto-generated method stub 192 | Toast.makeText(MainActivity.this,year + "-" + month + "-" + day,Toast.LENGTH_LONG).show(); 193 | StringBuilder sb = new StringBuilder(); 194 | sb.append(year.substring(0, year.length() - 1)).append("-").append(month.substring(0, day.length() - 1)).append("-").append(day); 195 | str[0] = year + "-" + month + "-" + day; 196 | str[1] = sb.toString(); 197 | 198 | button5.setText(str[0]); 199 | 200 | } 201 | }); 202 | } 203 | }); 204 | 205 | button6.setOnClickListener(new View.OnClickListener() { 206 | @Override 207 | public void onClick(View v) { 208 | 209 | final String[] str = new String[10]; 210 | final ChangeDatePopwindow2 mChangeBirthDialog = new ChangeDatePopwindow2(MainActivity.this); 211 | mChangeBirthDialog.setDate("2017", "6", "20"); 212 | mChangeBirthDialog.showAtLocation(main, Gravity.BOTTOM, 0, 0); 213 | mChangeBirthDialog.setBirthdayListener(new ChangeDatePopwindow2.OnBirthListener() { 214 | 215 | @Override 216 | public void onClick(String year, String month, String day) { 217 | // TODO Auto-generated method stub 218 | Toast.makeText(MainActivity.this,year + "-" + month + "-" + day,Toast.LENGTH_LONG).show(); 219 | StringBuilder sb = new StringBuilder(); 220 | sb.append(year.substring(0, year.length() - 1)).append("-").append(month.substring(0, day.length() - 1)).append("-").append(day); 221 | str[0] = year + "-" + month + "-" + day; 222 | str[1] = sb.toString(); 223 | // mChangeBirthDialog.getBgtext().setText(year); 224 | // mChangeBirthDialog.update(); 225 | button6.setText(str[0]); 226 | 227 | } 228 | }); 229 | 230 | } 231 | }); 232 | 233 | button7.setOnClickListener(new View.OnClickListener() { 234 | @Override 235 | public void onClick(View v) { 236 | TimePickerView pvTime = new TimePickerView.Builder(MainActivity.this, new TimePickerView.OnTimeSelectListener() { 237 | @Override 238 | public void onTimeSelect(Date date2, View v) {//选中事件回调 239 | String time = getTime(date2); 240 | button7.setText(time); 241 | } 242 | }) 243 | .setType(TimePickerView.Type.YEAR_MONTH_DAY)//默认全部显示 244 | .setCancelText("取消")//取消按钮文字 245 | .setSubmitText("确定")//确认按钮文字 246 | .setContentSize(20)//滚轮文字大小 247 | .setTitleSize(20)//标题文字大小 248 | // .setTitleText("请选择时间")//标题文字 249 | .setOutSideCancelable(true)//点击屏幕,点在控件外部范围时,是否取消显示 250 | .isCyclic(true)//是否循环滚动 251 | .setTextColorCenter(Color.BLACK)//设置选中项的颜色 252 | .setTitleColor(Color.BLACK)//标题文字颜色 253 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 254 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 255 | // .setTitleBgColor(0xFF666666)//标题背景颜色 Night mode 256 | // .setBgColor(0xFF333333)//滚轮背景颜色 Night mode 257 | // .setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR) + 20)//默认是1900-2100年 258 | // .setDate(selectedDate)// 如果不设置的话,默认是系统时间*/ 259 | // .setRangDate(startDate,endDate)//起始终止年月日设定 260 | // .setLabel("年","月","日","时","分","秒") 261 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 262 | .isDialog(true)//是否显示为对话框样式 263 | .build(); 264 | pvTime.setDate(Calendar.getInstance());//注:根据需求来决定是否使用该方法(一般是精确到秒的情况),此项可以在弹出选择器的时候重新设置当前时间,避免在初始化之后由于时间已经设定,导致选中时间与当前时间不匹配的问题。 265 | pvTime.show(); 266 | } 267 | }); 268 | } 269 | 270 | public String getTime(Date date) {//可根据需要自行截取数据显示 271 | SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日"); 272 | return format.format(date); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/ChangeDatePopwindow.java: -------------------------------------------------------------------------------- 1 | package com.panghaha.it.timepackdemo.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.PopupWindow; 9 | import android.widget.TextView; 10 | 11 | 12 | import com.panghaha.it.timepackdemo.R; 13 | import com.panghaha.it.timepackdemo.view.wheelview.OnWheelChangedListener; 14 | import com.panghaha.it.timepackdemo.view.wheelview.OnWheelScrollListener; 15 | import com.panghaha.it.timepackdemo.view.wheelview.WheelView; 16 | import com.panghaha.it.timepackdemo.view.wheelview.adapter.AbstractWheelTextAdapter1; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Calendar; 20 | 21 | /** 22 | * Author: Chen.yuan 23 | * Email: hubeiqiyuan2010@163.com 24 | * Date: 2016/7/28 17:37 25 | * Description:日期选择window 26 | */ 27 | public class ChangeDatePopwindow extends PopupWindow implements View.OnClickListener { 28 | 29 | private Context context; 30 | private WheelView wvYear; 31 | private WheelView wvMonth; 32 | private WheelView wvDay; 33 | 34 | private TextView btnSure; 35 | private TextView btnCancel; 36 | 37 | private ArrayList arry_years = new ArrayList(); 38 | private ArrayList arry_months = new ArrayList(); 39 | private ArrayList arry_days = new ArrayList(); 40 | private CalendarTextAdapter mYearAdapter; 41 | private CalendarTextAdapter mMonthAdapter; 42 | private CalendarTextAdapter mDaydapter; 43 | 44 | private String month; 45 | private String day; 46 | 47 | private String currentYear = getYear(); 48 | private String currentMonth = getMonth(); 49 | private String currentDay = getDay(); 50 | 51 | private int maxTextSize = 24; 52 | private int minTextSize = 14; 53 | 54 | private boolean issetdata = false; 55 | 56 | private String selectYear; 57 | private String selectMonth; 58 | private String selectDay; 59 | 60 | private OnBirthListener onBirthListener; 61 | 62 | public ChangeDatePopwindow(final Context context) { 63 | super(context); 64 | this.context = context; 65 | View view=View.inflate(context, R.layout.dialog_myinfo_changebirth,null); 66 | wvYear = (WheelView) view.findViewById(R.id.wv_birth_year); 67 | wvMonth = (WheelView) view.findViewById(R.id.wv_birth_month); 68 | wvDay = (WheelView) view.findViewById(R.id.wv_birth_day); 69 | btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure); 70 | btnCancel = (TextView) view.findViewById(R.id.btn_myinfo_cancel); 71 | 72 | //设置SelectPicPopupWindow的View 73 | this.setContentView(view); 74 | //设置SelectPicPopupWindow弹出窗体的宽 75 | this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 76 | //设置SelectPicPopupWindow弹出窗体的高 77 | this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); 78 | //设置SelectPicPopupWindow弹出窗体可点击 79 | this.setFocusable(true); 80 | //设置SelectPicPopupWindow弹出窗体动画效果 81 | // this.setAnimationStyle(R.style.AnimBottom); 82 | //实例化一个ColorDrawable颜色为半透明 83 | ColorDrawable dw = new ColorDrawable(0xb0000000); 84 | //设置SelectPicPopupWindow弹出窗体的背景 85 | this.setBackgroundDrawable(dw); 86 | 87 | btnSure.setOnClickListener(this); 88 | btnCancel.setOnClickListener(this); 89 | 90 | if (!issetdata) { 91 | initData(); 92 | } 93 | initYears(); 94 | mYearAdapter = new CalendarTextAdapter(context, arry_years, setYear(currentYear), maxTextSize, minTextSize); 95 | wvYear.setVisibleItems(5); 96 | wvYear.setViewAdapter(mYearAdapter); 97 | wvYear.setCurrentItem(setYear(currentYear)); 98 | 99 | initMonths(Integer.parseInt(month)); 100 | mMonthAdapter = new CalendarTextAdapter(context, arry_months, setMonth(currentMonth), maxTextSize, minTextSize); 101 | wvMonth.setVisibleItems(5); 102 | wvMonth.setViewAdapter(mMonthAdapter); 103 | wvMonth.setCurrentItem(setMonth(currentMonth)); 104 | 105 | initDays(Integer.parseInt(day)); 106 | mDaydapter = new CalendarTextAdapter(context, arry_days, Integer.parseInt(currentDay) - 1, maxTextSize, minTextSize); 107 | wvDay.setVisibleItems(5); 108 | wvDay.setViewAdapter(mDaydapter); 109 | wvDay.setCurrentItem(Integer.parseInt(currentDay) - 1); 110 | 111 | wvYear.addChangingListener(new OnWheelChangedListener() { 112 | 113 | @Override 114 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 115 | // TODO Auto-generated method stub 116 | String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem()); 117 | selectYear = currentText; 118 | setTextviewSize(currentText, mYearAdapter); 119 | currentYear = currentText.substring(0, currentText.length()-1).toString(); 120 | Log.d("currentYear==",currentYear); 121 | setYear(currentYear); 122 | initMonths(Integer.parseInt(month)); 123 | mMonthAdapter = new CalendarTextAdapter(context, arry_months, 0, maxTextSize, minTextSize); 124 | wvMonth.setVisibleItems(5); 125 | wvMonth.setViewAdapter(mMonthAdapter); 126 | wvMonth.setCurrentItem(0); 127 | 128 | calDays(currentYear, month); 129 | } 130 | }); 131 | 132 | wvYear.addScrollingListener(new OnWheelScrollListener() { 133 | 134 | @Override 135 | public void onScrollingStarted(WheelView wheel) { 136 | // TODO Auto-generated method stub 137 | 138 | } 139 | 140 | @Override 141 | public void onScrollingFinished(WheelView wheel) { 142 | // TODO Auto-generated method stub 143 | String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem()); 144 | setTextviewSize(currentText, mYearAdapter); 145 | } 146 | }); 147 | 148 | wvMonth.addChangingListener(new OnWheelChangedListener() { 149 | 150 | @Override 151 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 152 | // TODO Auto-generated method stub 153 | String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem()); 154 | selectMonth = currentText; 155 | setTextviewSize(currentText, mMonthAdapter); 156 | setMonth(currentText.substring(0, 1)); 157 | initDays(Integer.parseInt(day)); 158 | mDaydapter = new CalendarTextAdapter(context, arry_days, 0, maxTextSize, minTextSize); 159 | wvDay.setVisibleItems(5); 160 | wvDay.setViewAdapter(mDaydapter); 161 | wvDay.setCurrentItem(0); 162 | 163 | calDays(currentYear, month); 164 | } 165 | }); 166 | 167 | wvMonth.addScrollingListener(new OnWheelScrollListener() { 168 | 169 | @Override 170 | public void onScrollingStarted(WheelView wheel) { 171 | // TODO Auto-generated method stub 172 | 173 | } 174 | 175 | @Override 176 | public void onScrollingFinished(WheelView wheel) { 177 | // TODO Auto-generated method stub 178 | String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem()); 179 | setTextviewSize(currentText, mMonthAdapter); 180 | } 181 | }); 182 | 183 | wvDay.addChangingListener(new OnWheelChangedListener() { 184 | 185 | @Override 186 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 187 | // TODO Auto-generated method stub 188 | String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem()); 189 | setTextviewSize(currentText, mDaydapter); 190 | selectDay = currentText; 191 | } 192 | }); 193 | 194 | wvDay.addScrollingListener(new OnWheelScrollListener() { 195 | 196 | @Override 197 | public void onScrollingStarted(WheelView wheel) { 198 | // TODO Auto-generated method stub 199 | 200 | } 201 | 202 | @Override 203 | public void onScrollingFinished(WheelView wheel) { 204 | // TODO Auto-generated method stub 205 | String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem()); 206 | setTextviewSize(currentText, mDaydapter); 207 | } 208 | }); 209 | } 210 | 211 | 212 | public void initYears() { 213 | for (int i = Integer.parseInt(getYear()); i > 1950; i--) { 214 | arry_years.add(i + "年"); 215 | } 216 | } 217 | 218 | public void initMonths(int months) { 219 | arry_months.clear(); 220 | for (int i = 1; i <= months; i++) { 221 | arry_months.add(i + "月"); 222 | } 223 | } 224 | 225 | public void initDays(int days) { 226 | arry_days.clear(); 227 | for (int i = 1; i <= days; i++) { 228 | arry_days.add(i + "日"); 229 | } 230 | } 231 | 232 | private class CalendarTextAdapter extends AbstractWheelTextAdapter1 { 233 | ArrayList list; 234 | 235 | protected CalendarTextAdapter(Context context, ArrayList list, int currentItem, int maxsize, int minsize) { 236 | super(context, R.layout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize); 237 | this.list = list; 238 | setItemTextResource(R.id.tempValue); 239 | } 240 | 241 | @Override 242 | public View getItem(int index, View cachedView, ViewGroup parent) { 243 | View view = super.getItem(index, cachedView, parent); 244 | return view; 245 | } 246 | 247 | @Override 248 | public int getItemsCount() { 249 | return list.size(); 250 | } 251 | 252 | @Override 253 | protected CharSequence getItemText(int index) { 254 | return list.get(index) + ""; 255 | } 256 | } 257 | 258 | public void setBirthdayListener(OnBirthListener onBirthListener) { 259 | this.onBirthListener = onBirthListener; 260 | } 261 | 262 | @Override 263 | public void onClick(View v) { 264 | 265 | if (v == btnSure) { 266 | if (onBirthListener != null) { 267 | onBirthListener.onClick(selectYear, selectMonth, selectDay); 268 | Log.d("cy",""+selectYear+""+selectMonth+""+selectDay); 269 | } 270 | } else if (v == btnSure) { 271 | 272 | } else { 273 | dismiss(); 274 | } 275 | dismiss(); 276 | 277 | } 278 | 279 | public interface OnBirthListener { 280 | public void onClick(String year, String month, String day); 281 | } 282 | 283 | /** 284 | * 设置字体大小 285 | * 286 | * @param curriteItemText 287 | * @param adapter 288 | */ 289 | public void setTextviewSize(String curriteItemText, CalendarTextAdapter adapter) { 290 | ArrayList arrayList = adapter.getTestViews(); 291 | int size = arrayList.size(); 292 | String currentText; 293 | for (int i = 0; i < size; i++) { 294 | TextView textvew = (TextView) arrayList.get(i); 295 | currentText = textvew.getText().toString(); 296 | if (curriteItemText.equals(currentText)) { 297 | textvew.setTextSize(maxTextSize); 298 | } else { 299 | textvew.setTextSize(minTextSize); 300 | } 301 | } 302 | } 303 | 304 | public String getYear() { 305 | Calendar c = Calendar.getInstance(); 306 | return c.get(Calendar.YEAR)+""; 307 | } 308 | 309 | public String getMonth() { 310 | Calendar c = Calendar.getInstance(); 311 | return c.get(Calendar.MONTH) + 1+""; 312 | } 313 | 314 | public String getDay() { 315 | Calendar c = Calendar.getInstance(); 316 | return c.get(Calendar.DATE)+""; 317 | } 318 | 319 | public void initData() { 320 | setDate(getYear(), getMonth(), getDay()); 321 | this.currentDay = 1+""; 322 | this.currentMonth = 1+""; 323 | } 324 | 325 | /** 326 | * 设置年月日 327 | * 328 | * @param year 329 | * @param month 330 | * @param day 331 | */ 332 | public void setDate(String year, String month, String day) { 333 | selectYear = year + "年"; 334 | selectMonth = month + "月"; 335 | selectDay = day + "日"; 336 | issetdata = true; 337 | this.currentYear = year; 338 | this.currentMonth = month; 339 | this.currentDay = day; 340 | if (year == getYear()) { 341 | this.month = getMonth(); 342 | } else { 343 | this.month = 12+""; 344 | } 345 | calDays(year, month); 346 | } 347 | 348 | /** 349 | * 设置年份 350 | * 351 | * @param year 352 | */ 353 | public int setYear(String year) { 354 | int yearIndex = 0; 355 | if (!year.equals(getYear())) { 356 | this.month = 12+""; 357 | } else { 358 | this.month = getMonth(); 359 | } 360 | for (int i = Integer.parseInt(getYear()); i > 1950; i--) { 361 | if (i == Integer.parseInt(year)) { 362 | return yearIndex; 363 | } 364 | yearIndex++; 365 | } 366 | return yearIndex; 367 | } 368 | 369 | /** 370 | * 设置月份 371 | * 372 | * @param month 373 | * @param month 374 | * @return 375 | */ 376 | public int setMonth(String month) { 377 | int monthIndex = 0; 378 | calDays(currentYear, month); 379 | for (int i = 1; i < Integer.parseInt(this.month); i++) { 380 | if (Integer.parseInt(month) == i) { 381 | return monthIndex; 382 | } else { 383 | monthIndex++; 384 | } 385 | } 386 | return monthIndex; 387 | } 388 | 389 | /** 390 | * 计算每月多少天 391 | * 392 | * @param month 393 | * @param year 394 | */ 395 | public void calDays(String year, String month) { 396 | boolean leayyear = false; 397 | if (Integer.parseInt(year) % 4 == 0 && Integer.parseInt(year) % 100 != 0) { 398 | leayyear = true; 399 | } else { 400 | leayyear = false; 401 | } 402 | for (int i = 1; i <= 12; i++) { 403 | switch (Integer.parseInt(month)) { 404 | case 1: 405 | case 3: 406 | case 5: 407 | case 7: 408 | case 8: 409 | case 10: 410 | case 12: 411 | this.day = 31+""; 412 | break; 413 | case 2: 414 | if (leayyear) { 415 | this.day = 29+""; 416 | } else { 417 | this.day = 28+""; 418 | } 419 | break; 420 | case 4: 421 | case 6: 422 | case 9: 423 | case 11: 424 | this.day = 30+""; 425 | break; 426 | } 427 | } 428 | if (year.equals( getYear()) && month .equals( getMonth())) { 429 | this.day = getDay(); 430 | } 431 | } 432 | } -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/ChangeDatePopwindow2.java: -------------------------------------------------------------------------------- 1 | package com.panghaha.it.timepackdemo.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.util.Log; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.PopupWindow; 10 | import android.widget.TextView; 11 | 12 | import com.panghaha.it.timepackdemo.R; 13 | import com.panghaha.it.timepackdemo.view.wheelview.OnWheelChangedListener; 14 | import com.panghaha.it.timepackdemo.view.wheelview.OnWheelScrollListener; 15 | import com.panghaha.it.timepackdemo.view.wheelview.WheelView; 16 | import com.panghaha.it.timepackdemo.view.wheelview.adapter.AbstractWheelTextAdapter1; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Calendar; 20 | 21 | /** 22 | * Author: Chen.yuan 23 | * Email: hubeiqiyuan2010@163.com 24 | * Date: 2016/7/28 17:37 25 | * Description:日期选择window 26 | */ 27 | public class ChangeDatePopwindow2 extends PopupWindow implements View.OnClickListener { 28 | 29 | private Context context; 30 | private WheelView wvYear; 31 | private WheelView wvMonth; 32 | private WheelView wvDay; 33 | 34 | private TextView btnSure; 35 | private TextView btnCancel; 36 | private TextView bgtext; 37 | 38 | private ArrayList arry_years = new ArrayList(); 39 | private ArrayList arry_months = new ArrayList(); 40 | private ArrayList arry_days = new ArrayList(); 41 | private CalendarTextAdapter mYearAdapter; 42 | private CalendarTextAdapter mMonthAdapter; 43 | private CalendarTextAdapter mDaydapter; 44 | 45 | private String month; 46 | private String day; 47 | 48 | private String currentYear = getYear(); 49 | private String currentMonth = getMonth(); 50 | private String currentDay = getDay(); 51 | 52 | private int maxTextSize = 24; 53 | private int minTextSize = 14; 54 | 55 | private boolean issetdata = false; 56 | 57 | private String selectYear; 58 | private String selectMonth; 59 | private String selectDay; 60 | 61 | private OnBirthListener onBirthListener; 62 | 63 | public ChangeDatePopwindow2(final Context context) { 64 | super(context); 65 | this.context = context; 66 | final View view=View.inflate(context, R.layout.dialog_myinfo_changebirth2,null); 67 | wvYear = (WheelView) view.findViewById(R.id.wv_birth_year); 68 | wvMonth = (WheelView) view.findViewById(R.id.wv_birth_month); 69 | wvDay = (WheelView) view.findViewById(R.id.wv_birth_day); 70 | btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure); 71 | // btnCancel = (TextView) view.findViewById(R.id.btn_myinfo_cancel); 72 | bgtext = (TextView) view.findViewById(R.id.bgtext); 73 | //设置SelectPicPopupWindow的View 74 | this.setContentView(view); 75 | //设置SelectPicPopupWindow弹出窗体的宽 76 | this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); 77 | //设置SelectPicPopupWindow弹出窗体的高 78 | this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); 79 | //设置SelectPicPopupWindow弹出窗体可点击 80 | this.setFocusable(true); 81 | //设置SelectPicPopupWindow弹出窗体动画效果 82 | // this.setAnimationStyle(R.style.AnimBottom); 83 | //实例化一个ColorDrawable颜色为半透明 84 | ColorDrawable dw = new ColorDrawable(0xb0000000); 85 | //设置SelectPicPopupWindow弹出窗体的背景 86 | this.setBackgroundDrawable(dw); 87 | 88 | // bgtext.setText(getYear()); 89 | btnSure.setOnClickListener(this); 90 | // btnCancel.setOnClickListener(this); 91 | 92 | // 单击弹出窗以外处 关闭弹出窗 93 | view.setOnTouchListener(new View.OnTouchListener() { 94 | 95 | @Override 96 | public boolean onTouch(View v, MotionEvent event) { 97 | // TODO Auto-generated method stub 98 | int height = view.findViewById(R.id.ly_myinfo_changeaddress_child).getTop(); 99 | int y = (int) event.getY(); 100 | if (event.getAction() == MotionEvent.ACTION_UP) { 101 | if (y < height) { 102 | dismiss(); 103 | } 104 | } 105 | return true; 106 | } 107 | }); 108 | 109 | if (!issetdata) { 110 | initData(); 111 | } 112 | initYears(); 113 | mYearAdapter = new CalendarTextAdapter(context, arry_years, setYear(currentYear), maxTextSize, minTextSize); 114 | wvYear.setVisibleItems(5); 115 | wvYear.setViewAdapter(mYearAdapter); 116 | wvYear.setCurrentItem(setYear(currentYear)); 117 | 118 | initMonths(Integer.parseInt(month)); 119 | mMonthAdapter = new CalendarTextAdapter(context, arry_months, setMonth(currentMonth), maxTextSize, minTextSize); 120 | wvMonth.setVisibleItems(5); 121 | wvMonth.setViewAdapter(mMonthAdapter); 122 | wvMonth.setCurrentItem(setMonth(currentMonth)); 123 | 124 | initDays(Integer.parseInt(day)); 125 | mDaydapter = new CalendarTextAdapter(context, arry_days, Integer.parseInt(currentDay) - 1, maxTextSize, minTextSize); 126 | wvDay.setVisibleItems(5); 127 | wvDay.setViewAdapter(mDaydapter); 128 | wvDay.setCurrentItem(Integer.parseInt(currentDay) - 1); 129 | 130 | wvYear.addChangingListener(new OnWheelChangedListener() { 131 | 132 | @Override 133 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 134 | // TODO Auto-generated method stub 135 | String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem()); 136 | selectYear = currentText; 137 | setTextviewSize(currentText, mYearAdapter); 138 | currentYear = currentText.substring(0, currentText.length()-1).toString(); 139 | Log.d("currentYear==",currentYear); 140 | setYear(currentYear); 141 | initMonths(Integer.parseInt(month)); 142 | mMonthAdapter = new CalendarTextAdapter(context, arry_months, 0, maxTextSize, minTextSize); 143 | wvMonth.setVisibleItems(5); 144 | wvMonth.setViewAdapter(mMonthAdapter); 145 | wvMonth.setCurrentItem(0); 146 | 147 | calDays(currentYear, month); 148 | } 149 | }); 150 | 151 | wvYear.addScrollingListener(new OnWheelScrollListener() { 152 | 153 | @Override 154 | public void onScrollingStarted(WheelView wheel) { 155 | // TODO Auto-generated method stub 156 | 157 | } 158 | 159 | @Override 160 | public void onScrollingFinished(WheelView wheel) { 161 | // TODO Auto-generated method stub 162 | String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem()); 163 | setTextviewSize(currentText, mYearAdapter); 164 | } 165 | }); 166 | 167 | wvMonth.addChangingListener(new OnWheelChangedListener() { 168 | 169 | @Override 170 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 171 | // TODO Auto-generated method stub 172 | String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem()); 173 | selectMonth = currentText; 174 | setTextviewSize(currentText, mMonthAdapter); 175 | setMonth(currentText.substring(0, 1)); 176 | initDays(Integer.parseInt(day)); 177 | mDaydapter = new CalendarTextAdapter(context, arry_days, 0, maxTextSize, minTextSize); 178 | wvDay.setVisibleItems(5); 179 | wvDay.setViewAdapter(mDaydapter); 180 | wvDay.setCurrentItem(0); 181 | 182 | calDays(currentYear, month); 183 | } 184 | }); 185 | 186 | wvMonth.addScrollingListener(new OnWheelScrollListener() { 187 | 188 | @Override 189 | public void onScrollingStarted(WheelView wheel) { 190 | // TODO Auto-generated method stub 191 | 192 | } 193 | 194 | @Override 195 | public void onScrollingFinished(WheelView wheel) { 196 | // TODO Auto-generated method stub 197 | String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem()); 198 | setTextviewSize(currentText, mMonthAdapter); 199 | } 200 | }); 201 | 202 | wvDay.addChangingListener(new OnWheelChangedListener() { 203 | 204 | @Override 205 | public void onChanged(WheelView wheel, int oldValue, int newValue) { 206 | // TODO Auto-generated method stub 207 | String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem()); 208 | setTextviewSize(currentText, mDaydapter); 209 | selectDay = currentText; 210 | } 211 | }); 212 | 213 | wvDay.addScrollingListener(new OnWheelScrollListener() { 214 | 215 | @Override 216 | public void onScrollingStarted(WheelView wheel) { 217 | // TODO Auto-generated method stub 218 | 219 | } 220 | 221 | @Override 222 | public void onScrollingFinished(WheelView wheel) { 223 | // TODO Auto-generated method stub 224 | String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem()); 225 | setTextviewSize(currentText, mDaydapter); 226 | } 227 | }); 228 | } 229 | 230 | public TextView getBgtext(){ 231 | 232 | return bgtext; 233 | } 234 | 235 | 236 | public void initYears() { 237 | for (int i = Integer.parseInt(getYear()); i > 1950; i--) { 238 | arry_years.add(i + "年"); 239 | } 240 | } 241 | 242 | public void initMonths(int months) { 243 | arry_months.clear(); 244 | for (int i = 1; i <= months; i++) { 245 | arry_months.add(i + "月"); 246 | } 247 | } 248 | 249 | public void initDays(int days) { 250 | arry_days.clear(); 251 | for (int i = 1; i <= days; i++) { 252 | arry_days.add(i + "日"); 253 | } 254 | } 255 | 256 | private class CalendarTextAdapter extends AbstractWheelTextAdapter1 { 257 | ArrayList list; 258 | 259 | protected CalendarTextAdapter(Context context, ArrayList list, int currentItem, int maxsize, int minsize) { 260 | super(context, R.layout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize); 261 | this.list = list; 262 | setItemTextResource(R.id.tempValue); 263 | } 264 | 265 | @Override 266 | public View getItem(int index, View cachedView, ViewGroup parent) { 267 | View view = super.getItem(index, cachedView, parent); 268 | return view; 269 | } 270 | 271 | @Override 272 | public int getItemsCount() { 273 | return list.size(); 274 | } 275 | 276 | @Override 277 | protected CharSequence getItemText(int index) { 278 | return list.get(index) + ""; 279 | } 280 | } 281 | 282 | public void setBirthdayListener(OnBirthListener onBirthListener) { 283 | this.onBirthListener = onBirthListener; 284 | } 285 | 286 | @Override 287 | public void onClick(View v) { 288 | 289 | if (v == btnSure) { 290 | if (onBirthListener != null) { 291 | onBirthListener.onClick(selectYear, selectMonth, selectDay); 292 | Log.d("cy",""+selectYear+""+selectMonth+""+selectDay); 293 | } 294 | } 295 | 296 | dismiss(); 297 | } 298 | 299 | public interface OnBirthListener { 300 | public void onClick(String year, String month, String day); 301 | } 302 | 303 | /** 304 | * 设置字体大小 305 | * 306 | * @param curriteItemText 307 | * @param adapter 308 | */ 309 | public void setTextviewSize(String curriteItemText, CalendarTextAdapter adapter) { 310 | ArrayList arrayList = adapter.getTestViews(); 311 | int size = arrayList.size(); 312 | String currentText; 313 | for (int i = 0; i < size; i++) { 314 | TextView textvew = (TextView) arrayList.get(i); 315 | currentText = textvew.getText().toString(); 316 | if (curriteItemText.equals(currentText)) { 317 | textvew.setTextSize(maxTextSize); 318 | } else { 319 | textvew.setTextSize(minTextSize); 320 | } 321 | } 322 | } 323 | 324 | public String getYear() { 325 | Calendar c = Calendar.getInstance(); 326 | return c.get(Calendar.YEAR)+""; 327 | } 328 | 329 | public String getMonth() { 330 | Calendar c = Calendar.getInstance(); 331 | return c.get(Calendar.MONTH) + 1+""; 332 | } 333 | 334 | public String getDay() { 335 | Calendar c = Calendar.getInstance(); 336 | return c.get(Calendar.DATE)+""; 337 | } 338 | 339 | public void initData() { 340 | setDate(getYear(), getMonth(), getDay()); 341 | this.currentDay = 1+""; 342 | this.currentMonth = 1+""; 343 | } 344 | 345 | /** 346 | * 设置年月日 347 | * 348 | * @param year 349 | * @param month 350 | * @param day 351 | */ 352 | public void setDate(String year, String month, String day) { 353 | selectYear = year + "年"; 354 | selectMonth = month + "月"; 355 | selectDay = day + "日"; 356 | issetdata = true; 357 | this.currentYear = year; 358 | this.currentMonth = month; 359 | this.currentDay = day; 360 | if (year == getYear()) { 361 | this.month = getMonth(); 362 | } else { 363 | this.month = 12+""; 364 | } 365 | calDays(year, month); 366 | } 367 | 368 | /** 369 | * 设置年份 370 | * 371 | * @param year 372 | */ 373 | public int setYear(String year) { 374 | int yearIndex = 0; 375 | if (!year.equals(getYear())) { 376 | this.month = 12+""; 377 | } else { 378 | this.month = getMonth(); 379 | } 380 | for (int i = Integer.parseInt(getYear()); i > 1950; i--) { 381 | if (i == Integer.parseInt(year)) { 382 | return yearIndex; 383 | } 384 | yearIndex++; 385 | } 386 | return yearIndex; 387 | } 388 | 389 | /** 390 | * 设置月份 391 | * 392 | * @param month 393 | * @param month 394 | * @return 395 | */ 396 | public int setMonth(String month) { 397 | int monthIndex = 0; 398 | calDays(currentYear, month); 399 | for (int i = 1; i < Integer.parseInt(this.month); i++) { 400 | if (Integer.parseInt(month) == i) { 401 | return monthIndex; 402 | } else { 403 | monthIndex++; 404 | } 405 | } 406 | return monthIndex; 407 | } 408 | 409 | /** 410 | * 计算每月多少天 411 | * 412 | * @param month 413 | * @param year 414 | */ 415 | public void calDays(String year, String month) { 416 | boolean leayyear = false; 417 | if (Integer.parseInt(year) % 4 == 0 && Integer.parseInt(year) % 100 != 0) { 418 | leayyear = true; 419 | } else { 420 | leayyear = false; 421 | } 422 | for (int i = 1; i <= 12; i++) { 423 | switch (Integer.parseInt(month)) { 424 | case 1: 425 | case 3: 426 | case 5: 427 | case 7: 428 | case 8: 429 | case 10: 430 | case 12: 431 | this.day = 31+""; 432 | break; 433 | case 2: 434 | if (leayyear) { 435 | this.day = 29+""; 436 | } else { 437 | this.day = 28+""; 438 | } 439 | break; 440 | case 4: 441 | case 6: 442 | case 9: 443 | case 11: 444 | this.day = 30+""; 445 | break; 446 | } 447 | } 448 | if (year.equals( getYear()) && month .equals( getMonth())) { 449 | this.day = getDay(); 450 | } 451 | } 452 | } -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/ItemsRange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Android Wheel Control. 3 | * https://code.google.com/p/android-wheel/ 4 | * 5 | * Copyright 2011 Yuri Kanivets 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.panghaha.it.timepackdemo.view.wheelview; 21 | 22 | /** 23 | * Range for visible items. 24 | */ 25 | public class ItemsRange { 26 | // First item number 27 | private int first; 28 | 29 | // Items count 30 | private int count; 31 | 32 | /** 33 | * Default constructor. Creates an empty range 34 | */ 35 | public ItemsRange() { 36 | this(0, 0); 37 | } 38 | 39 | /** 40 | * Constructor 41 | * @param first the number of first item 42 | * @param count the count of items 43 | */ 44 | public ItemsRange(int first, int count) { 45 | this.first = first; 46 | this.count = count; 47 | } 48 | 49 | /** 50 | * Gets number of first item 51 | * @return the number of the first item 52 | */ 53 | public int getFirst() { 54 | return first; 55 | } 56 | 57 | /** 58 | * Gets number of last item 59 | * @return the number of last item 60 | */ 61 | public int getLast() { 62 | return getFirst() + getCount() - 1; 63 | } 64 | 65 | /** 66 | * Get items count 67 | * @return the count of items 68 | */ 69 | public int getCount() { 70 | return count; 71 | } 72 | 73 | /** 74 | * Tests whether item is contained by range 75 | * @param index the item number 76 | * @return true if item is contained 77 | */ 78 | public boolean contains(int index) { 79 | return index >= getFirst() && index <= getLast(); 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/OnWheelChangedListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview; 18 | 19 | /** 20 | * Wheel changed listener interface. 21 | *

The onChanged() method is called whenever current wheel positions is changed: 22 | *

  • New Wheel position is set 23 | *
  • Wheel view is scrolled 24 | */ 25 | public interface OnWheelChangedListener { 26 | /** 27 | * Callback method to be invoked when current item changed 28 | * @param wheel the wheel view whose state has changed 29 | * @param oldValue the old value of current item 30 | * @param newValue the new value of current item 31 | */ 32 | void onChanged(WheelView wheel, int oldValue, int newValue); 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/OnWheelClickedListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview; 18 | 19 | /** 20 | * Wheel clicked listener interface. 21 | *

    The onItemClicked() method is called whenever a wheel item is clicked 22 | *

  • New Wheel position is set 23 | *
  • Wheel view is scrolled 24 | */ 25 | public interface OnWheelClickedListener { 26 | /** 27 | * Callback method to be invoked when current item clicked 28 | * @param wheel the wheel view 29 | * @param itemIndex the index of clicked item 30 | */ 31 | void onItemClicked(WheelView wheel, int itemIndex); 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/OnWheelScrollListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview; 18 | 19 | /** 20 | * Wheel scrolled listener interface. 21 | */ 22 | public interface OnWheelScrollListener { 23 | /** 24 | * Callback method to be invoked when scrolling started. 25 | * @param wheel the wheel view whose state has changed. 26 | */ 27 | void onScrollingStarted(WheelView wheel); 28 | 29 | /** 30 | * Callback method to be invoked when scrolling ended. 31 | * @param wheel the wheel view whose state has changed. 32 | */ 33 | void onScrollingFinished(WheelView wheel); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/WheelAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview; 18 | 19 | /** 20 | * Wheel adapter interface 21 | * 22 | * @deprecated Use WheelViewAdapter 23 | */ 24 | public interface WheelAdapter { 25 | /** 26 | * Gets items count 27 | * @return the count of wheel items 28 | */ 29 | public int getItemsCount(); 30 | 31 | /** 32 | * Gets a wheel item by index. 33 | * 34 | * @param index the item index 35 | * @return the wheel item text or null 36 | */ 37 | public String getItem(int index); 38 | 39 | /** 40 | * Gets maximum item length. It is used to determine the wheel width. 41 | * If -1 is returned there will be used the default wheel width. 42 | * 43 | * @return the maximum item length or -1 44 | */ 45 | public int getMaximumLength(); 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/WheelRecycle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Android Wheel Control. 3 | * https://code.google.com/p/android-wheel/ 4 | * 5 | * Copyright 2011 Yuri Kanivets 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.panghaha.it.timepackdemo.view.wheelview; 21 | 22 | import android.view.View; 23 | import android.widget.LinearLayout; 24 | 25 | import java.util.LinkedList; 26 | import java.util.List; 27 | 28 | /** 29 | * Recycle stores wheel items to reuse. 30 | */ 31 | public class WheelRecycle { 32 | // Cached items 33 | private List items; 34 | 35 | // Cached empty items 36 | private List emptyItems; 37 | 38 | // Wheel view 39 | private WheelView wheel; 40 | 41 | /** 42 | * Constructor 43 | * @param wheel the wheel view 44 | */ 45 | public WheelRecycle(WheelView wheel) { 46 | this.wheel = wheel; 47 | } 48 | 49 | /** 50 | * Recycles items from specified layout. 51 | * There are saved only items not included to specified range. 52 | * All the cached items are removed from original layout. 53 | * 54 | * @param layout the layout containing items to be cached 55 | * @param firstItem the number of first item in layout 56 | * @param range the range of current wheel items 57 | * @return the new value of first item number 58 | */ 59 | public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) { 60 | int index = firstItem; 61 | for (int i = 0; i < layout.getChildCount();) { 62 | if (!range.contains(index)) { 63 | recycleView(layout.getChildAt(i), index); 64 | layout.removeViewAt(i); 65 | if (i == 0) { // first item 66 | firstItem++; 67 | } 68 | } else { 69 | i++; // go to next item 70 | } 71 | index++; 72 | } 73 | return firstItem; 74 | } 75 | 76 | /** 77 | * Gets item view 78 | * @return the cached view 79 | */ 80 | public View getItem() { 81 | return getCachedView(items); 82 | } 83 | 84 | /** 85 | * Gets empty item view 86 | * @return the cached empty view 87 | */ 88 | public View getEmptyItem() { 89 | return getCachedView(emptyItems); 90 | } 91 | 92 | /** 93 | * Clears all views 94 | */ 95 | public void clearAll() { 96 | if (items != null) { 97 | items.clear(); 98 | } 99 | if (emptyItems != null) { 100 | emptyItems.clear(); 101 | } 102 | } 103 | 104 | /** 105 | * Adds view to specified cache. Creates a cache list if it is null. 106 | * @param view the view to be cached 107 | * @param cache the cache list 108 | * @return the cache list 109 | */ 110 | private List addView(View view, List cache) { 111 | if (cache == null) { 112 | cache = new LinkedList(); 113 | } 114 | 115 | cache.add(view); 116 | return cache; 117 | } 118 | 119 | /** 120 | * Adds view to cache. Determines view type (item view or empty one) by index. 121 | * @param view the view to be cached 122 | * @param index the index of view 123 | */ 124 | private void recycleView(View view, int index) { 125 | int count = wheel.getViewAdapter().getItemsCount(); 126 | 127 | if ((index < 0 || index >= count) && !wheel.isCyclic()) { 128 | // empty view 129 | emptyItems = addView(view, emptyItems); 130 | } else { 131 | while (index < 0) { 132 | index = count + index; 133 | } 134 | index %= count; 135 | items = addView(view, items); 136 | } 137 | } 138 | 139 | /** 140 | * Gets view from specified cache. 141 | * @param cache the cache 142 | * @return the first view from cache. 143 | */ 144 | private View getCachedView(List cache) { 145 | if (cache != null && cache.size() > 0) { 146 | View view = cache.get(0); 147 | cache.remove(0); 148 | return view; 149 | } 150 | return null; 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/WheelScroller.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Android Wheel Control. 3 | * https://code.google.com/p/android-wheel/ 4 | * 5 | * Copyright 2011 Yuri Kanivets 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.panghaha.it.timepackdemo.view.wheelview; 21 | 22 | import android.content.Context; 23 | import android.os.Handler; 24 | import android.os.Message; 25 | import android.view.GestureDetector; 26 | import android.view.GestureDetector.SimpleOnGestureListener; 27 | import android.view.MotionEvent; 28 | import android.view.animation.Interpolator; 29 | import android.widget.Scroller; 30 | 31 | /** 32 | * Scroller class handles scrolling events and updates the 33 | */ 34 | public class WheelScroller { 35 | /** 36 | * Scrolling listener interface 37 | */ 38 | public interface ScrollingListener { 39 | /** 40 | * Scrolling callback called when scrolling is performed. 41 | * @param distance the distance to scroll 42 | */ 43 | void onScroll(int distance); 44 | 45 | /** 46 | * Starting callback called when scrolling is started 47 | */ 48 | void onStarted(); 49 | 50 | /** 51 | * Finishing callback called after justifying 52 | */ 53 | void onFinished(); 54 | 55 | /** 56 | * Justifying callback called to justify a view when scrolling is ended 57 | */ 58 | void onJustify(); 59 | } 60 | 61 | /** Scrolling duration */ 62 | private static final int SCROLLING_DURATION = 400; 63 | 64 | /** Minimum delta for scrolling */ 65 | public static final int MIN_DELTA_FOR_SCROLLING = 1; 66 | 67 | // Listener 68 | private ScrollingListener listener; 69 | 70 | // Context 71 | private Context context; 72 | 73 | // Scrolling 74 | private GestureDetector gestureDetector; 75 | private Scroller scroller; 76 | private int lastScrollY; 77 | private float lastTouchedY; 78 | private boolean isScrollingPerformed; 79 | 80 | /** 81 | * Constructor 82 | * @param context the current context 83 | * @param listener the scrolling listener 84 | */ 85 | public WheelScroller(Context context, ScrollingListener listener) { 86 | gestureDetector = new GestureDetector(context, gestureListener); 87 | gestureDetector.setIsLongpressEnabled(false); 88 | 89 | scroller = new Scroller(context); 90 | 91 | this.listener = listener; 92 | this.context = context; 93 | } 94 | 95 | /** 96 | * Set the the specified scrolling interpolator 97 | * @param interpolator the interpolator 98 | */ 99 | public void setInterpolator(Interpolator interpolator) { 100 | scroller.forceFinished(true); 101 | scroller = new Scroller(context, interpolator); 102 | } 103 | 104 | /** 105 | * Scroll the wheel 106 | * @param distance the scrolling distance 107 | * @param time the scrolling duration 108 | */ 109 | public void scroll(int distance, int time) { 110 | scroller.forceFinished(true); 111 | 112 | lastScrollY = 0; 113 | 114 | scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION); 115 | setNextMessage(MESSAGE_SCROLL); 116 | 117 | startScrolling(); 118 | } 119 | 120 | /** 121 | * Stops scrolling 122 | */ 123 | public void stopScrolling() { 124 | scroller.forceFinished(true); 125 | } 126 | 127 | /** 128 | * Handles Touch event 129 | * @param event the motion event 130 | * @return 131 | */ 132 | public boolean onTouchEvent(MotionEvent event) { 133 | switch (event.getAction()) { 134 | case MotionEvent.ACTION_DOWN: 135 | lastTouchedY = event.getY(); 136 | scroller.forceFinished(true); 137 | clearMessages(); 138 | break; 139 | 140 | case MotionEvent.ACTION_MOVE: 141 | // perform scrolling 142 | int distanceY = (int)(event.getY() - lastTouchedY); 143 | if (distanceY != 0) { 144 | startScrolling(); 145 | listener.onScroll(distanceY); 146 | lastTouchedY = event.getY(); 147 | } 148 | break; 149 | } 150 | 151 | if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) { 152 | justify(); 153 | } 154 | 155 | return true; 156 | } 157 | 158 | // gesture listener 159 | private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() { 160 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 161 | // Do scrolling in onTouchEvent() since onScroll() are not call immediately 162 | // when user touch and move the wheel 163 | return true; 164 | } 165 | 166 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 167 | lastScrollY = 0; 168 | final int maxY = 0x7FFFFFFF; 169 | final int minY = -maxY; 170 | scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY); 171 | setNextMessage(MESSAGE_SCROLL); 172 | return true; 173 | } 174 | }; 175 | 176 | // Messages 177 | private final int MESSAGE_SCROLL = 0; 178 | private final int MESSAGE_JUSTIFY = 1; 179 | 180 | /** 181 | * Set next message to queue. Clears queue before. 182 | * 183 | * @param message the message to set 184 | */ 185 | private void setNextMessage(int message) { 186 | clearMessages(); 187 | animationHandler.sendEmptyMessage(message); 188 | } 189 | 190 | /** 191 | * Clears messages from queue 192 | */ 193 | private void clearMessages() { 194 | animationHandler.removeMessages(MESSAGE_SCROLL); 195 | animationHandler.removeMessages(MESSAGE_JUSTIFY); 196 | } 197 | 198 | // animation handler 199 | private Handler animationHandler = new Handler() { 200 | public void handleMessage(Message msg) { 201 | scroller.computeScrollOffset(); 202 | int currY = scroller.getCurrY(); 203 | int delta = lastScrollY - currY; 204 | lastScrollY = currY; 205 | if (delta != 0) { 206 | listener.onScroll(delta); 207 | } 208 | 209 | // scrolling is not finished when it comes to final Y 210 | // so, finish it manually 211 | if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) { 212 | currY = scroller.getFinalY(); 213 | scroller.forceFinished(true); 214 | } 215 | if (!scroller.isFinished()) { 216 | animationHandler.sendEmptyMessage(msg.what); 217 | } else if (msg.what == MESSAGE_SCROLL) { 218 | justify(); 219 | } else { 220 | finishScrolling(); 221 | } 222 | } 223 | }; 224 | 225 | /** 226 | * Justifies wheel 227 | */ 228 | private void justify() { 229 | listener.onJustify(); 230 | setNextMessage(MESSAGE_JUSTIFY); 231 | } 232 | 233 | /** 234 | * Starts scrolling 235 | */ 236 | private void startScrolling() { 237 | if (!isScrollingPerformed) { 238 | isScrollingPerformed = true; 239 | listener.onStarted(); 240 | } 241 | } 242 | 243 | /** 244 | * Finishes scrolling 245 | */ 246 | void finishScrolling() { 247 | if (isScrollingPerformed) { 248 | listener.onFinished(); 249 | isScrollingPerformed = false; 250 | } 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/WheelView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Android Wheel Control. 3 | * https://code.google.com/p/android-wheel/ 4 | * 5 | * Copyright 2011 Yuri Kanivets 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.panghaha.it.timepackdemo.view.wheelview; 21 | 22 | import android.content.Context; 23 | import android.database.DataSetObserver; 24 | import android.graphics.Canvas; 25 | import android.graphics.Paint; 26 | import android.graphics.drawable.Drawable; 27 | import android.graphics.drawable.GradientDrawable; 28 | import android.graphics.drawable.GradientDrawable.Orientation; 29 | import android.util.AttributeSet; 30 | import android.view.MotionEvent; 31 | import android.view.View; 32 | import android.view.ViewGroup.LayoutParams; 33 | import android.view.animation.Interpolator; 34 | import android.widget.LinearLayout; 35 | 36 | import com.panghaha.it.timepackdemo.R; 37 | import com.panghaha.it.timepackdemo.view.wheelview.adapter.WheelViewAdapter; 38 | 39 | import java.util.LinkedList; 40 | import java.util.List; 41 | 42 | /** 43 | * Numeric wheel view. 44 | * 45 | * @author Yuri Kanivets 46 | */ 47 | public class WheelView extends View { 48 | 49 | /** Top and bottom shadows colors */ 50 | /*/ Modified by wulianghuan 2014-11-25 51 | private int[] SHADOWS_COLORS = new int[] { 0xFF111111, 52 | 0x00AAAAAA, 0x00AAAAAA }; 53 | //*/ 54 | private int[] SHADOWS_COLORS = new int[] {0xFFFFFFFF, 0x00FFFFFF, 0x00FFFFFF }; 55 | 56 | /** Top and bottom items offset (to hide that) */ 57 | private static final int ITEM_OFFSET_PERCENT = 0; 58 | 59 | /** Left and right padding value */ 60 | private static final int PADDING = 10; 61 | 62 | /** Default count of visible items */ 63 | private static final int DEF_VISIBLE_ITEMS = 5; 64 | 65 | // Wheel Values 66 | private int currentItem = 0; 67 | 68 | // Count of visible items 69 | private int visibleItems = DEF_VISIBLE_ITEMS; 70 | 71 | // Item height 72 | private int itemHeight = 0; 73 | 74 | // Center Line 75 | private Drawable centerDrawable; 76 | 77 | // Wheel drawables 78 | private int wheelBackground = R.drawable.wheel_bg; 79 | private int wheelForeground = R.drawable.wheel_val; 80 | 81 | // Shadows drawables 82 | private GradientDrawable topShadow; 83 | private GradientDrawable bottomShadow; 84 | 85 | // Draw Shadows 86 | private boolean drawShadows = true; 87 | 88 | // Scrolling 89 | private WheelScroller scroller; 90 | private boolean isScrollingPerformed; 91 | private int scrollingOffset; 92 | 93 | // Cyclic 94 | boolean isCyclic = false; 95 | 96 | // Items layout 97 | private LinearLayout itemsLayout; 98 | 99 | // The number of first item in layout 100 | private int firstItem; 101 | 102 | // View adapter 103 | private WheelViewAdapter viewAdapter; 104 | 105 | // Recycle 106 | private WheelRecycle recycle = new WheelRecycle(this); 107 | 108 | // Listeners 109 | private List changingListeners = new LinkedList(); 110 | private List scrollingListeners = new LinkedList(); 111 | private List clickingListeners = new LinkedList(); 112 | 113 | String label=""; 114 | 115 | /** 116 | * Constructor 117 | */ 118 | public WheelView(Context context, AttributeSet attrs, int defStyle) { 119 | super(context, attrs, defStyle); 120 | initData(context); 121 | } 122 | 123 | /** 124 | * Constructor 125 | */ 126 | public WheelView(Context context, AttributeSet attrs) { 127 | super(context, attrs); 128 | initData(context); 129 | } 130 | 131 | /** 132 | * Constructor 133 | */ 134 | public WheelView(Context context) { 135 | super(context); 136 | initData(context); 137 | } 138 | 139 | /** 140 | * Initializes class data 141 | * @param context the context 142 | */ 143 | private void initData(Context context) { 144 | scroller = new WheelScroller(getContext(), scrollingListener); 145 | } 146 | 147 | // Scrolling listener 148 | WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() { 149 | @Override 150 | public void onStarted() { 151 | isScrollingPerformed = true; 152 | notifyScrollingListenersAboutStart(); 153 | } 154 | 155 | @Override 156 | public void onScroll(int distance) { 157 | doScroll(distance); 158 | 159 | int height = getHeight(); 160 | if (scrollingOffset > height) { 161 | scrollingOffset = height; 162 | scroller.stopScrolling(); 163 | } else if (scrollingOffset < -height) { 164 | scrollingOffset = -height; 165 | scroller.stopScrolling(); 166 | } 167 | } 168 | 169 | @Override 170 | public void onFinished() { 171 | if (isScrollingPerformed) { 172 | notifyScrollingListenersAboutEnd(); 173 | isScrollingPerformed = false; 174 | } 175 | 176 | scrollingOffset = 0; 177 | invalidate(); 178 | } 179 | 180 | @Override 181 | public void onJustify() { 182 | if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) { 183 | scroller.scroll(scrollingOffset, 0); 184 | } 185 | } 186 | }; 187 | 188 | /** 189 | * Set the the specified scrolling interpolator 190 | * @param interpolator the interpolator 191 | */ 192 | public void setInterpolator(Interpolator interpolator) { 193 | scroller.setInterpolator(interpolator); 194 | } 195 | 196 | /** 197 | * Gets count of visible items 198 | * 199 | * @return the count of visible items 200 | */ 201 | public int getVisibleItems() { 202 | return visibleItems; 203 | } 204 | 205 | /** 206 | * Sets the desired count of visible items. 207 | * Actual amount of visible items depends on wheel layout parameters. 208 | * To apply changes and rebuild view call measure(). 209 | * 210 | * @param count the desired count for visible items 211 | */ 212 | public void setVisibleItems(int count) { 213 | visibleItems = count; 214 | } 215 | 216 | /** 217 | * Gets view adapter 218 | * @return the view adapter 219 | */ 220 | public WheelViewAdapter getViewAdapter() { 221 | return viewAdapter; 222 | } 223 | 224 | // Adapter listener 225 | private DataSetObserver dataObserver = new DataSetObserver() { 226 | @Override 227 | public void onChanged() { 228 | invalidateWheel(false); 229 | } 230 | 231 | @Override 232 | public void onInvalidated() { 233 | invalidateWheel(true); 234 | } 235 | }; 236 | 237 | /** 238 | * Sets view adapter. Usually new adapters contain different views, so 239 | * it needs to rebuild view by calling measure(). 240 | * 241 | * @param viewAdapter the view adapter 242 | */ 243 | public void setViewAdapter(WheelViewAdapter viewAdapter) { 244 | if (this.viewAdapter != null) { 245 | this.viewAdapter.unregisterDataSetObserver(dataObserver); 246 | } 247 | this.viewAdapter = viewAdapter; 248 | if (this.viewAdapter != null) { 249 | this.viewAdapter.registerDataSetObserver(dataObserver); 250 | } 251 | 252 | invalidateWheel(true); 253 | } 254 | 255 | /** 256 | * Adds wheel changing listener 257 | * @param listener the listener 258 | */ 259 | public void addChangingListener(OnWheelChangedListener listener) { 260 | changingListeners.add(listener); 261 | } 262 | 263 | /** 264 | * Removes wheel changing listener 265 | * @param listener the listener 266 | */ 267 | public void removeChangingListener(OnWheelChangedListener listener) { 268 | changingListeners.remove(listener); 269 | } 270 | 271 | /** 272 | * Notifies changing listeners 273 | * @param oldValue the old wheel value 274 | * @param newValue the new wheel value 275 | */ 276 | protected void notifyChangingListeners(int oldValue, int newValue) { 277 | for (OnWheelChangedListener listener : changingListeners) { 278 | listener.onChanged(this, oldValue, newValue); 279 | } 280 | } 281 | 282 | /** 283 | * Adds wheel scrolling listener 284 | * @param listener the listener 285 | */ 286 | public void addScrollingListener(OnWheelScrollListener listener) { 287 | scrollingListeners.add(listener); 288 | } 289 | 290 | /** 291 | * Removes wheel scrolling listener 292 | * @param listener the listener 293 | */ 294 | public void removeScrollingListener(OnWheelScrollListener listener) { 295 | scrollingListeners.remove(listener); 296 | } 297 | 298 | /** 299 | * Notifies listeners about starting scrolling 300 | */ 301 | protected void notifyScrollingListenersAboutStart() { 302 | for (OnWheelScrollListener listener : scrollingListeners) { 303 | listener.onScrollingStarted(this); 304 | } 305 | } 306 | 307 | /** 308 | * Notifies listeners about ending scrolling 309 | */ 310 | protected void notifyScrollingListenersAboutEnd() { 311 | for (OnWheelScrollListener listener : scrollingListeners) { 312 | listener.onScrollingFinished(this); 313 | } 314 | } 315 | 316 | /** 317 | * Adds wheel clicking listener 318 | * @param listener the listener 319 | */ 320 | public void addClickingListener(OnWheelClickedListener listener) { 321 | clickingListeners.add(listener); 322 | } 323 | 324 | /** 325 | * Removes wheel clicking listener 326 | * @param listener the listener 327 | */ 328 | public void removeClickingListener(OnWheelClickedListener listener) { 329 | clickingListeners.remove(listener); 330 | } 331 | 332 | /** 333 | * Notifies listeners about clicking 334 | */ 335 | protected void notifyClickListenersAboutClick(int item) { 336 | for (OnWheelClickedListener listener : clickingListeners) { 337 | listener.onItemClicked(this, item); 338 | } 339 | } 340 | 341 | /** 342 | * Gets current value 343 | * 344 | * @return the current value 345 | */ 346 | public int getCurrentItem() { 347 | return currentItem; 348 | } 349 | 350 | /** 351 | * Sets the current item. Does nothing when index is wrong. 352 | * 353 | * @param index the item index 354 | * @param animated the animation flag 355 | */ 356 | public void setCurrentItem(int index, boolean animated) { 357 | if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { 358 | return; // throw? 359 | } 360 | 361 | int itemCount = viewAdapter.getItemsCount(); 362 | if (index < 0 || index >= itemCount) { 363 | if (isCyclic) { 364 | while (index < 0) { 365 | index += itemCount; 366 | } 367 | index %= itemCount; 368 | } else{ 369 | return; // throw? 370 | } 371 | } 372 | if (index != currentItem) { 373 | if (animated) { 374 | int itemsToScroll = index - currentItem; 375 | if (isCyclic) { 376 | int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem); 377 | if (scroll < Math.abs(itemsToScroll)) { 378 | itemsToScroll = itemsToScroll < 0 ? scroll : -scroll; 379 | } 380 | } 381 | scroll(itemsToScroll, 0); 382 | } else { 383 | scrollingOffset = 0; 384 | 385 | int old = currentItem; 386 | currentItem = index; 387 | 388 | notifyChangingListeners(old, currentItem); 389 | 390 | invalidate(); 391 | } 392 | } 393 | } 394 | 395 | /** 396 | * Sets the current item w/o animation. Does nothing when index is wrong. 397 | * 398 | * @param index the item index 399 | */ 400 | public void setCurrentItem(int index) { 401 | setCurrentItem(index, false); 402 | } 403 | 404 | /** 405 | * Tests if wheel is cyclic. That means before the 1st item there is shown the last one 406 | * @return true if wheel is cyclic 407 | */ 408 | public boolean isCyclic() { 409 | return isCyclic; 410 | } 411 | 412 | /** 413 | * Set wheel cyclic flag 414 | * @param isCyclic the flag to set 415 | */ 416 | public void setCyclic(boolean isCyclic) { 417 | this.isCyclic = isCyclic; 418 | invalidateWheel(false); 419 | } 420 | 421 | /** 422 | * Determine whether shadows are drawn 423 | * @return true is shadows are drawn 424 | */ 425 | public boolean drawShadows() { 426 | return drawShadows; 427 | } 428 | 429 | /** 430 | * Set whether shadows should be drawn 431 | * @param drawShadows flag as true or false 432 | */ 433 | public void setDrawShadows(boolean drawShadows) { 434 | this.drawShadows = drawShadows; 435 | } 436 | 437 | /** 438 | * Set the shadow gradient color 439 | * @param start 440 | * @param middle 441 | * @param end 442 | */ 443 | public void setShadowColor(int start, int middle, int end) { 444 | SHADOWS_COLORS = new int[] {start, middle, end}; 445 | } 446 | 447 | /** 448 | * Sets the drawable for the wheel background 449 | * @param resource 450 | */ 451 | public void setWheelBackground(int resource) { 452 | wheelBackground = resource; 453 | setBackgroundResource(wheelBackground); 454 | } 455 | 456 | /** 457 | * Sets the drawable for the wheel foreground 458 | * @param resource 459 | */ 460 | public void setWheelForeground(int resource) { 461 | wheelForeground = resource; 462 | centerDrawable = getContext().getResources().getDrawable(wheelForeground); 463 | } 464 | 465 | /** 466 | * Invalidates wheel 467 | * @param clearCaches if true then cached views will be clear 468 | */ 469 | public void invalidateWheel(boolean clearCaches) { 470 | if (clearCaches) { 471 | recycle.clearAll(); 472 | if (itemsLayout != null) { 473 | itemsLayout.removeAllViews(); 474 | } 475 | scrollingOffset = 0; 476 | } else if (itemsLayout != null) { 477 | // cache all items 478 | recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); 479 | } 480 | 481 | invalidate(); 482 | } 483 | 484 | /** 485 | * Initializes resources 486 | */ 487 | private void initResourcesIfNecessary() { 488 | if (centerDrawable == null) { 489 | centerDrawable = getContext().getResources().getDrawable(wheelForeground); 490 | } 491 | 492 | if (topShadow == null) { 493 | topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS); 494 | } 495 | 496 | if (bottomShadow == null) { 497 | bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS); 498 | } 499 | 500 | setBackgroundResource(wheelBackground); 501 | } 502 | 503 | /** 504 | * Calculates desired height for layout 505 | * 506 | * @param layout 507 | * the source layout 508 | * @return the desired layout height 509 | */ 510 | private int getDesiredHeight(LinearLayout layout) { 511 | if (layout != null && layout.getChildAt(0) != null) { 512 | itemHeight = layout.getChildAt(0).getMeasuredHeight(); 513 | } 514 | 515 | int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50; 516 | 517 | return Math.max(desired, getSuggestedMinimumHeight()); 518 | } 519 | 520 | /** 521 | * Returns height of wheel item 522 | * @return the item height 523 | */ 524 | private int getItemHeight() { 525 | if (itemHeight != 0) { 526 | return itemHeight; 527 | } 528 | 529 | if (itemsLayout != null && itemsLayout.getChildAt(0) != null) { 530 | itemHeight = itemsLayout.getChildAt(0).getHeight(); 531 | return itemHeight; 532 | } 533 | 534 | return getHeight() / visibleItems; 535 | } 536 | 537 | /** 538 | * Calculates control width and creates text layouts 539 | * @param widthSize the input layout width 540 | * @param mode the layout mode 541 | * @return the calculated control width 542 | */ 543 | private int calculateLayoutWidth(int widthSize, int mode) { 544 | initResourcesIfNecessary(); 545 | 546 | // TODO: make it static 547 | itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 548 | itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED), 549 | MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 550 | int width = itemsLayout.getMeasuredWidth(); 551 | 552 | if (mode == MeasureSpec.EXACTLY) { 553 | width = widthSize; 554 | } else { 555 | width += 2 * PADDING; 556 | 557 | // Check against our minimum width 558 | width = Math.max(width, getSuggestedMinimumWidth()); 559 | 560 | if (mode == MeasureSpec.AT_MOST && widthSize < width) { 561 | width = widthSize; 562 | } 563 | } 564 | 565 | itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY), 566 | MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 567 | 568 | return width; 569 | } 570 | 571 | @Override 572 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 573 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 574 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 575 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 576 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 577 | 578 | buildViewForMeasuring(); 579 | 580 | int width = calculateLayoutWidth(widthSize, widthMode); 581 | 582 | int height; 583 | if (heightMode == MeasureSpec.EXACTLY) { 584 | height = heightSize; 585 | } else { 586 | height = getDesiredHeight(itemsLayout); 587 | 588 | if (heightMode == MeasureSpec.AT_MOST) { 589 | height = Math.min(height, heightSize); 590 | } 591 | } 592 | 593 | setMeasuredDimension(width, height); 594 | } 595 | 596 | @Override 597 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 598 | layout(r - l, b - t); 599 | } 600 | 601 | /** 602 | * Sets layouts width and height 603 | * @param width the layout width 604 | * @param height the layout height 605 | */ 606 | private void layout(int width, int height) { 607 | int itemsWidth = width - 2 * PADDING; 608 | 609 | itemsLayout.layout(0, 0, itemsWidth, height); 610 | } 611 | 612 | @Override 613 | protected void onDraw(Canvas canvas) { 614 | super.onDraw(canvas); 615 | 616 | if (viewAdapter != null && viewAdapter.getItemsCount() > 0) { 617 | updateView(); 618 | 619 | drawItems(canvas); 620 | drawCenterRect(canvas); 621 | } 622 | 623 | if (drawShadows) drawShadows(canvas); 624 | } 625 | 626 | /** 627 | * Draws shadows on top and bottom of control 628 | * @param canvas the canvas for drawing 629 | */ 630 | private void drawShadows(Canvas canvas) { 631 | /*/ Modified by wulianghuan 2014-11-25 632 | int height = (int)(1.5 * getItemHeight()); 633 | //*/ 634 | int height = (int)(3 * getItemHeight()); 635 | //*/ 636 | //topShadow.setBounds(0, 0, getWidth(), height); 637 | topShadow.setBounds(0, 0, getWidth(), getHeight()); 638 | topShadow.draw(canvas); 639 | 640 | //bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight()); 641 | bottomShadow.setBounds(0, 0, getWidth(), getHeight()); 642 | bottomShadow.draw(canvas); 643 | } 644 | 645 | /** 646 | * Draws items 647 | * @param canvas the canvas for drawing 648 | */ 649 | private void drawItems(Canvas canvas) { 650 | canvas.save(); 651 | 652 | int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2; 653 | canvas.translate(PADDING, - top + scrollingOffset); 654 | 655 | itemsLayout.draw(canvas); 656 | 657 | canvas.restore(); 658 | } 659 | 660 | /** 661 | * Draws rect for current value 662 | * @param canvas the canvas for drawing 663 | */ 664 | private void drawCenterRect(Canvas canvas) { 665 | int center = getHeight() / 2; 666 | int offset = (int) (getItemHeight() / 2 * 1.2); 667 | // int offset = 60; 668 | /*/ Remarked by wulianghuan 2014-11-27 使用自己的画线,而不是描边 669 | Rect rect = new Rect(left, top, right, bottom) 670 | centerDrawable.setBounds(bounds) 671 | centerDrawable.setBounds(0, center - offset, getWidth(), center + offset); 672 | centerDrawable.draw(canvas); 673 | //*/ 674 | Paint paint = new Paint(); 675 | paint.setColor(getResources().getColor(R.color.province_line_border)); 676 | // 设置线宽 677 | // paint.setStrokeWidth((float) 3); 678 | paint.setStrokeWidth((float) 2); 679 | // 绘制上边直线 680 | canvas.drawLine(0, center - offset, getWidth(), center - offset, paint); 681 | // 绘制下边直线 682 | canvas.drawLine(0, center + offset, getWidth(), center + offset, paint); 683 | //*/ 684 | } 685 | 686 | @Override 687 | public boolean onTouchEvent(MotionEvent event) { 688 | if (!isEnabled() || getViewAdapter() == null) { 689 | return true; 690 | } 691 | 692 | switch (event.getAction()) { 693 | case MotionEvent.ACTION_MOVE: 694 | if (getParent() != null) { 695 | getParent().requestDisallowInterceptTouchEvent(true); 696 | } 697 | break; 698 | 699 | case MotionEvent.ACTION_UP: 700 | if (!isScrollingPerformed) { 701 | int distance = (int) event.getY() - getHeight() / 2; 702 | if (distance > 0) { 703 | distance += getItemHeight() / 2; 704 | } else { 705 | distance -= getItemHeight() / 2; 706 | } 707 | int items = distance / getItemHeight(); 708 | if (items != 0 && isValidItemIndex(currentItem + items)) { 709 | notifyClickListenersAboutClick(currentItem + items); 710 | } 711 | } 712 | break; 713 | } 714 | 715 | return scroller.onTouchEvent(event); 716 | } 717 | 718 | /** 719 | * Scrolls the wheel 720 | * @param delta the scrolling value 721 | */ 722 | private void doScroll(int delta) { 723 | scrollingOffset += delta; 724 | 725 | int itemHeight = getItemHeight(); 726 | int count = scrollingOffset / itemHeight; 727 | 728 | int pos = currentItem - count; 729 | int itemCount = viewAdapter.getItemsCount(); 730 | 731 | int fixPos = scrollingOffset % itemHeight; 732 | if (Math.abs(fixPos) <= itemHeight / 2) { 733 | fixPos = 0; 734 | } 735 | if (isCyclic && itemCount > 0) { 736 | if (fixPos > 0) { 737 | pos--; 738 | count++; 739 | } else if (fixPos < 0) { 740 | pos++; 741 | count--; 742 | } 743 | // fix position by rotating 744 | while (pos < 0) { 745 | pos += itemCount; 746 | } 747 | pos %= itemCount; 748 | } else { 749 | // 750 | if (pos < 0) { 751 | count = currentItem; 752 | pos = 0; 753 | } else if (pos >= itemCount) { 754 | count = currentItem - itemCount + 1; 755 | pos = itemCount - 1; 756 | } else if (pos > 0 && fixPos > 0) { 757 | pos--; 758 | count++; 759 | } else if (pos < itemCount - 1 && fixPos < 0) { 760 | pos++; 761 | count--; 762 | } 763 | } 764 | 765 | int offset = scrollingOffset; 766 | if (pos != currentItem) { 767 | setCurrentItem(pos, false); 768 | } else { 769 | invalidate(); 770 | } 771 | 772 | // update offset 773 | scrollingOffset = offset - count * itemHeight; 774 | if (scrollingOffset > getHeight()) { 775 | scrollingOffset = scrollingOffset % getHeight() + getHeight(); 776 | } 777 | } 778 | 779 | /** 780 | * Scroll the wheel 781 | * @param itemsToScroll items to scroll 782 | * @param time scrolling duration 783 | */ 784 | public void scroll(int itemsToScroll, int time) { 785 | int distance = itemsToScroll * getItemHeight() - scrollingOffset; 786 | scroller.scroll(distance, time); 787 | } 788 | 789 | /** 790 | * Calculates range for wheel items 791 | * @return the items range 792 | */ 793 | private ItemsRange getItemsRange() { 794 | if (getItemHeight() == 0) { 795 | return null; 796 | } 797 | 798 | int first = currentItem; 799 | int count = 1; 800 | 801 | while (count * getItemHeight() < getHeight()) { 802 | first--; 803 | count += 2; // top + bottom items 804 | } 805 | 806 | if (scrollingOffset != 0) { 807 | if (scrollingOffset > 0) { 808 | first--; 809 | } 810 | count++; 811 | 812 | // process empty items above the first or below the second 813 | int emptyItems = scrollingOffset / getItemHeight(); 814 | first -= emptyItems; 815 | count += Math.asin(emptyItems); 816 | } 817 | return new ItemsRange(first, count); 818 | } 819 | 820 | /** 821 | * Rebuilds wheel items if necessary. Caches all unused items. 822 | * 823 | * @return true if items are rebuilt 824 | */ 825 | private boolean rebuildItems() { 826 | boolean updated = false; 827 | ItemsRange range = getItemsRange(); 828 | if (itemsLayout != null) { 829 | int first = recycle.recycleItems(itemsLayout, firstItem, range); 830 | updated = firstItem != first; 831 | firstItem = first; 832 | } else { 833 | createItemsLayout(); 834 | updated = true; 835 | } 836 | 837 | if (!updated) { 838 | updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount(); 839 | } 840 | 841 | if (firstItem > range.getFirst() && firstItem <= range.getLast()) { 842 | for (int i = firstItem - 1; i >= range.getFirst(); i--) { 843 | if (!addViewItem(i, true)) { 844 | break; 845 | } 846 | firstItem = i; 847 | } 848 | } else { 849 | firstItem = range.getFirst(); 850 | } 851 | 852 | int first = firstItem; 853 | for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) { 854 | if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) { 855 | first++; 856 | } 857 | } 858 | firstItem = first; 859 | 860 | return updated; 861 | } 862 | 863 | /** 864 | * Updates view. Rebuilds items and label if necessary, recalculate items sizes. 865 | */ 866 | private void updateView() { 867 | if (rebuildItems()) { 868 | calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY); 869 | layout(getWidth(), getHeight()); 870 | } 871 | } 872 | 873 | /** 874 | * Creates item layouts if necessary 875 | */ 876 | private void createItemsLayout() { 877 | if (itemsLayout == null) { 878 | itemsLayout = new LinearLayout(getContext()); 879 | itemsLayout.setOrientation(LinearLayout.VERTICAL); 880 | } 881 | } 882 | 883 | /** 884 | * Builds view for measuring 885 | */ 886 | private void buildViewForMeasuring() { 887 | // clear all items 888 | if (itemsLayout != null) { 889 | recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); 890 | } else { 891 | createItemsLayout(); 892 | } 893 | 894 | // add views 895 | int addItems = visibleItems / 2; 896 | for (int i = currentItem + addItems; i >= currentItem - addItems; i--) { 897 | if (addViewItem(i, true)) { 898 | firstItem = i; 899 | } 900 | } 901 | } 902 | 903 | /** 904 | * Adds view for item to items layout 905 | * @param index the item index 906 | * @param first the flag indicates if view should be first 907 | * @return true if corresponding item exists and is added 908 | */ 909 | private boolean addViewItem(int index, boolean first) { 910 | View view = getItemView(index); 911 | if (view != null) { 912 | if (first) { 913 | itemsLayout.addView(view, 0); 914 | } else { 915 | itemsLayout.addView(view); 916 | } 917 | 918 | return true; 919 | } 920 | 921 | return false; 922 | } 923 | 924 | /** 925 | * Checks whether intem index is valid 926 | * @param index the item index 927 | * @return true if item index is not out of bounds or the wheel is cyclic 928 | */ 929 | private boolean isValidItemIndex(int index) { 930 | return viewAdapter != null && viewAdapter.getItemsCount() > 0 && 931 | (isCyclic || index >= 0 && index < viewAdapter.getItemsCount()); 932 | } 933 | 934 | /** 935 | * Returns view for specified item 936 | * @param index the item index 937 | * @return item view or empty view if index is out of bounds 938 | */ 939 | private View getItemView(int index) { 940 | if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { 941 | return null; 942 | } 943 | int count = viewAdapter.getItemsCount(); 944 | if (!isValidItemIndex(index)) { 945 | return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout); 946 | } else { 947 | while (index < 0) { 948 | index = count + index; 949 | } 950 | } 951 | 952 | index %= count; 953 | return viewAdapter.getItem(index, recycle.getItem(), itemsLayout); 954 | } 955 | 956 | /** 957 | * Stops scrolling 958 | */ 959 | public void stopScrolling() { 960 | scroller.stopScrolling(); 961 | } 962 | } 963 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/AbstractWheelAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 18 | 19 | import android.database.DataSetObserver; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | import java.util.LinkedList; 24 | import java.util.List; 25 | 26 | /** 27 | * Abstract Wheel adapter. 28 | */ 29 | public abstract class AbstractWheelAdapter implements WheelViewAdapter { 30 | // Observers 31 | private List datasetObservers; 32 | 33 | @Override 34 | public View getEmptyItem(View convertView, ViewGroup parent) { 35 | return null; 36 | } 37 | 38 | @Override 39 | public void registerDataSetObserver(DataSetObserver observer) { 40 | if (datasetObservers == null) { 41 | datasetObservers = new LinkedList(); 42 | } 43 | datasetObservers.add(observer); 44 | } 45 | 46 | @Override 47 | public void unregisterDataSetObserver(DataSetObserver observer) { 48 | if (datasetObservers != null) { 49 | datasetObservers.remove(observer); 50 | } 51 | } 52 | 53 | /** 54 | * Notifies observers about data changing 55 | */ 56 | protected void notifyDataChangedEvent() { 57 | if (datasetObservers != null) { 58 | for (DataSetObserver observer : datasetObservers) { 59 | observer.onChanged(); 60 | } 61 | } 62 | } 63 | 64 | /** 65 | * Notifies observers about invalidating data 66 | */ 67 | protected void notifyDataInvalidatedEvent() { 68 | if (datasetObservers != null) { 69 | for (DataSetObserver observer : datasetObservers) { 70 | observer.onInvalidated(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/AbstractWheelTextAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 17 | 18 | import android.content.Context; 19 | import android.text.TextUtils; 20 | import android.util.Log; 21 | import android.view.Gravity; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.TextView; 26 | 27 | /** 28 | * Abstract wheel adapter provides common functionality for adapters. 29 | */ 30 | public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter { 31 | 32 | /** Text view resource. Used as a default view for adapter. */ 33 | public static final int TEXT_VIEW_ITEM_RESOURCE = -1; 34 | 35 | /** No resource constant. */ 36 | protected static final int NO_RESOURCE = 0; 37 | 38 | /** Default text color */ 39 | public static final int DEFAULT_TEXT_COLOR = 0xFF585858; 40 | 41 | /** Default text color */ 42 | public static final int LABEL_COLOR = 0xFF700070; 43 | 44 | /** Default text size */ 45 | public static final int DEFAULT_TEXT_SIZE = 18; 46 | 47 | // Text settings 48 | private int textColor = DEFAULT_TEXT_COLOR; 49 | private int textSize = DEFAULT_TEXT_SIZE; 50 | 51 | // Current context 52 | protected Context context; 53 | // Layout inflater 54 | protected LayoutInflater inflater; 55 | 56 | // Items resources 57 | protected int itemResourceId; 58 | protected int itemTextResourceId; 59 | 60 | // Empty items resources 61 | protected int emptyItemResourceId; 62 | 63 | /** 64 | * Constructor 65 | * @param context the current context 66 | */ 67 | protected AbstractWheelTextAdapter(Context context) { 68 | this(context, TEXT_VIEW_ITEM_RESOURCE); 69 | } 70 | 71 | /** 72 | * Constructor 73 | * @param context the current context 74 | * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views 75 | */ 76 | protected AbstractWheelTextAdapter(Context context, int itemResource) { 77 | this(context, itemResource, NO_RESOURCE); 78 | } 79 | 80 | /** 81 | * Constructor 82 | * @param context the current context 83 | * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views 84 | * @param itemTextResource the resource ID for a text view in the item layout 85 | */ 86 | protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) { 87 | this.context = context; 88 | itemResourceId = itemResource; 89 | itemTextResourceId = itemTextResource; 90 | 91 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 92 | } 93 | 94 | /** 95 | * Gets text color 96 | * @return the text color 97 | */ 98 | public int getTextColor() { 99 | return textColor; 100 | } 101 | 102 | /** 103 | * Sets text color 104 | * @param textColor the text color to set 105 | */ 106 | public void setTextColor(int textColor) { 107 | this.textColor = textColor; 108 | } 109 | 110 | /** 111 | * Gets text size 112 | * @return the text size 113 | */ 114 | public int getTextSize() { 115 | return textSize; 116 | } 117 | 118 | /** 119 | * Sets text size 120 | * @param textSize the text size to set 121 | */ 122 | public void setTextSize(int textSize) { 123 | this.textSize = textSize; 124 | } 125 | 126 | /** 127 | * Gets resource Id for items views 128 | * @return the item resource Id 129 | */ 130 | public int getItemResource() { 131 | return itemResourceId; 132 | } 133 | 134 | /** 135 | * Sets resource Id for items views 136 | * @param itemResourceId the resource Id to set 137 | */ 138 | public void setItemResource(int itemResourceId) { 139 | this.itemResourceId = itemResourceId; 140 | } 141 | 142 | /** 143 | * Gets resource Id for text view in item layout 144 | * @return the item text resource Id 145 | */ 146 | public int getItemTextResource() { 147 | return itemTextResourceId; 148 | } 149 | 150 | /** 151 | * Sets resource Id for text view in item layout 152 | * @param itemTextResourceId the item text resource Id to set 153 | */ 154 | public void setItemTextResource(int itemTextResourceId) { 155 | this.itemTextResourceId = itemTextResourceId; 156 | } 157 | 158 | /** 159 | * Gets resource Id for empty items views 160 | * @return the empty item resource Id 161 | */ 162 | public int getEmptyItemResource() { 163 | return emptyItemResourceId; 164 | } 165 | 166 | /** 167 | * Sets resource Id for empty items views 168 | * @param emptyItemResourceId the empty item resource Id to set 169 | */ 170 | public void setEmptyItemResource(int emptyItemResourceId) { 171 | this.emptyItemResourceId = emptyItemResourceId; 172 | } 173 | 174 | 175 | /** 176 | * Returns text for specified item 177 | * @param index the item index 178 | * @return the text of specified items 179 | */ 180 | protected abstract CharSequence getItemText(int index); 181 | 182 | @Override 183 | public View getItem(int index, View convertView, ViewGroup parent) { 184 | if (index >= 0 && index < getItemsCount()) { 185 | if (convertView == null) { 186 | convertView = getView(itemResourceId, parent); 187 | } 188 | TextView textView = getTextView(convertView, itemTextResourceId); 189 | if (textView != null) { 190 | CharSequence text = getItemText(index); 191 | if (text == null) { 192 | text = ""; 193 | } 194 | textView.setText(text); 195 | 196 | if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { 197 | configureTextView(textView); 198 | } 199 | } 200 | return convertView; 201 | } 202 | return null; 203 | } 204 | 205 | @Override 206 | public View getEmptyItem(View convertView, ViewGroup parent) { 207 | if (convertView == null) { 208 | convertView = getView(emptyItemResourceId, parent); 209 | } 210 | if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) { 211 | configureTextView((TextView)convertView); 212 | } 213 | 214 | return convertView; 215 | } 216 | 217 | /** 218 | * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. 219 | * @param view the text view to be configured 220 | */ 221 | protected void configureTextView(TextView view) { 222 | view.setTextColor(textColor); 223 | view.setGravity(Gravity.CENTER); 224 | view.setTextSize(textSize); 225 | view.setEllipsize(TextUtils.TruncateAt.END); 226 | view.setLines(1); 227 | // view.setCompoundDrawablePadding(20); 228 | // view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); 229 | } 230 | 231 | /** 232 | * Loads a text view from view 233 | * @param view the text view or layout containing it 234 | * @param textResource the text resource Id in layout 235 | * @return the loaded text view 236 | */ 237 | public TextView getTextView(View view, int textResource) { 238 | TextView text = null; 239 | try { 240 | if (textResource == NO_RESOURCE && view instanceof TextView) { 241 | text = (TextView) view; 242 | } else if (textResource != NO_RESOURCE) { 243 | text = (TextView) view.findViewById(textResource); 244 | } 245 | } catch (ClassCastException e) { 246 | Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); 247 | throw new IllegalStateException( 248 | "AbstractWheelAdapter requires the resource ID to be a TextView", e); 249 | } 250 | 251 | return text; 252 | } 253 | 254 | /** 255 | * Loads view from resources 256 | * @param resource the resource Id 257 | * @return the loaded view or null if resource is not set 258 | */ 259 | public View getView(int resource, ViewGroup parent) { 260 | switch (resource) { 261 | case NO_RESOURCE: 262 | return null; 263 | case TEXT_VIEW_ITEM_RESOURCE: 264 | return new TextView(context); 265 | default: 266 | return inflater.inflate(resource, parent, false); 267 | } 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/AbstractWheelTextAdapter1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 17 | 18 | import android.content.Context; 19 | import android.graphics.Typeface; 20 | import android.util.Log; 21 | import android.view.Gravity; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.TextView; 26 | 27 | import java.util.ArrayList; 28 | 29 | /** 30 | * Abstract wheel adapter provides common functionality for adapters. 31 | */ 32 | public abstract class AbstractWheelTextAdapter1 extends AbstractWheelAdapter { 33 | 34 | /** Text view resource. Used as a default view for adapter. */ 35 | public static final int TEXT_VIEW_ITEM_RESOURCE = -1; 36 | 37 | /** No resource constant. */ 38 | protected static final int NO_RESOURCE = 0; 39 | 40 | /** Default text color */ 41 | public static final int DEFAULT_TEXT_COLOR = 0xFF101010; 42 | 43 | /** Default text color */ 44 | public static final int LABEL_COLOR = 0xFF700070; 45 | 46 | /** Default text size */ 47 | public static final int DEFAULT_TEXT_SIZE = 24; 48 | 49 | // Text settings 50 | private int textColor = DEFAULT_TEXT_COLOR; 51 | private int textSize = DEFAULT_TEXT_SIZE; 52 | 53 | // Current context 54 | protected Context context; 55 | // Layout inflater 56 | protected LayoutInflater inflater; 57 | 58 | // Items resources 59 | protected int itemResourceId; 60 | protected int itemTextResourceId; 61 | 62 | // Empty items resources 63 | protected int emptyItemResourceId; 64 | 65 | private int currentIndex = 0; 66 | private static int maxsize = 14; 67 | private static int minsize = 12; 68 | private ArrayList arrayList = new ArrayList(); 69 | 70 | /** 71 | * Constructor 72 | * 73 | * @param context 74 | * the current context 75 | */ 76 | protected AbstractWheelTextAdapter1(Context context) { 77 | this(context, TEXT_VIEW_ITEM_RESOURCE); 78 | } 79 | 80 | /** 81 | * Constructor 82 | * 83 | * @param context 84 | * the current context 85 | * @param itemResource 86 | * the resource ID for a layout file containing a TextView to use 87 | * when instantiating items views 88 | */ 89 | protected AbstractWheelTextAdapter1(Context context, int itemResource) { 90 | this(context, itemResource, NO_RESOURCE, 0, maxsize, minsize); 91 | } 92 | 93 | /** 94 | * Constructor 95 | * 96 | * @param context 97 | * the current context 98 | * @param itemResource 99 | * the resource ID for a layout file containing a TextView to use 100 | * when instantiating items views 101 | * @param itemTextResource 102 | * the resource ID for a text view in the item layout 103 | */ 104 | protected AbstractWheelTextAdapter1(Context context, int itemResource, int itemTextResource, int currentIndex, 105 | int maxsize, int minsize) { 106 | this.context = context; 107 | itemResourceId = itemResource; 108 | itemTextResourceId = itemTextResource; 109 | this.currentIndex = currentIndex; 110 | this.maxsize = maxsize; 111 | this.minsize = minsize; 112 | 113 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 114 | } 115 | 116 | /** 117 | * get the list of show textview 118 | * 119 | * @return the array of textview 120 | */ 121 | public ArrayList getTestViews() { 122 | return arrayList; 123 | } 124 | 125 | /** 126 | * Gets text color 127 | * 128 | * @return the text color 129 | */ 130 | public int getTextColor() { 131 | return textColor; 132 | } 133 | 134 | /** 135 | * Sets text color 136 | * 137 | * @param textColor 138 | * the text color to set 139 | */ 140 | public void setTextColor(int textColor) { 141 | this.textColor = textColor; 142 | } 143 | 144 | /** 145 | * Gets text size 146 | * 147 | * @return the text size 148 | */ 149 | public int getTextSize() { 150 | return textSize; 151 | } 152 | 153 | /** 154 | * Sets text size 155 | * 156 | * @param textSize 157 | * the text size to set 158 | */ 159 | public void setTextSize(int textSize) { 160 | this.textSize = textSize; 161 | } 162 | 163 | /** 164 | * Gets resource Id for items views 165 | * 166 | * @return the item resource Id 167 | */ 168 | public int getItemResource() { 169 | return itemResourceId; 170 | } 171 | 172 | /** 173 | * Sets resource Id for items views 174 | * 175 | * @param itemResourceId 176 | * the resource Id to set 177 | */ 178 | public void setItemResource(int itemResourceId) { 179 | this.itemResourceId = itemResourceId; 180 | } 181 | 182 | /** 183 | * Gets resource Id for text view in item layout 184 | * 185 | * @return the item text resource Id 186 | */ 187 | public int getItemTextResource() { 188 | return itemTextResourceId; 189 | } 190 | 191 | /** 192 | * Sets resource Id for text view in item layout 193 | * 194 | * @param itemTextResourceId 195 | * the item text resource Id to set 196 | */ 197 | public void setItemTextResource(int itemTextResourceId) { 198 | this.itemTextResourceId = itemTextResourceId; 199 | } 200 | 201 | /** 202 | * Gets resource Id for empty items views 203 | * 204 | * @return the empty item resource Id 205 | */ 206 | public int getEmptyItemResource() { 207 | return emptyItemResourceId; 208 | } 209 | 210 | /** 211 | * Sets resource Id for empty items views 212 | * 213 | * @param emptyItemResourceId 214 | * the empty item resource Id to set 215 | */ 216 | public void setEmptyItemResource(int emptyItemResourceId) { 217 | this.emptyItemResourceId = emptyItemResourceId; 218 | } 219 | 220 | /** 221 | * Returns text for specified item 222 | * 223 | * @param index 224 | * the item index 225 | * @return the text of specified items 226 | */ 227 | protected abstract CharSequence getItemText(int index); 228 | 229 | @Override 230 | public View getItem(int index, View convertView, ViewGroup parent) { 231 | if (index >= 0 && index < getItemsCount()) { 232 | if (convertView == null) { 233 | convertView = getView(itemResourceId, parent); 234 | } 235 | TextView textView = getTextView(convertView, itemTextResourceId); 236 | if (!arrayList.contains(textView)) { 237 | arrayList.add(textView); 238 | } 239 | if (textView != null) { 240 | CharSequence text = getItemText(index); 241 | if (text == null) { 242 | text = ""; 243 | } 244 | textView.setText(text); 245 | 246 | if (index == currentIndex) { 247 | textView.setTextSize(maxsize); 248 | } else { 249 | textView.setTextSize(minsize); 250 | } 251 | 252 | if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { 253 | configureTextView(textView); 254 | } 255 | } 256 | return convertView; 257 | } 258 | return null; 259 | } 260 | 261 | @Override 262 | public View getEmptyItem(View convertView, ViewGroup parent) { 263 | if (convertView == null) { 264 | convertView = getView(emptyItemResourceId, parent); 265 | } 266 | if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) { 267 | configureTextView((TextView) convertView); 268 | } 269 | 270 | return convertView; 271 | } 272 | 273 | /** 274 | * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. 275 | * 276 | * @param view 277 | * the text view to be configured 278 | */ 279 | protected void configureTextView(TextView view) { 280 | view.setTextColor(textColor); 281 | view.setGravity(Gravity.CENTER); 282 | view.setTextSize(textSize); 283 | view.setLines(1); 284 | view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); 285 | } 286 | 287 | /** 288 | * Loads a text view from view 289 | * 290 | * @param view 291 | * the text view or layout containing it 292 | * @param textResource 293 | * the text resource Id in layout 294 | * @return the loaded text view 295 | */ 296 | private TextView getTextView(View view, int textResource) { 297 | TextView text = null; 298 | try { 299 | if (textResource == NO_RESOURCE && view instanceof TextView) { 300 | text = (TextView) view; 301 | } else if (textResource != NO_RESOURCE) { 302 | text = (TextView) view.findViewById(textResource); 303 | } 304 | } catch (ClassCastException e) { 305 | Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); 306 | throw new IllegalStateException("AbstractWheelAdapter requires the resource ID to be a TextView", e); 307 | } 308 | 309 | return text; 310 | } 311 | 312 | /** 313 | * Loads view from resources 314 | * 315 | * @param resource 316 | * the resource Id 317 | * @return the loaded view or null if resource is not set 318 | */ 319 | private View getView(int resource, ViewGroup parent) { 320 | switch (resource) { 321 | case NO_RESOURCE: 322 | return null; 323 | case TEXT_VIEW_ITEM_RESOURCE: 324 | return new TextView(context); 325 | default: 326 | return inflater.inflate(resource, parent, false); 327 | } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/AdapterWheel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 18 | 19 | 20 | import android.content.Context; 21 | 22 | import com.panghaha.it.timepackdemo.view.wheelview.WheelAdapter; 23 | 24 | 25 | /** 26 | * Adapter class for old wheel adapter (deprecated WheelAdapter class). 27 | * 28 | * @deprecated Will be removed soon 29 | */ 30 | public class AdapterWheel extends AbstractWheelTextAdapter { 31 | 32 | // Source adapter 33 | private WheelAdapter adapter; 34 | 35 | /** 36 | * Constructor 37 | * @param context the current context 38 | * @param adapter the source adapter 39 | */ 40 | public AdapterWheel(Context context, WheelAdapter adapter) { 41 | super(context); 42 | 43 | this.adapter = adapter; 44 | } 45 | 46 | /** 47 | * Gets original adapter 48 | * @return the original adapter 49 | */ 50 | public WheelAdapter getAdapter() { 51 | return adapter; 52 | } 53 | 54 | @Override 55 | public int getItemsCount() { 56 | return adapter.getItemsCount(); 57 | } 58 | 59 | @Override 60 | protected CharSequence getItemText(int index) { 61 | return adapter.getItem(index); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/ArrayWheelAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 17 | 18 | import android.content.Context; 19 | 20 | /** 21 | * The simple Array wheel adapter 22 | * @param the element type 23 | */ 24 | public class ArrayWheelAdapter extends AbstractWheelTextAdapter { 25 | 26 | // items 27 | private T items[]; 28 | 29 | /** 30 | * Constructor 31 | * @param context the current context 32 | * @param items the items 33 | */ 34 | public ArrayWheelAdapter(Context context, T items[]) { 35 | super(context); 36 | 37 | //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE); 38 | this.items = items; 39 | } 40 | 41 | @Override 42 | public CharSequence getItemText(int index) { 43 | if (index >= 0 && index < items.length) { 44 | T item = items[index]; 45 | if (item instanceof CharSequence) { 46 | return (CharSequence) item; 47 | } 48 | return item.toString(); 49 | } 50 | return null; 51 | } 52 | 53 | @Override 54 | public int getItemsCount() { 55 | return items.length; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/EnMonthWheelAdapter.java: -------------------------------------------------------------------------------- 1 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Description: 7 | * Created by zhouweiyong on 2015/12/8. 8 | */ 9 | public class EnMonthWheelAdapter extends AbstractWheelTextAdapter{ 10 | /** The default min value */ 11 | public static final int DEFAULT_MAX_VALUE = 9; 12 | 13 | /** The default max value */ 14 | private static final int DEFAULT_MIN_VALUE = 0; 15 | 16 | // Values 17 | private int minValue; 18 | private int maxValue; 19 | 20 | // format 21 | private String format; 22 | 23 | private String label; 24 | protected EnMonthWheelAdapter(Context context) { 25 | this(context,DEFAULT_MIN_VALUE,DEFAULT_MAX_VALUE); 26 | } 27 | 28 | /** 29 | * Constructor 30 | * @param context the current context 31 | * @param minValue the wheel min value 32 | * @param maxValue the wheel max value 33 | */ 34 | public EnMonthWheelAdapter(Context context, int minValue, int maxValue) { 35 | this(context, minValue, maxValue, null); 36 | } 37 | 38 | /** 39 | * Constructor 40 | * @param context the current context 41 | * @param minValue the wheel min value 42 | * @param maxValue the wheel max value 43 | * @param format the format string 44 | */ 45 | public EnMonthWheelAdapter(Context context, int minValue, int maxValue, String format) { 46 | super(context); 47 | this.minValue = minValue; 48 | this.maxValue = maxValue; 49 | this.format = format; 50 | } 51 | 52 | 53 | @Override 54 | protected CharSequence getItemText(int index) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public int getItemsCount() { 60 | return 0; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/NumericWheelAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 18 | 19 | import android.content.Context; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | import android.widget.TextView; 23 | 24 | /** 25 | * Numeric Wheel adapter. 26 | */ 27 | public class NumericWheelAdapter extends AbstractWheelTextAdapter { 28 | 29 | /** The default min value */ 30 | public static final int DEFAULT_MAX_VALUE = 9; 31 | 32 | /** The default max value */ 33 | private static final int DEFAULT_MIN_VALUE = 0; 34 | 35 | // Values 36 | private int minValue; 37 | private int maxValue; 38 | 39 | // format 40 | private String format; 41 | 42 | private String label; 43 | 44 | /** 45 | * Constructor 46 | * @param context the current context 47 | */ 48 | public NumericWheelAdapter(Context context) { 49 | this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); 50 | } 51 | 52 | /** 53 | * Constructor 54 | * @param context the current context 55 | * @param minValue the wheel min value 56 | * @param maxValue the wheel max value 57 | */ 58 | public NumericWheelAdapter(Context context, int minValue, int maxValue) { 59 | this(context, minValue, maxValue, null); 60 | } 61 | 62 | /** 63 | * Constructor 64 | * @param context the current context 65 | * @param minValue the wheel min value 66 | * @param maxValue the wheel max value 67 | * @param format the format string 68 | */ 69 | public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) { 70 | super(context); 71 | 72 | this.minValue = minValue; 73 | this.maxValue = maxValue; 74 | this.format = format; 75 | } 76 | 77 | @Override 78 | public CharSequence getItemText(int index) { 79 | if (index >= 0 && index < getItemsCount()) { 80 | int value = minValue + index; 81 | return format != null ? String.format(format, value) : Integer.toString(value); 82 | } 83 | return null; 84 | } 85 | 86 | @Override 87 | public int getItemsCount() { 88 | return maxValue - minValue + 1; 89 | } 90 | 91 | @Override 92 | public View getItem(int index, View convertView, ViewGroup parent) { 93 | if (index >= 0 && index < getItemsCount()) { 94 | if (convertView == null) { 95 | convertView = getView(itemResourceId, parent); 96 | } 97 | TextView textView = getTextView(convertView, itemTextResourceId); 98 | if (textView != null) { 99 | CharSequence text = getItemText(index); 100 | if (text == null) { 101 | text = ""; 102 | } 103 | 104 | textView.setText(text+label); 105 | // if ("1".equals(UIUtils.getString(R.string.common_lang))){ 106 | // textView.setText(text+label); 107 | // }else{ 108 | // textView.setText(label+text); 109 | // } 110 | 111 | if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { 112 | configureTextView(textView); 113 | } 114 | } 115 | return convertView; 116 | } 117 | return null; 118 | } 119 | 120 | public void setLabel(String label) { 121 | this.label=label; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/panghaha/it/timepackdemo/view/wheelview/adapter/WheelViewAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Yuri Kanivets 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.panghaha.it.timepackdemo.view.wheelview.adapter; 18 | 19 | import android.database.DataSetObserver; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | /** 24 | * Wheel items adapter interface 25 | */ 26 | public interface WheelViewAdapter { 27 | 28 | /** 29 | * Gets items count 30 | * @return the count of wheel items 31 | */ 32 | public int getItemsCount(); 33 | 34 | /** 35 | * Get a View that displays the data at the specified position in the data set 36 | * 37 | * @param index the item index 38 | * @param convertView the old view to reuse if possible 39 | * @param parent the parent that this view will eventually be attached to 40 | * @return the wheel item View 41 | */ 42 | public View getItem(int index, View convertView, ViewGroup parent); 43 | 44 | /** 45 | * Get a View that displays an empty wheel item placed before the first or after 46 | * the last wheel item. 47 | * 48 | * @param convertView the old view to reuse if possible 49 | * @param parent the parent that this view will eventually be attached to 50 | * @return the empty item View 51 | */ 52 | public View getEmptyItem(View convertView, ViewGroup parent); 53 | 54 | /** 55 | * Register an observer that is called when changes happen to the data used by this adapter. 56 | * @param observer the observer to be registered 57 | */ 58 | public void registerDataSetObserver(DataSetObserver observer); 59 | 60 | /** 61 | * Unregister an observer that has previously been registered 62 | * @param observer the observer to be unregistered 63 | */ 64 | void unregisterDataSetObserver(DataSetObserver observer); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/popu_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sfdfb.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PangHaHa12138/TimePackdemo/ce4afd2befb3e9adcc6a53535a7b6f1441d33db6/app/src/main/res/drawable/sfdfb.PNG -------------------------------------------------------------------------------- /app/src/main/res/drawable/wheel_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wheel_val.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |