之前做过一些需求,因为开发周期短,在产品分类的弹窗上一直有一些遗憾,这次又遇到了分类的页面要做,所以花了点时间思考,利用一个开源组件SlideBottomPanel成功实现了一个体验很好的分类功能
网上流传了很多版本的弹窗,但基本都是基于popWindow,Spinner,或者直接覆盖一层Dialog,大多用户必须手点把外层的弹窗点掉,才能选择其他种类的分类放,逼死强迫
症有木有。
捣鼓了一番,效果如下
真正使用效果会非常平滑
废话不多说,Git地址https://github.com/kingideayou/SlideBottomPanel
下载后可以直接把几个java文件复制到自己的项目中,同时记得复制attr参数信息
项目需要Jar包:SmartAndroid
全部弄好,写页面~
SlideBottomPanel中的一个属性background_layout必须填,这里定义的这个控件所覆盖的页面,可以理解成它本身是一个Framelayout,这个属性定义的是最底层的一个页面
,如果你用其他手段(外部用FrameLayout去做重叠,那么他会强制截取掉你的触摸事件)
我这边简单的做了一个空的页面background_layout,内部是可以任意编辑的,比如在其中加入ScrollView等
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private SlideBottomPanel sbp;
private RadioButton rbBank;
private RadioButton rbRange;
private RadioButton rbMoney;
private RadioButton rbTime;
private ImageView arrow1;
private ImageView arrow2;
private ImageView arrow3;
private ImageView arrow4;
private ListView lvCreditSort;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initTit();
setListen();
initData();
}
private void initData() {
lvCreditSort.setAdapter(new ArrayAdapter<>(MainActivity.this, R.layout.list_item, getData()));
}
private ArrayList getData()
{
ArrayList list = new ArrayList();
for (int i = 0; i < 20; i++) {
list.add("Item " + i);
}
return list;
}
private void setListen() {
rbMoney.setOnClickListener(this);
rbTime.setOnClickListener(this);
rbRange.setOnClickListener(this);
rbBank.setOnClickListener(this);
sbp.setOnStateChangeListener(new SlideBottomPanel.OnStateChangeListener() {
@Override
public void Hidden(boolean isHidden) {
if (isHidden){
clearArrow();
clearTextColor();
}
}
});
}
private void initView() {
lvCreditSort = (ListView) findViewById(R.id.lv_credit_sort);
sbp = (SlideBottomPanel) findViewById(R.id.sbp);
rbBank = (RadioButton) findViewById(R.id.rb_bank);
rbMoney = (RadioButton) findViewById(R.id.rb_money);
rbRange = (RadioButton) findViewById(R.id.rb_range);
rbTime = (RadioButton) findViewById(R.id.rb_time);
arrow1 = (ImageView) findViewById(R.id.arrow1);
arrow2 = (ImageView) findViewById(R.id.arrow2);
arrow3 = (ImageView) findViewById(R.id.arrow3);
arrow4 = (ImageView) findViewById(R.id.arrow4);
}
private void initTit() {
rbBank.setText("机构类型");
rbRange.setText("综合排序");
rbMoney.setText("金额范围");
rbTime.setText("贷款期限");
}
public void clearTextColor(){
rbTime.setTextColor(getResources().getColor(R.color.black));
rbMoney.setTextColor(getResources().getColor(R.color.black));
rbRange.setTextColor(getResources().getColor(R.color.black));
rbBank.setTextColor(getResources().getColor(R.color.black));
}
public void clearArrow(){
arrow1.setImageResource(R.mipmap.arrow_black);
arrow2.setImageResource(R.mipmap.arrow_black);
arrow3.setImageResource(R.mipmap.arrow_black);
arrow4.setImageResource(R.mipmap.arrow_black);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.rb_bank:
clearArrow();
clearTextColor();
rbBank.setTextColor(getResources().getColor(R.color.tv_money_color));
arrow1.setImageResource(R.mipmap.arrow_orienge_up);
sbp.reOpen();
break;
case R.id.rb_money:
clearArrow();
clearTextColor();
rbMoney.setTextColor(getResources().getColor(R.color.tv_money_color));
arrow3.setImageResource(R.mipmap.arrow_orienge_up);
sbp.reOpen();
break;
case R.id.rb_range:
clearArrow();
clearTextColor();
rbRange.setTextColor(getResources().getColor(R.color.tv_money_color));
arrow2.setImageResource(R.mipmap.arrow_orienge_up);
sbp.reOpen();
break;
case R.id.rb_time:
clearArrow();
clearTextColor();
rbTime.setTextColor(getResources().getColor(R.color.tv_money_color));
arrow4.setImageResource(R.mipmap.arrow_orienge_up);
sbp.reOpen();
break;
default:
break;
}
}
}
http://download.csdn.net/detail/u013475663/9564166
因为时间原因,先把完全版的代码地址贴上,哈哈哈,赚点分,有时间继续完善
好,下一步的工作,原版本的开源组件虽然能实现大部分的功能,但在快速点击,他是反应不过来的,以为他在动画的前面进行了判断,如果进行动画中,那么忽略你的操作
直接加一个方法
private void reOpenPanel() {
final View mPanel = findViewWithTag(TAG_PANEL);
if (isPanelShowing()){
if (isAnimating) {
mPanel.clearAnimation();
isAnimating = false;
reOpen();
return;
}
final int t = (int)(mMeasureHeight - mTitleHeightNoDisplay);
ValueAnimator animator = ValueAnimator.ofFloat(
ViewHelper.getY(mPanel), mMeasureHeight - mTitleHeightNoDisplay);
animator.setInterpolator(mCloseAnimationInterpolator);
animator.setTarget(mPanel);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
ViewHelper.setY(mPanel, value);
if (mDarkFrameLayout != null && mIsFade && value < t) {
mDarkFrameLayout.fade((int) ((1 - value / t) * DarkFrameLayout.MAX_ALPHA));
}
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
isAnimating = true;
}
@Override
public void onAnimationEnd(Animator animation) {
isAnimating = false;
isPanelShowing = false;
showPanelTitle(mPanel);
displayPanel();
}
@Override
public void onAnimationCancel(Animator animation) {
isAnimating = false;
isPanelShowing = false;
showPanelTitle(mPanel);
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(50);
animator.start();
}else {
displayPanel();
}
}
此时快速点击就可以完美运行啦
但是仔细一看,卧槽,点击暗层的监听这个也没有
public interface OnStateChangeListener{ void Hidden(boolean isHidden); } OnStateChangeListener mOnStateChangeListener; public void setOnStateChangeListener(OnStateChangeListener e){ mOnStateChangeListener=e; }
加个监听
重新写一下hide()方法中的Listener
animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { isAnimating = true; } @Override public void onAnimationEnd(Animator animation) { isAnimating = false; isPanelShowing = false; mOnStateChangeListener.Hidden(true); showPanelTitle(mPanel); } @Override public void onAnimationCancel(Animator animation) { isAnimating = false; isPanelShowing = false; mOnStateChangeListener.Hidden(true); showPanelTitle(mPanel); } @Override public void onAnimationRepeat(Animator animation) { } });
Ok,完事大吉~