Commit 67cd831c authored by jianglx's avatar jianglx

个人中心优化

parent 84e5c9a2
......@@ -1077,15 +1077,16 @@ public class HomeFragment extends BaseFragment<HomePresenter> implements Observa
case 3:
rvTourLatitude = lat;
rvTourLongitude = lon;
if (tvRvCity != null) {
if (tvRvCity != null && !TextUtils.isEmpty(data)) {
tvRvCity.setText(data);
}
break;
case 4:
if(travelCityText != null && !TextUtils.isEmpty(data))
travelCityText.setText(data);
// headTvGetCity.setText(data);
// headTvOutCity.setText(data);
if (tvRvCity != null) {
if (tvRvCity != null && !TextUtils.isEmpty(data)) {
tvRvCity.setText(data);
}
getShopList(false);
......
......@@ -550,7 +550,11 @@ public class MineFragment extends BaseFragment<CommonPresenter> implements Simpl
if (info != null) {
GlideManager.getInstance(_mActivity).loadImage(info.getHeadimgurl(), ivAvatar);
tvNickname.setText(info.getNickname());
tvCapacity.setText(info.getPositionName());
if(!TextUtils.isEmpty(info.getPositionName())){
tvCapacity.setText(info.getPositionName());
tvCapacity.setVisibility(View.VISIBLE);
}
//更新实名信息
UtilsManager.getInstance(OkGoUtil.application).setSharePreferencesSave(SPConstance.USER_JSON).putString(SPConstance.USER_JSON_USERINFO, JSON.toJSONString(info)).commit();
if (info.getCertificationStatus() == 0) { //实名认证状态:0-未认证,1-已认证
......
......@@ -192,8 +192,8 @@ public class BindPhoneSecondFragment extends BaseFragment<CommonPresenter> {
}
@Override
public void onStop() {
super.onStop();
public void onDestroyView() {
super.onDestroyView();
stopCarousel();
}
......
......@@ -205,8 +205,8 @@ public class BindPhoneThirdFragment extends BaseFragment<CommonPresenter> {
}
@Override
public void onStop() {
super.onStop();
public void onDestroyView() {
super.onDestroyView();
stopCarousel();
}
......
......@@ -224,18 +224,6 @@ public class AccountSafeActivity extends BaseStatusActivity<CommonPresenter> imp
}
private void setQqInfo() {
hasBindWX = bean.getData().isBindWx();
if (hasBindWX) {
String wx = bean.getData().getWxNickname();
tvWx.setTextColor(Color.parseColor("#171413"));
tvWx.setText(!TextUtils.isEmpty(wx) ? wx : "已绑定");
} else {
tvWx.setTextColor(Color.parseColor("#cccccc"));
tvWx.setText("去授权绑定QQ");
}
}
private void setWxInfo() {
hasBindQQ = bean.getData().isBindQQ();
if (hasBindQQ) {
String qq = bean.getData().getQqNickname();
......@@ -243,7 +231,19 @@ public class AccountSafeActivity extends BaseStatusActivity<CommonPresenter> imp
tvQQ.setText(!TextUtils.isEmpty(qq) ? qq : "已绑定");
} else {
tvQQ.setTextColor(Color.parseColor("#cccccc"));
tvQQ.setText("去授权绑定微信");
tvQQ.setText("去授权绑定QQ");
}
}
private void setWxInfo() {
hasBindWX = bean.getData().isBindWx();
if (hasBindWX) {
String wx = bean.getData().getWxNickname();
tvWx.setTextColor(Color.parseColor("#171413"));
tvWx.setText(!TextUtils.isEmpty(wx) ? wx : "已绑定");
} else {
tvWx.setTextColor(Color.parseColor("#cccccc"));
tvWx.setText("去授权绑定微信");
}
}
......
......@@ -53,6 +53,7 @@ public class AlterNickNameActivity extends BaseStatusActivity<CommonPresenter> {
private void upUserinfo() {
if (TextUtils.isEmpty(getNickName())) {
showToast("昵称不能为空");
return;
}
Intent intent = new Intent();
intent.putExtra("nick", getNickName());
......
......@@ -4,7 +4,6 @@ import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
......@@ -13,9 +12,7 @@ import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.base.utils.ui.datetime.selector.util.TextUtil;
import com.base.utils.ui.image.round.RoundImageView;
import com.bigkoo.pickerview.TimePickerView;
import com.frame.base.bus.RxBus;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
......@@ -35,10 +32,10 @@ import com.rv.rvmine.R;
import com.rv.rvmine.R2;
import com.rv.rvmine.dialog.ChooseGenderDialog;
import com.rv.rvmine.rxbusevent.UserInfoEvent;
import com.rv.rvmine.view.DateTimeWheelDialog;
import com.yuyife.okgo.OkGoUtil;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
......@@ -58,7 +55,7 @@ import pub.devrel.easypermissions.AppSettingsDialog;
*/
public class PersonalInformationActivity extends BaseStatusActivity<PickerPresenter> {
public final int TYPE_ALTER_NICK = 1006;
private final int TYPE_ALTER_NICK = 1006;
@BindView(R2.id.iv_avatar)
RoundImageView ivAvatar;
......@@ -76,11 +73,6 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
private int sex;// 0-女,1-男
private String mQQOpenid;
private String mWXOpenid;
private String mUnionid;
private String aliCode;
private String birthday = "";
private static final int SDK_AUTH_FLAG = 2;
......@@ -99,14 +91,6 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
@Override
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
titleView.setTitle("个人资料");
titleView.setText(R.id.tv_title_right, "保存");
titleView.setTextColor(R.id.tv_title_right, Color.parseColor("#666666"));
titleView.setChildClickListener(R.id.tv_title_right, new View.OnClickListener() {
@Override
public void onClick(View v) {
upUserinfo();
}
});
tvNickname.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
......@@ -119,12 +103,8 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
});
dialog = new ProgressDialog(this);
info = ((UserInfoBean) RvCache.getInstance().get(CacheEnum.USER)).getData();
// info = (UserInfoBean.UserInfo) intent.getSerializableExtra("userinfo");
if (info != null) {
ivAvatarUrl = info.getHeadimgurl();
mWXOpenid = info.getWxOpenid();
mUnionid = info.getUnionid();
mQQOpenid = info.getOpenid();
GlideManager.getInstance(mActivity).loadImage(info.getHeadimgurl(), ivAvatar);
if (!TextUtils.isEmpty(info.getNickname())) {
......@@ -132,9 +112,9 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
tvNickname.setText(info.getNickname());
tvNickname.setTextColor(getResources().getColor(R.color.colorMain));
}
if (info.getBirthday() != null) {
if (!TextUtils.isEmpty(info.getBirthday())) {
birthday = info.getBirthday();
tvDateOfBirth.setText(info.getBirthday());
tvDateOfBirth.setText(birthday);
}
if (info.getSex() != null) {
sex = info.getSex();
......@@ -158,10 +138,12 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
case 0:
ImageUploadBean bean = (ImageUploadBean) result;
ivAvatarUrl = bean.getData();
UserInfo userInfo = new UserInfo();
userInfo.setHeadimgurl(ivAvatarUrl);
upUserinfo(userInfo, true);
break;
case 1:
RxBus.post(new UserInfoEvent());
finish();
break;
}
}
......@@ -185,8 +167,13 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
String nickName = data.getStringExtra("nick");
if (!TextUtils.isEmpty(nickName)) {
hasNickName = true;
tvNickname.setText(nickName);
tvNickname.setTextColor(getResources().getColor(R.color.colorMain));
if (!nickName.equals(tvNickname.getText().toString().trim())) {
tvNickname.setText(nickName);
tvNickname.setTextColor(getResources().getColor(R.color.colorMain));
UserInfo userInfo = new UserInfo();
userInfo.setNickname(nickName);
upUserinfo(userInfo, false);
}
}
}
}
......@@ -225,20 +212,23 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
public void onClick(View v) {
int id = v.getId();
if (id == R.id.cb_man || id == R.id.rl_man) {
sex = 1;
helper.setChecked(R.id.cb_girl, false);
} else if (id == R.id.cb_girl|| id == R.id.rl_woman) {
sex = 0;
helper.setChecked(R.id.cb_man, false);
}
if (sex == 0) { // 0-女,1-男
tvSex.setText("女");
} else if (sex == 1) {
tvSex.setText("男");
if (sex != 1) {
sex = 1;
helper.setChecked(R.id.cb_girl, false);
tvSex.setText("男");
upUserinfo(new UserInfo(), true);
}
} else if (id == R.id.cb_girl || id == R.id.rl_woman) {
if (sex != 0) {
sex = 0;
helper.setChecked(R.id.cb_man, false);
tvSex.setText("女");
upUserinfo(new UserInfo(), true);
}
}
dismiss();
}
}, R.id.cb_man, R.id.cb_girl,R.id.rl_man,R.id.rl_woman);
}, R.id.cb_man, R.id.cb_girl, R.id.rl_man, R.id.rl_woman);
}
}.show();
}
......@@ -343,23 +333,14 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
}
private void upUserinfo() {
String nickName = tvNickname.getText().toString().trim();
if (TextUtil.isEmpty(nickName)) {
showToast("昵称不为空!");
return;
}
if (birthday != null && TextUtil.isEmpty(birthday)) {
showToast("生日不为空!");
return;
private void upUserinfo(UserInfo userInfo, boolean isShow) {
if (userInfo != null) {
userInfo.setSex(sex);
userInfo.setUserid(info.getUserid() + "");
userInfo.setId(info.getId() + "");
mPresenter.postBodyData(RvFrameConfig.ADMIN_POST, 1, ApiConfig.HTTP_URL_UPUSER_EDIT, BaseBean.class, userInfo, getHeadMap(), isShow);
}
if (info == null) {
return;
}
mPresenter.postBodyData(RvFrameConfig.ADMIN_POST, 1, ApiConfig.HTTP_URL_UPUSER_EDIT, BaseBean.class, new UserInfo(info.getId() + "", info.getUserid() + "", info.getUsername(), "0", nickName, info.getRealname(), ivAvatarUrl, birthday, sex, mWXOpenid, mUnionid, mQQOpenid, aliCode), getHeadMap(), true);
// mPresenter.postBodyData(RvFrameConfig.ADMIN_POST, 1, ApiConfig.HTTP_URL_UPUSER_EDIT, BaseBean.class, new UserInfo(info.getId() + "", info.getUserid() + "", info.getUsername(), "0", nickName, info.getRealname(), ivAvatarUrl, birthday, sex, "", "", ""), getHeadMap(), true);
}
private Map<String, Object> getHeadMap() {
......@@ -403,6 +384,9 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
private String openid;
private String aliCode;
public UserInfo() {
}
public UserInfo(String id, String userid, String username, String status, String nickname, String realname, String headimgurl, String birthday, int sex, String wxOpenid, String unionid, String openid, String aliCode) {
this.id = id;
this.userid = userid;
......@@ -524,62 +508,110 @@ public class PersonalInformationActivity extends BaseStatusActivity<PickerPresen
}
}
private DateTimeWheelDialog dateTimeWheelDialog = null;
private void initTimePicker1() {//选择出生年月日
//控制时间范围(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释)
//因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
Date curDate = new Date(System.currentTimeMillis());//获取当前时间
SimpleDateFormat formatter_year = new SimpleDateFormat("yyyy ");
String year_str = formatter_year.format(curDate);
int year_int = (int) Double.parseDouble(year_str);
SimpleDateFormat formatter_mouth = new SimpleDateFormat("MM ");
String mouth_str = formatter_mouth.format(curDate);
int mouth_int = (int) Double.parseDouble(mouth_str);
SimpleDateFormat formatter_day = new SimpleDateFormat("dd ");
String day_str = formatter_day.format(curDate);
int day_int = (int) Double.parseDouble(day_str);
Calendar selectedDate = Calendar.getInstance();//系统当前时间
Calendar startDate = Calendar.getInstance();
startDate.set(1900, 0, 1);
Calendar endDate = Calendar.getInstance();
endDate.set(year_int, mouth_int - 1, day_int);
private void initTimePicker1() {
if (dateTimeWheelDialog == null)
dateTimeWheelDialog = createDialog();
else
dateTimeWheelDialog.show();
}
//时间选择器
TimePickerView build = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
private DateTimeWheelDialog createDialog() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 1900);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
Date startDate = calendar.getTime();
calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1);
Date endDate = calendar.getTime();
DateTimeWheelDialog dialog = new DateTimeWheelDialog(this);
dialog.show();
dialog.setTitle("选择时间");
int config = DateTimeWheelDialog.SHOW_YEAR_MONTH;
dialog.configShowUI(config);
dialog.setOkListener(new DateTimeWheelDialog.OnClickCallBack() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
// 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
birthday = getTime(date);
tvDateOfBirth.setText(getTime(date));
public boolean callBack(View v, int year, int month) {
String newBirthDay;
if (month >= 10) {
newBirthDay = year + "-" + month;
} else {
newBirthDay = year + "-0" + month;
}
if (!newBirthDay.equals(birthday)) {
birthday = newBirthDay;
tvDateOfBirth.setText(birthday);
UserInfo userInfo = new UserInfo();
userInfo.setBirthday(birthday);
upUserinfo(userInfo, true);
}
return false;
}
})
.setType(new boolean[]{true, true, true, false, false, false}) //年月日时分秒 的显示与否,不设置则默认全部显示
.setLabel("年", "月", "日", "", "", "")//默认设置为年月日时分秒
.isCenterLabel(false)
.setSubmitColor(getResources().getColor(R.color.colorMain))
.setCancelColor(getResources().getColor(R.color.colorMain))
.setDividerColor(getResources().getColor(R.color.gray_FFB74B))
.setTextColorCenter(getResources().getColor(R.color.colorMain))//设置选中项的颜色
.setTextColorOut(getResources().getColor(R.color.colorGray))//设置没有被选中项的颜色
.setContentSize(21)
.setDate(selectedDate)
.setLineSpacingMultiplier(1.2f)
.setTextXOffset(-10, 0, 10, 0, 0, 0)//设置X轴倾斜角度[ -90 , 90°]
.setRangDate(startDate, endDate)
// .setBackgroundId(0x00FFFFFF) //设置外部遮罩颜色
.setDecorView(null)
.build();
build.show();
});
dialog.setDateArea(startDate, endDate, true);
dialog.updateSelectedDate(birthday);
return dialog;
}
private String getTime(Date date) {//可根据需要自行截取数据显示
// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.format(date);
}
// private void initTimePicker1() {//选择出生年月日
// //控制时间范围(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释)
// //因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
// Date curDate = new Date(System.currentTimeMillis());//获取当前时间
// SimpleDateFormat formatter_year = new SimpleDateFormat("yyyy ");
// String year_str = formatter_year.format(curDate);
// int year_int = (int) Double.parseDouble(year_str);
//
//
// SimpleDateFormat formatter_mouth = new SimpleDateFormat("MM ");
// String mouth_str = formatter_mouth.format(curDate);
// int mouth_int = (int) Double.parseDouble(mouth_str);
//
// SimpleDateFormat formatter_day = new SimpleDateFormat("dd ");
// String day_str = formatter_day.format(curDate);
// int day_int = (int) Double.parseDouble(day_str);
//
//
// Calendar selectedDate = Calendar.getInstance();//系统当前时间
// Calendar startDate = Calendar.getInstance();
// startDate.set(1900, 0, 1);
// Calendar endDate = Calendar.getInstance();
// endDate.set(year_int, mouth_int - 1, day_int);
//
// //时间选择器
// TimePickerView build = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
// @Override
// public void onTimeSelect(Date date, View v) {//选中事件回调
// // 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
//
// }
// })
// .setType(new boolean[]{true, true, true, false, false, false}) //年月日时分秒 的显示与否,不设置则默认全部显示
// .setLabel("年", "月", "日", "", "", "")//默认设置为年月日时分秒
// .isCenterLabel(false)
// .setSubmitColor(getResources().getColor(R.color.colorMain))
// .setCancelColor(getResources().getColor(R.color.colorMain))
// .setDividerColor(getResources().getColor(R.color.gray_FFB74B))
// .setTextColorCenter(getResources().getColor(R.color.colorMain))//设置选中项的颜色
// .setTextColorOut(getResources().getColor(R.color.colorGray))//设置没有被选中项的颜色
// .setContentSize(21)
// .setDate(selectedDate)
// .setLineSpacingMultiplier(1.2f)
// .setTextXOffset(-10, 0, 10, 0, 0, 0)//设置X轴倾斜角度[ -90 , 90°]
// .setRangDate(startDate, endDate)
//// .setBackgroundId(0x00FFFFFF) //设置外部遮罩颜色
// .setDecorView(null)
// .build();
// build.show();
// }
// private String getTime(Date date) {//可根据需要自行截取数据显示
//// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
// return format.format(date);
// }
}
package com.rv.rvmine.view;
import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
/**
* <br>Email:1006368252@qq.com
* <br>QQ:1006368252
* <br><a href="https://github.com/JustinRoom/WheelViewDemo" target="_blank">https://github.com/JustinRoom/WheelViewDemo</a>
*
* @author jiangshicheng
*/
public class DateItem implements IWheel {
public static final int TYPE_YEAR = 0;
public static final int TYPE_MONTH = 1;
public static final int TYPE_DAY = 2;
public static final int TYPE_HOUR = 3;
public static final int TYPE_MINUTE = 4;
@IntDef({TYPE_YEAR, TYPE_MONTH, TYPE_DAY, TYPE_HOUR, TYPE_MINUTE})
@Retention(RetentionPolicy.SOURCE)
public @interface DateType {
}
private int type;
private int value;
public DateItem() {
}
public DateItem(int value) {
this(TYPE_YEAR, value);
}
public DateItem(@DateType int type, int value) {
this.type = type;
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String getShowText() {
return String.format(Locale.CHINA, getFormatStringByType(), (value < 10 ? "0" + value : "" + value));
}
private String getFormatStringByType() {
String result = "";
switch (type) {
case TYPE_YEAR:
result = "%s年";
break;
case TYPE_MONTH:
result = "%s月";
break;
case TYPE_DAY:
result = "%s日";
break;
case TYPE_HOUR:
result = "%s时";
break;
case TYPE_MINUTE:
result = "%s分";
break;
}
return result;
}
}
package com.rv.rvmine.view;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.rv.component.utils.DisplayUtil;
import com.rv.rvmine.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Calendar;
import java.util.Date;
public class DateTimeWheelDialog extends Dialog {
public static final int SHOW_YEAR = 0;
public static final int SHOW_YEAR_MONTH = 1;
public static final int SHOW_YEAR_MONTH_DAY = 2;
public static final int SHOW_YEAR_MONTH_DAY_HOUR = 3;
public static final int SHOW_YEAR_MONTH_DAY_HOUR_MINUTE = 4;
@IntDef({
SHOW_YEAR,
SHOW_YEAR_MONTH,
SHOW_YEAR_MONTH_DAY,
SHOW_YEAR_MONTH_DAY_HOUR,
SHOW_YEAR_MONTH_DAY_HOUR_MINUTE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShowConfig {
}
private final int MIN_MONTH = 1;
private final int MAX_MONTH = 12;
private WheelItemView yearWheelItemView;
private WheelItemView monthWheelItemView;
private DateItem[] yearItems;
private DateItem[] monthItems;
private Button btnConfirm;
private Calendar startCalendar = Calendar.getInstance();
private Calendar endCalendar = Calendar.getInstance();
private Calendar selectedCalendar = Calendar.getInstance();
private int showCount = 3;
private int itemVerticalSpace = 30;
private boolean isViewInitialized = false;
private boolean keepLastSelected = false;
private int showConfig = SHOW_YEAR_MONTH_DAY_HOUR_MINUTE;
public DateTimeWheelDialog(@NonNull Context context) {
this(context, R.style.WheelDialog);
}
private DateTimeWheelDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
if (getWindow() != null) {
getWindow().setGravity(Gravity.CENTER);
getWindow().setBackgroundDrawable(null);
getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT);
}
setContentView(R.layout.wheel_dialog_base);
initView();
}
private void initView() {
isViewInitialized = true;
LinearLayout lyPickerContainer = findViewById(R.id.wheel_id_picker_container);
//year
yearWheelItemView = new WheelItemView(lyPickerContainer.getContext());
yearWheelItemView.setItemVerticalSpace(DisplayUtil.dip2px(getContext(), itemVerticalSpace));
yearWheelItemView.setShowCount(showCount);
lyPickerContainer.addView(yearWheelItemView, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1));
//month
monthWheelItemView = new WheelItemView(lyPickerContainer.getContext());
monthWheelItemView.setItemVerticalSpace(DisplayUtil.dip2px(getContext(), itemVerticalSpace));
monthWheelItemView.setShowCount(showCount);
lyPickerContainer.addView(monthWheelItemView, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1));
btnConfirm = findViewById(R.id.btn_confirm);
btnConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener == null) {
dismiss();
return;
}
if (isScrolling()) {
return;
}
mListener.callBack(v, selectedCalendar.get(Calendar.YEAR), selectedCalendar.get(Calendar.MONTH) + 1);
dismiss();
}
});
}
@Override
public void show() {
super.show();
if (getWindow() != null) {
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
}
private OnClickCallBack mListener;
public void setOkListener(OnClickCallBack listener) {
this.mListener = listener;
}
public void configShowUI(@ShowConfig int config) {
configShowUI(config, -1);
}
public void configShowUI(@ShowConfig int showConfig, int totalOffsetX) {
ensureIsViewInitialized();
this.showConfig = showConfig;
yearWheelItemView.setTotalOffsetX(0);
monthWheelItemView.setTotalOffsetX(0);
yearWheelItemView.setVisibility(View.VISIBLE);
monthWheelItemView.setVisibility(View.VISIBLE);
}
public void setDateArea(@NonNull Date startDate, @NonNull Date endDate, boolean keepLastSelected) {
ensureIsViewInitialized();
if (startDate.after(endDate))
throw new IllegalArgumentException("start date should be before end date");
startCalendar.setTime(startDate);
endCalendar.setTime(endDate);
selectedCalendar.setTimeInMillis(startDate.getTime());
this.keepLastSelected = keepLastSelected;
initAreaDate();
}
public void updateSelectedDate(@NonNull Date selectedDate) {
ensureIsViewInitialized();
if (selectedDate.before(startCalendar.getTime()) || selectedDate.after(endCalendar.getTime()))
throw new IllegalArgumentException("selected date must be between start date and end date");
selectedCalendar.setTime(selectedDate);
initSelectedDate();
initOnScrollListener();
}
public void updateSelectedDate(String date) {
ensureIsViewInitialized();
Date selectedDate = dateChange(date);
if (selectedDate.before(startCalendar.getTime()) || selectedDate.after(endCalendar.getTime()))
throw new IllegalArgumentException("selected date must be between start date and end date");
selectedCalendar.setTime(selectedDate);
initSelectedDate();
initOnScrollListener();
}
private Date dateChange(String date) {
try {
if (!TextUtils.isEmpty(date)) {
String[] split = date.split("-");
if (split.length >= 2) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.valueOf(split[0]));
calendar.set(Calendar.MONTH, Integer.valueOf(split[1]) - 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
return calendar.getTime();
} else {
return new Date();
}
} else {
return new Date();
}
} catch (Exception e) {
return new Date();
}
}
private void initAreaDate() {
int startYear = startCalendar.get(Calendar.YEAR);
int endYear = endCalendar.get(Calendar.YEAR);
int startMonth = startCalendar.get(Calendar.MONTH) + 1;
yearItems = updateItems(DateItem.TYPE_YEAR, startYear, endYear);
monthItems = updateItems(DateItem.TYPE_MONTH, startMonth, MAX_MONTH);
yearWheelItemView.setItems(yearItems);
monthWheelItemView.setItems(monthItems);
}
private void initOnScrollListener() {
yearWheelItemView.setOnSelectedListener(new WheelView.OnSelectedListener() {
@Override
public void onSelected(Context context, int selectedIndex) {
selectedCalendar.set(Calendar.YEAR, yearItems[selectedIndex].getValue());
if (showConfig > SHOW_YEAR)
onYearChanged();
}
});
monthWheelItemView.setOnSelectedListener(new WheelView.OnSelectedListener() {
@Override
public void onSelected(Context context, int selectedIndex) {
selectedCalendar.set(Calendar.MONTH, monthItems[selectedIndex].getValue() - 1);
}
});
}
private void initSelectedDate() {
int year = selectedCalendar.get(Calendar.YEAR);
int month = selectedCalendar.get(Calendar.MONTH) + 1;
int index = findSelectedIndexByValue(yearItems, year);
yearWheelItemView.setSelectedIndex(index, false);
index = findSelectedIndexByValue(monthItems, month);
monthWheelItemView.setSelectedIndex(index, false);
}
private void onYearChanged() {
// //update month list
// int startYear = startCalendar.get(Calendar.YEAR);
// int endYear = endCalendar.get(Calendar.YEAR);
// int selectedYear = selectedCalendar.get(Calendar.YEAR);
// int startMonth = startCalendar.get(Calendar.MONTH) + 1;
// int endMonth = endCalendar.get(Calendar.MONTH) + 1;
// int selectedMonth = selectedCalendar.get(Calendar.MONTH) + 1;
// int tempIndex = -1;
// int lastSelectedIndex = -1;
// int startValue, endValue;
// if (isSameValue(selectedYear, startYear)) {
// startValue = startMonth;
// endValue = MAX_MONTH;
// } else if (isSameValue(selectedYear, endYear)) {
// startValue = MIN_MONTH;
// endValue = endMonth;
// } else {
// startValue = MIN_MONTH;
// endValue = MAX_MONTH;
// }
// monthItems = new DateItem[endValue - startValue + 1];
// for (int i = startValue; i <= endValue; i++) {
// tempIndex++;
// monthItems[tempIndex] = new DateItem(DateItem.TYPE_MONTH, i);
// if (isSameValue(selectedMonth, i)) {
// lastSelectedIndex = tempIndex;
// }
// }
// int newSelectedIndex = keepLastSelected ? (lastSelectedIndex == -1 ? 0 : lastSelectedIndex) : 0;
// monthWheelItemView.setItems(monthItems);
// monthWheelItemView.setSelectedIndex(newSelectedIndex);
}
private int findSelectedIndexByValue(DateItem[] items, int value) {
int selectedIndex = 0;
for (int i = 0; i < items.length; i++) {
if (isSameValue(value, items[i].getValue())) {
selectedIndex = i;
break;
}
}
return selectedIndex;
}
private DateItem[] updateItems(@DateItem.DateType int type, int startValue, int endValue) {
int index = -1;
DateItem[] items = new DateItem[endValue - startValue + 1];
for (int i = startValue; i <= endValue; i++) {
index++;
items[index] = new DateItem(type, i);
}
return items;
}
private boolean isScrolling() {
return yearWheelItemView.isScrolling()
|| monthWheelItemView.isScrolling();
}
private boolean isSameValue(int value1, int value2) {
return value1 == value2;
}
private void ensureIsViewInitialized() {
if (!isViewInitialized)
throw new IllegalStateException("View wasn't initialized, call show() first.");
}
public interface OnClickCallBack {
boolean callBack(View v, int year, int month);
}
}
package com.rv.rvmine.view;
public interface IWheel {
String getShowText();
}
package com.rv.rvmine.view;
import android.support.annotation.ColorInt;
public interface IWheelViewSetting {
void setTextSize(float textSize);
void setTextColor(@ColorInt int textColor);
void setShowCount(int showCount);
void setTotalOffsetX(int totalOffsetX);
void setItemVerticalSpace(int itemVerticalSpace);
void setItems(IWheel[] items);
int getSelectedIndex();
void setSelectedIndex(int targetIndexPosition);
void setSelectedIndex(int targetIndexPosition, boolean withAnimation);
void setOnSelectedListener(WheelView.OnSelectedListener onSelectedListener);
boolean isScrolling();
}
package com.rv.rvmine.view;
public class WheelItem implements IWheel {
String label;
public WheelItem(String label) {
this.label = label;
}
@Override
public String getShowText() {
return label;
}
}
package com.rv.rvmine.view;
import android.content.Context;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class WheelItemView extends FrameLayout implements IWheelViewSetting {
private WheelView wheelView;
private WheelMaskView wheelMaskView;
public WheelItemView(@NonNull Context context) {
super(context);
initAttr(context, null, 0);
}
public WheelItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttr(context, attrs, 0);
}
public WheelItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs, defStyleAttr);
}
private void initAttr(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
wheelView = new WheelView(context);
wheelView.initAttr(context, attrs, defStyleAttr);
wheelMaskView = new WheelMaskView(context);
wheelMaskView.initAttr(context, attrs, defStyleAttr);
addView(wheelView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
addView(wheelMaskView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ViewGroup.LayoutParams params = wheelMaskView.getLayoutParams();
params.height = wheelView.getMeasuredHeight();
wheelMaskView.setLayoutParams(params);
wheelMaskView.updateMask(wheelView.getShowCount(), wheelView.getItemHeight());
}
@Override
public void setTextSize(float textSize) {
wheelView.setTextSize(textSize);
}
@Override
public void setTextColor(@ColorInt int textColor) {
wheelView.setTextColor(textColor);
}
@Override
public void setShowCount(int showCount) {
wheelView.setShowCount(showCount);
}
@Override
public void setTotalOffsetX(int totalOffsetX) {
wheelView.setTotalOffsetX(totalOffsetX);
}
@Override
public void setItemVerticalSpace(int itemVerticalSpace) {
wheelView.setItemVerticalSpace(itemVerticalSpace);
}
@Override
public void setItems(IWheel[] items) {
wheelView.setItems(items);
}
@Override
public int getSelectedIndex() {
return wheelView.getSelectedIndex();
}
@Override
public void setSelectedIndex(int targetIndexPosition) {
setSelectedIndex(targetIndexPosition, true);
}
@Override
public void setSelectedIndex(int targetIndexPosition, boolean withAnimation) {
wheelView.setSelectedIndex(targetIndexPosition, withAnimation);
}
@Override
public void setOnSelectedListener(WheelView.OnSelectedListener onSelectedListener) {
wheelView.setOnSelectedListener(onSelectedListener);
}
public void setMaskLineColor(@ColorInt int color) {
wheelMaskView.setLineColor(color);
}
@Override
public boolean isScrolling() {
return wheelView.isScrolling();
}
public WheelView getWheelView() {
return wheelView;
}
public WheelMaskView getWheelMaskView() {
return wheelMaskView;
}
}
package com.rv.rvmine.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.rv.rvmine.R;
public class WheelMaskView extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int top = 0;
private int bottom = 0;
private int lineColor = 0xFFEEEEEE;
public WheelMaskView(Context context) {
super(context);
initAttr(context, null, 0);
}
public WheelMaskView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttr(context, attrs, 0);
}
public WheelMaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs, defStyleAttr);
}
public void initAttr(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WheelMaskView, defStyleAttr, 0);
lineColor = a.getColor(R.styleable.WheelMaskView_wheelMaskLineColor, 0xFFEEEEEE);
a.recycle();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
}
public void updateMask(int heightCount, int itemHeight) {
if (heightCount > 0) {
int centerIndex = heightCount / 2;
top = centerIndex * itemHeight;
bottom = top + itemHeight;
} else {
top = 0;
bottom = 0;
}
invalidate();
}
public void setLineColor(@ColorInt int lineColor) {
this.lineColor = lineColor;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (top > 0 && bottom > 0) {
paint.setColor(lineColor);
canvas.drawLine(0, top, getWidth(), top, paint);
canvas.drawLine(0, bottom, getWidth(), bottom, paint);
}
}
}
package com.rv.rvmine.view;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.LinearInterpolator;
import android.widget.OverScroller;
import com.rv.rvmine.R;
public class WheelView extends View implements IWheelViewSetting {
private final String TAG = "WheelView";
private static final float DEFAULT_ROTATION_X = 45.0f;
private static final int DEFAULT_VELOCITY_UNITS = 600;
private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private Camera camera = new Camera();
private Matrix matrix = new Matrix();
private float textBaseLine = 0;
private IWheel[] items = null;
/**
* The color of show text.
*/
private int textColor = Color.BLACK;
/**
* The size of showing text.
* Default value is 14dp.
*/
private float textSize = 0.0f;
/**
* The offset pixel from x coordination.
* <br>text align {@code right} with a positive value
* <br>text align {@code center} with 0 value
* <br>text align {@code left} with a negative value
*/
private int totalOffsetX = 0;
/**
* the average pixel length of show text.
*/
private float averageShowTextLength = 0;
/**
* The most showing item count.
* use it to measure view's height
*/
private int showCount = 3;
/**
* The most draw item count.
*/
private int drawCount = showCount + 2;
private Rect[] defaultRectArray = null;
private Rect[] drawRectArray = null;
private int offsetY = 0;
private int totalMoveY = 0;//
private float wheelRotationX = 0;
private int velocityUnits = 0;
/**
* the space width of two items
*/
private int itemVerticalSpace = 0;
/**
* the height of every item
*/
private int itemHeight = 0;
private float lastX = 0.0f;
private float lastY = 0.0f;
private int[] calculateResult = new int[2];//for saving the calculate result.
private int selectedIndex = 0;//the selected index position
private OnSelectedListener onSelectedListener = null;
private ValueAnimator animator = null;
private boolean isScrolling = false;
private boolean isAnimatorCanceledForwardly = false;//whether cancel auto scroll animation forwardly
private static final long CLICK_EVENT_INTERNAL_TIME = 1000;
private RectF rectF = new RectF();
private long touchDownTimeStamp = 0;
//about fling action
private int mMinimumVelocity;
private int mMaximumVelocity;
private int scaledTouchSlop;
private VelocityTracker mVelocityTracker = null;
private OverScroller mOverScroller;
private int flingDirection = 0;//-1向上、1向下
public WheelView(Context context) {
super(context);
initAttr(context, null, 0);
}
public WheelView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttr(context, attrs, 0);
}
public WheelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttr(context, attrs, defStyleAttr);
}
public void initAttr(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
mOverScroller = new OverScroller(context);
final ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mMinimumVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
mMaximumVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
scaledTouchSlop = viewConfiguration.getScaledTouchSlop();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WheelView, defStyleAttr, 0);
float defaultTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, getResources().getDisplayMetrics());
textColor = a.getColor(R.styleable.WheelView_wheelTextColor, 0xFF171413);
textSize = a.getDimension(R.styleable.WheelView_wheelTextSize, defaultTextSize);
showCount = 3;
totalOffsetX = a.getDimensionPixelSize(R.styleable.WheelView_wheelTotalOffsetX, 0);
itemVerticalSpace = 50;
wheelRotationX = a.getFloat(R.styleable.WheelView_wheelRotationX, DEFAULT_ROTATION_X);
velocityUnits = a.getInteger(R.styleable.WheelView_wheelRotationX, DEFAULT_VELOCITY_UNITS);
if (velocityUnits < 0) {
velocityUnits = Math.abs(velocityUnits);
}
a.recycle();
initConfig();
if (isInEditMode()) {
IWheel[] items = new IWheel[50];
for (int i = 0; i < items.length; i++) {
items[i] = new WheelItem("菜单选项" + (i < 10 ? "0" + i : String.valueOf(i)));
}
setItems(items);
}
}
private void initConfig() {
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
String testText = "菜单选项";
Rect rect = new Rect();
textPaint.getTextBounds(testText, 0, testText.length(), rect);
itemHeight = rect.height() + itemVerticalSpace;
textBaseLine = -itemHeight / 2.0f + (itemHeight - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
// if (showCount < 5) {
// showCount = 5;
// }
if (showCount % 2 == 0) {
showCount++;
}
drawCount = showCount + 2;
defaultRectArray = new Rect[drawCount];
drawRectArray = new Rect[drawCount];
for (int i = 0; i < drawCount; i++) {
defaultRectArray[i] = new Rect();
drawRectArray[i] = new Rect();
}
}
@Override
public void setTextSize(float textSize) {
this.textSize = textSize;
initConfig();
requestLayout();
}
@Override
public void setTextColor(@ColorInt int textColor) {
this.textColor = textColor;
textPaint.setColor(textColor);
invalidate();
}
@Override
public void setShowCount(int showCount) {
this.showCount = showCount;
initConfig();
requestLayout();
}
@Override
public void setTotalOffsetX(int totalOffsetX) {
this.totalOffsetX = totalOffsetX;
invalidate();
}
@Override
public void setItemVerticalSpace(int itemVerticalSpace) {
this.itemVerticalSpace = itemVerticalSpace;
initConfig();
requestLayout();
}
/**
* Set the fling velocity units.
* The default value is {@link #DEFAULT_VELOCITY_UNITS}.
* @param velocityUnits the velocity units
*/
public void setVelocityUnits(int velocityUnits) {
this.velocityUnits = Math.abs(velocityUnits);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int top = 0 - itemHeight;
for (int i = 0; i < drawCount; i++) {
defaultRectArray[i].set(0, top, 0, top + itemHeight);
top += itemHeight;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(itemHeight * showCount, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isEmpty())
return super.onTouchEvent(event);
initVelocityTrackerIfNotExists();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//add event into velocity tracker.
mVelocityTracker.clear();
//stop fling and reset fling direction
flingDirection = 0;
mOverScroller.forceFinished(true);
if (animator != null && animator.isRunning()) {
isAnimatorCanceledForwardly = true;
animator.cancel();
}
lastX = event.getX();
lastY = event.getY();
//Make it as a click event when touch down,
//and record touch down time stamp.
touchDownTimeStamp = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE:
//add event into velocity tracker and compute velocity.
mVelocityTracker.addMovement(event);
float currentX = event.getX();
float currentY = event.getY();
int distance = (int) (currentY - lastY);
int direction = 0;
if (distance == 0)
break;
//if moved, cancel click event
touchDownTimeStamp = 0;
direction = distance / Math.abs(distance);
//initialize touch area
rectF.set(0, 0, getWidth(), getHeight());
if (rectF.contains(currentX, currentY)) {
//inside touch area, execute move event.
lastX = currentX;
lastY = currentY;
updateByTotalMoveY(totalMoveY + distance, direction);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (System.currentTimeMillis() - touchDownTimeStamp <= CLICK_EVENT_INTERNAL_TIME) {
//it's a click event, do it
executeClickEvent(event.getX(), event.getY());
break;
}
//calculate current velocity
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(velocityUnits, mMaximumVelocity);
float currentVelocity = velocityTracker.getYVelocity();
recycleVelocityTracker();
final int tempFlingDirection = currentVelocity == 0 ? 0 : (currentVelocity < 0 ? -1 : 1);
if (Math.abs(currentVelocity) >= mMinimumVelocity) {
//it's a fling event.
flingDirection = tempFlingDirection;
mOverScroller.fling(
0, totalMoveY,
0, (int) currentVelocity,
0, 0,
-(getItemCount() + showCount / 2) * itemHeight, (showCount / 2) * itemHeight,
0, 0
);
invalidate();
} else {
calculateSelectedIndex(totalMoveY, tempFlingDirection);
selectedIndex = calculateResult[0];
offsetY = calculateResult[1];
//execute rebound animation
executeAnimation(
totalMoveY,
0 - selectedIndex * itemHeight
);
}
break;
}
return true;
}
public void setOnSelectedListener(OnSelectedListener onSelectedListener) {
this.onSelectedListener = onSelectedListener;
}
public void setItems(IWheel[] items) {
this.items = items;
if (!isEmpty()) {
averageShowTextLength = calAverageShowTextLength();
invalidate();
}
}
public int getItemHeight() {
return itemHeight;
}
public int getShowCount() {
return showCount;
}
/**
* Get the current selected index position.
*
* @return the current selected index position
*/
public int getSelectedIndex() {
return selectedIndex;
}
/**
* Scroll to fixed index position with animation.
*
* @param targetIndexPosition the target index position
*/
public void setSelectedIndex(int targetIndexPosition) {
setSelectedIndex(targetIndexPosition, true);
}
/**
* Set the 3D rotation.
*
* @param wheelRotationX the rotate wheel base x axis
*/
public void setWheelRotationX(float wheelRotationX) {
if (this.wheelRotationX != wheelRotationX) {
this.wheelRotationX = wheelRotationX;
invalidate();
}
}
/**
* Scroll to fixed index position.
*
* @param targetIndexPosition the target index position
* @param withAnimation true, scroll with animation
*/
public void setSelectedIndex(int targetIndexPosition, boolean withAnimation) {
if (targetIndexPosition < 0 || targetIndexPosition >= getItemCount())
throw new IndexOutOfBoundsException("Out of array bounds.");
if (withAnimation) {
executeAnimation(totalMoveY, 0 - itemHeight * targetIndexPosition);
} else {
totalMoveY = 0 - itemHeight * targetIndexPosition;
selectedIndex = targetIndexPosition;
offsetY = 0;
invalidate();
if (onSelectedListener != null)
onSelectedListener.onSelected(getContext(), selectedIndex);
}
}
@Override
public boolean isScrolling() {
return isScrolling;
}
/**
* Calculate average pixel length of show text.
*
* @return the average pixel length of show text
*/
private float calAverageShowTextLength() {
float totalLength = 0;
String showText = null;
for (IWheel wheel : items) {
showText = wheel.getShowText();
if (showText == null || showText.length() == 0)
continue;
totalLength += textPaint.measureText(showText);
}
return totalLength / getItemCount();
}
/**
* Execute click event.
*
* @return true, valid click event, else invalid.
*/
private void executeClickEvent(float upX, float upY) {
boolean isValidTempSelectedIndex = false;
int tempSelectedIndex = selectedIndex - drawCount / 2;
for (int i = 0; i < drawCount; i++) {
rectF.set(drawRectArray[i]);
if (rectF.contains(upX, upY)) {
isValidTempSelectedIndex = true;
break;
}
tempSelectedIndex++;
}
if (isValidTempSelectedIndex
&& tempSelectedIndex >= 0
&& tempSelectedIndex < getItemCount()) {
//Move to target selected index
setSelectedIndex(tempSelectedIndex);
}
}
private int getItemCount() {
return items == null ? 0 : items.length;
}
private IWheel getItemAt(int position) {
if (isEmpty() || position < 0 || position >= getItemCount())
return null;
return items[position];
}
private boolean isEmpty() {
return getItemCount() == 0;
}
/**
* Execute animation.
*/
private void executeAnimation(int... values) {
//if it's invalid animation, call back immediately.
if (invalidAnimation(values)) {
if (onSelectedListener != null)
onSelectedListener.onSelected(getContext(), selectedIndex);
return;
}
int duration = 0;
for (int i = 0; i < values.length; i++) {
if (i > 0) {
duration += Math.abs(values[i] - values[i - 1]);
}
}
if (duration == 0) {
if (onSelectedListener != null)
onSelectedListener.onSelected(getContext(), selectedIndex);
return;
}
createAnimatorIfNecessary();
if (animator.isRunning()) {
isAnimatorCanceledForwardly = true;
animator.cancel();
}
animator.setIntValues(values);
animator.setDuration(calSuitableDuration(duration));
animator.start();
}
private boolean invalidAnimation(int... values) {
if (values == null || values.length < 2)
return true;
int firstValue = values[0];
for (int value : values) {
if (firstValue != value)
return false;
}
return true;
}
private int calSuitableDuration(int duration) {
int result = duration;
while (result > 1200) {
result = result / 2;
}
return result;
}
/**
* Create auto-scroll animation.
*/
private void createAnimatorIfNecessary() {
if (animator == null) {
animator = new ValueAnimator();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int tempTotalMoveY = (int) animation.getAnimatedValue();
updateByTotalMoveY(tempTotalMoveY, 0);
}
});
animator.setInterpolator(new LinearInterpolator());
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
isScrolling = true;
}
@Override
public void onAnimationEnd(Animator animation) {
isScrolling = false;
//Cancel animation forwardly.
if (isAnimatorCanceledForwardly) {
isAnimatorCanceledForwardly = false;
return;
}
if (onSelectedListener != null)
onSelectedListener.onSelected(getContext(), selectedIndex);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
}
public int getTotalMoveY() {
return totalMoveY;
}
private void updateByTotalMoveY(final int totalMoveY, int direction) {
calculateSelectedIndex(totalMoveY, direction);
this.totalMoveY = totalMoveY;
this.selectedIndex = calculateResult[0];
this.offsetY = calculateResult[1];
invalidate();
}
private void calculateSelectedIndex(int totalMoveY, int direction) {
int selectedIndex = totalMoveY / (0 - itemHeight);
int rest = totalMoveY % (0 - itemHeight);
if (direction > 0 && rest != 0) {
selectedIndex ++;
rest = itemHeight - Math.abs(rest);
}
//move up
if (direction < 0 && Math.abs(rest) >= itemHeight / 4) {
selectedIndex++;
}
//move down
if (direction > 0 && Math.abs(rest) >= itemHeight / 4) {
selectedIndex --;
}
selectedIndex = Math.max(selectedIndex, 0);
selectedIndex = Math.min(selectedIndex, getItemCount() - 1);
int offsetY = (0 - selectedIndex * itemHeight) - totalMoveY;
calculateResult[0] = selectedIndex;
calculateResult[1] = offsetY;
}
@Override
public void computeScroll() {
if (mOverScroller.computeScrollOffset()) {
totalMoveY = mOverScroller.getCurrY();
updateByTotalMoveY(totalMoveY, 0);
invalidate();
return;
}
if (flingDirection != 0) {
final int flingDirectionCopy = flingDirection;
flingDirection = 0;
calculateSelectedIndex(totalMoveY, flingDirectionCopy);
selectedIndex = calculateResult[0];
offsetY = calculateResult[1];
//execute rebound animation
executeAnimation(
totalMoveY,
0 - selectedIndex * itemHeight
);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (isEmpty())
return;
int tempStartSelectedIndex = selectedIndex - drawCount / 2;
for (int i = 0; i < drawCount; i++) {
Rect rect = drawRectArray[i];
rect.set(defaultRectArray[i]);
//record touch area for click event
rect.left = 0;
rect.right = getWidth();
if (tempStartSelectedIndex >= 0 && tempStartSelectedIndex < getItemCount()) {
drawItem(canvas, rect, getItemAt(tempStartSelectedIndex), -offsetY, textPaint);
}
tempStartSelectedIndex++;
}
computeScroll();
}
private void drawItem(Canvas canvas, Rect rect, IWheel item, int offsetY, TextPaint textPaint) {
String text = item == null ? "" : item.getShowText();
if (text == null || text.trim().length() == 0)
return;
rect.offset(0, offsetY);
textPaint.setAlpha(calAlpha(rect));
final int offsetX = totalOffsetX == 0 ? 0 : calOffsetX(totalOffsetX, rect);
final float w = textPaint.measureText(text);
float startX = 0;
if (totalOffsetX > 0) {
//show text align right
final float rightAlignPosition = (getWidth() + averageShowTextLength) / 2.0f;
startX = rightAlignPosition - w + offsetX;
} else if (totalOffsetX < 0) {
//show text align left
final float leftAlignPosition = (getWidth() - averageShowTextLength) / 2.0f;
startX = leftAlignPosition + offsetX;
} else {
//show text align center_horizontal
startX = (getWidth() - w) / 2.0f + offsetX;
}
float centerX = getWidth() / 2.0f;
float centerY = rect.exactCenterY();
float baseLine = centerY + textBaseLine;
matrix.reset();
camera.save();
camera.rotateX(calRotationX(rect, wheelRotationX));
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
if (totalOffsetX > 0) {
float skewX = 0 - calSkewX(rect);
centerX = (startX + w) / 2.0f;
matrix.setSkew(skewX, 0, centerX, centerY);
} else if (totalOffsetX < 0) {
float skewX = calSkewX(rect);
centerX = (startX + w) / 2.0f;
matrix.setSkew(skewX, 0, centerX, centerY);
}
canvas.save();
canvas.concat(matrix);
canvas.drawText(text, startX, baseLine, textPaint);
canvas.restore();
}
private int calAlpha(Rect rect) {
int centerY = getHeight() / 2;
int distance = Math.abs(centerY - rect.centerY());
int totalDistance = itemHeight * (showCount / 2);
float alpha = 0.6f * distance / totalDistance;
return (int) ((1 - alpha) * 0xFF);
}
private float calRotationX(Rect rect, float baseRotationX) {
int centerY = getHeight() / 2;
int distance = centerY - rect.centerY();
int totalDistance = itemHeight * (showCount / 2);
return baseRotationX * distance * 1.0f / totalDistance;
}
private float calSkewX(Rect rect) {
int centerY = getHeight() / 2;
int distance = centerY - rect.centerY();
int totalDistance = itemHeight * (showCount / 2);
return 0.3f * distance / totalDistance;
}
private int calOffsetX(int totalOffsetX, Rect rect) {
int centerY = getHeight() / 2;
int distance = Math.abs(centerY - rect.centerY());
int totalDistance = itemHeight * (showCount / 2);
return totalOffsetX * distance / totalDistance;
}
private void initVelocityTrackerIfNotExists() {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
}
private void recycleVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
public interface OnSelectedListener {
void onSelected(Context context, int selectedIndex);
}
}
......@@ -161,6 +161,7 @@
</LinearLayout>
<TextView
android:visibility="gone"
android:id="@+id/tv_capacity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/size_30"
android:layout_marginRight="@dimen/size_30"
android:background="@drawable/shape_rv_bg_write"
android:orientation="vertical">
<TextView
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="@dimen/size_50"
android:gravity="center"
android:text="生日"
android:textColor="@color/colorMain"
android:textSize="@dimen/text_20" />
<include layout="@layout/common_line" />
<LinearLayout
android:id="@+id/wheel_id_picker_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
<Button
android:id="@+id/btn_confirm"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_40"
android:layout_marginLeft="@dimen/size_20"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginRight="@dimen/size_20"
android:layout_marginBottom="@dimen/size_20"
android:background="@drawable/shape_rv_bg_fdc349"
android:gravity="center"
android:text="确定"
android:textColor="@color/white"
android:textSize="@dimen/sp_16" />
</LinearLayout>
\ No newline at end of file
......@@ -8,4 +8,13 @@
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="WheelDialog" parent="android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WheelView">
<attr name="wheelTextColor" format="color"/>
<attr name="wheelTextSize" format="dimension"/>
<attr name="wheelShowCount" format="integer"/>
<attr name="wheelTotalOffsetX" format="dimension"/>
<attr name="wheelItemVerticalSpace" format="dimension"/>
<attr name="wheelRotationX" format="float"/>
<attr name="wheelVelocityUnits" format="integer"/>
</declare-styleable>
<declare-styleable name="WheelMaskView">
<attr name="wheelMaskLineColor" format="color"/>
</declare-styleable>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment