+ * This can be used as the root view for a custom list item layout for
+ * {@link android.widget.AbsListView} elements with a
+ * {@link android.widget.AbsListView#setChoiceMode(int) choiceMode} set.
+ */
+public class CheckableLinearLayout extends LinearLayout implements Checkable {
+ private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
+
+ private boolean mChecked = false;
+
+ public CheckableLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ public void setChecked(boolean b) {
+ if (b != mChecked) {
+ mChecked = b;
+ refreshDrawableState();
+ }
+ }
+
+ public void toggle() {
+ setChecked(!mChecked);
+ }
+
+ @Override
+ public int[] onCreateDrawableState(int extraSpace) {
+ final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+ if (isChecked()) {
+ mergeDrawableStates(drawableState, CHECKED_STATE_SET);
+ }
+ return drawableState;
+ }
+}
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DividerItemDecoration.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DividerItemDecoration.java
new file mode 100644
index 0000000..0c4f519
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DividerItemDecoration.java
@@ -0,0 +1,86 @@
+package com.boredream.bdcodehelper.view;
+
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private static final int[] ATTRS = new int[]{
+ android.R.attr.listDivider
+ };
+
+ private List ignorePositionList;
+
+ private Drawable mDivider;
+
+ public DividerItemDecoration(Context context) {
+ final TypedArray a = context.obtainStyledAttributes(ATTRS);
+ mDivider = a.getDrawable(0);
+ a.recycle();
+ }
+
+ /**
+ * 忽略分割线的position,即该位置不添加
+ */
+ public void setIgnorePositions(Integer[] ignorePositions) {
+ ignorePositionList = Arrays.asList(ignorePositions);
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ drawVertical(c, parent);
+ }
+
+ public void drawVertical(Canvas c, RecyclerView parent) {
+ final int left = parent.getPaddingLeft();
+ final int right = parent.getWidth() - parent.getPaddingRight();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) { + if (ignorePositionList != null && ignorePositionList.contains(i)) { + continue; + } + + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int top = child.getBottom() + params.bottomMargin + + Math.round(ViewCompat.getTranslationY(child)); +// final int bottom = top + mDivider.getIntrinsicHeight(); + final int bottom = top + 1; + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { +// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); + outRect.set(0, 0, 0, 1); + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableRadioButton.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableRadioButton.java new file mode 100644 index 0000000..9fdff99 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableRadioButton.java @@ -0,0 +1,73 @@ +package com.boredream.bdcodehelper.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.RadioButton; + +import com.boredream.bdcodehelper.R; + + +public class DrawableRadioButton extends RadioButton { + + private int widthPx; + private int heightPx; + + public DrawableRadioButton(Context context) { + super(context); + } + + public DrawableRadioButton(Context context, AttributeSet attrs) { + super(context, attrs); + + initView(context, attrs); + } + + public DrawableRadioButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + initView(context, attrs); + } + + private void initView(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, + R.styleable.DrawableTextView); + + widthPx = ta.getDimensionPixelSize( + R.styleable.DrawableTextView_drawableWidth, -1); + heightPx = ta.getDimensionPixelSize( + R.styleable.DrawableTextView_drawableHeight, -1); + + // 左右上下四个图片 + Drawable[] drawables = getCompoundDrawables(); + + setDrawables(drawables); + + ta.recycle(); + } + + /** + * 左上右下四个图片,只会取一个方向图片使用 + */ + public void setDrawables(Drawable[] drawables) { + // 左右上下四个图片 + Drawable drawable = null; + // 如果其中一个方向有图片,获取之 + for (int i = 0; i < drawables.length; i++) { + if (drawables[i] != null) { + drawable = drawables[i]; + break; + } + } + + // 设置宽高 + if (drawable != null && widthPx != -1 && heightPx != -1) { + drawable.setBounds(0, 0, widthPx, heightPx); + } + + // 将图片放回到TextView中 + setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawables[3]); + } + +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableTextView.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableTextView.java new file mode 100644 index 0000000..ef08928 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DrawableTextView.java @@ -0,0 +1,67 @@ +package com.boredream.bdcodehelper.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.boredream.bdcodehelper.R; + + +public class DrawableTextView extends TextView { + + private final int widthPx; + private final int heightPx; + + public DrawableTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray ta = context.obtainStyledAttributes(attrs, + R.styleable.DrawableTextView); + + widthPx = ta.getDimensionPixelSize( + R.styleable.DrawableTextView_drawableWidth, -1); + heightPx = ta.getDimensionPixelSize( + R.styleable.DrawableTextView_drawableHeight, -1); + + // 左右上下四个图片 + Drawable[] drawables = getCompoundDrawables(); + + setDrawables(drawables); + + ta.recycle(); + } + + /** + * 左上右下四个图片,只会取一个方向图片使用 + */ + public void setDrawables(Drawable[] drawables) { + // 左右上下四个图片 + Drawable drawable = null; + // 如果其中一个方向有图片,获取之 + for (int i = 0; i < drawables.length; i++) { + if (drawables[i] != null) { + drawable = drawables[i]; + break; + } + } + + // 设置宽高 + if (drawable != null && widthPx != -1 && heightPx != -1) { + drawable.setBounds(0, 0, widthPx, heightPx); + } + + // 将图片放回到TextView中 + setCompoundDrawables(drawables[0], drawables[1], drawables[2], drawables[3]); + } + + public DrawableTextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DrawableTextView(Context context) { + this(context, null); + } + +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DropDownMenu.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DropDownMenu.java new file mode 100644 index 0000000..8b4f5e6 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/DropDownMenu.java @@ -0,0 +1,256 @@ +package com.boredream.bdcodehelper.view; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.boredream.bdcodehelper.R; + +import java.util.List; + +public class DropDownMenu extends LinearLayout { + + //顶部菜单布局 + private LinearLayout tabMenuView; + //底部容器,包含popupMenuViews,maskView + private FrameLayout containerView; + //弹出菜单父布局 + private FrameLayout popupMenuViews; + //遮罩半透明View,点击可关闭DropDownMenu + private View maskView; + //tabMenuView里面选中的tab位置,-1表示未选中 + private int current_tab_position = -1; + + //分割线颜色 + private int dividerColor = getResources().getColor(R.color.divider_gray); + //tab选中颜色 + private int textSelectedColor = getResources().getColor(R.color.colorPrimary); + //tab未选中颜色 + private int textUnselectedColor = getResources().getColor(R.color.txt_black); + //遮罩颜色 + private int maskColor = 0x88888888; + //tab字体大小 + private int menuTextSize = 12; + + //tab选中图标 + private int menuSelectedIcon; + //tab未选中图标 + private int menuUnselectedIcon; + + + public DropDownMenu(Context context) { + super(context, null); + } + + public DropDownMenu(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public DropDownMenu(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + setOrientation(VERTICAL); + + //为DropDownMenu添加自定义属性 + int menuBackgroundColor = 0xffffffff; + int underlineColor = 0xffcccccc; + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DropDownMenu); + underlineColor = a.getColor(R.styleable.DropDownMenu_ddunderlineColor, underlineColor); + dividerColor = a.getColor(R.styleable.DropDownMenu_dddividerColor, dividerColor); + textSelectedColor = a.getColor(R.styleable.DropDownMenu_ddtextSelectedColor, textSelectedColor); + textUnselectedColor = a.getColor(R.styleable.DropDownMenu_ddtextUnselectedColor, textUnselectedColor); + menuBackgroundColor = a.getColor(R.styleable.DropDownMenu_ddmenuBackgroundColor, menuBackgroundColor); + maskColor = a.getColor(R.styleable.DropDownMenu_ddmaskColor, maskColor); + menuTextSize = a.getDimensionPixelSize(R.styleable.DropDownMenu_ddmenuTextSize, menuTextSize); + menuSelectedIcon = a.getResourceId(R.styleable.DropDownMenu_ddmenuSelectedIcon, menuSelectedIcon); + menuUnselectedIcon = a.getResourceId(R.styleable.DropDownMenu_ddmenuUnselectedIcon, menuUnselectedIcon); + a.recycle(); + + //初始化tabMenuView并添加到tabMenuView + tabMenuView = new LinearLayout(context); + LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + tabMenuView.setOrientation(HORIZONTAL); + tabMenuView.setBackgroundColor(menuBackgroundColor); + tabMenuView.setLayoutParams(params); + addView(tabMenuView, 0); + + //为tabMenuView添加下划线 + View underLine = new View(getContext()); + underLine.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpTpPx(1.0f))); + underLine.setBackgroundColor(underlineColor); + addView(underLine, 1); + + //初始化containerView并将其添加到DropDownMenu + containerView = new FrameLayout(context); + containerView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); + addView(containerView, 2); + + } + + /** + * 初始化DropDownMenu + * + * @param tabTexts + * @param popupViews + * @param contentView + */ + public void setDropDownMenu(List tabTexts, List popupViews, View contentView) {
+ if (tabTexts.size() != popupViews.size()) {
+ throw new IllegalArgumentException("params not match, tabTexts.size() should be equal popupViews.size()");
+ }
+
+ for (int i = 0; i < tabTexts.size(); i++) { + addTab(tabTexts, i); + } + + containerView.addView(contentView, 0); + + maskView = new View(getContext()); + maskView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); + maskView.setBackgroundColor(maskColor); + maskView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + closeMenu(); + } + }); + containerView.addView(maskView, 1); + maskView.setVisibility(GONE); + + popupMenuViews = new FrameLayout(getContext()); + popupMenuViews.setVisibility(GONE); + containerView.addView(popupMenuViews, 2); + + for (int i = 0; i < popupViews.size(); i++) { + popupViews.get(i).setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + popupMenuViews.addView(popupViews.get(i), i); + } + + } + + private void addTab(List tabTexts, int i) {
+ final TextView tab = new TextView(getContext());
+ tab.setSingleLine();
+ tab.setEllipsize(TextUtils.TruncateAt.END);
+ tab.setGravity(Gravity.CENTER);
+ tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, menuTextSize);
+ tab.setLayoutParams(new LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
+ tab.setTextColor(textUnselectedColor);
+ tab.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(menuUnselectedIcon), null);
+ tab.setText(tabTexts.get(i));
+ tab.setPadding(dpTpPx(48), dpTpPx(8), dpTpPx(48), dpTpPx(8));
+ //添加点击事件
+ tab.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ switchMenu(tab);
+ }
+ });
+ tabMenuView.addView(tab);
+ //添加分割线
+ if (i < tabTexts.size() - 1) { + View view = new View(getContext()); + LayoutParams params = new LayoutParams( + dpTpPx(0.5f), ViewGroup.LayoutParams.MATCH_PARENT); + params.setMargins(0, dpTpPx(4), 0, dpTpPx(4)); + view.setLayoutParams(params); + view.setBackgroundColor(dividerColor); + tabMenuView.addView(view); + } + } + + /** + * 改变tab文字 + * + * @param text + */ + public void setTabText(String text) { + if (current_tab_position != -1) { + ((TextView) tabMenuView.getChildAt(current_tab_position)).setText(text); + } + } + + public void setTabClickable(boolean clickable) { + for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) { + tabMenuView.getChildAt(i).setClickable(clickable); + } + } + + /** + * 关闭菜单 + */ + public void closeMenu() { + if (current_tab_position != -1) { + ((TextView) tabMenuView.getChildAt(current_tab_position)).setTextColor(textUnselectedColor); + ((TextView) tabMenuView.getChildAt(current_tab_position)).setCompoundDrawablesWithIntrinsicBounds(null, null, + getResources().getDrawable(menuUnselectedIcon), null); + popupMenuViews.setVisibility(View.GONE); + popupMenuViews.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_menu_out)); + maskView.setVisibility(GONE); + maskView.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_mask_out)); + current_tab_position = -1; + } + + } + + /** + * DropDownMenu是否处于可见状态 + * + * @return + */ + public boolean isShowing() { + return current_tab_position != -1; + } + + /** + * 切换菜单 + * + * @param target + */ + private void switchMenu(View target) { + for (int i = 0; i < tabMenuView.getChildCount(); i = i + 2) { + if (target == tabMenuView.getChildAt(i)) { + if (current_tab_position == i) { + closeMenu(); + } else { + if (current_tab_position == -1) { + popupMenuViews.setVisibility(View.VISIBLE); + popupMenuViews.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_menu_in)); + maskView.setVisibility(VISIBLE); + maskView.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.dd_mask_in)); + popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE); + } else { + popupMenuViews.getChildAt(i / 2).setVisibility(View.VISIBLE); + } + current_tab_position = i; + ((TextView) tabMenuView.getChildAt(i)).setTextColor(textSelectedColor); + ((TextView) tabMenuView.getChildAt(i)).setCompoundDrawablesWithIntrinsicBounds(null, null, + getResources().getDrawable(menuSelectedIcon), null); + } + } else { + ((TextView) tabMenuView.getChildAt(i)).setTextColor(textUnselectedColor); + ((TextView) tabMenuView.getChildAt(i)).setCompoundDrawablesWithIntrinsicBounds(null, null, + getResources().getDrawable(menuUnselectedIcon), null); + popupMenuViews.getChildAt(i / 2).setVisibility(View.GONE); + } + } + } + + public int dpTpPx(float value) { + DisplayMetrics dm = getResources().getDisplayMetrics(); + return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm) + 0.5); + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/EmptyItemDecoration.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/EmptyItemDecoration.java new file mode 100644 index 0000000..f8d63aa --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/EmptyItemDecoration.java @@ -0,0 +1,50 @@ +package com.boredream.bdcodehelper.view; + +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import java.util.Arrays; +import java.util.List; + +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class EmptyItemDecoration extends RecyclerView.ItemDecoration { + + /** + * decoration添加的位置,为空时所有item都添加 + */ + private List dividerPositionList;
+ private int height;
+
+ public EmptyItemDecoration(int height) {
+ this.height = height;
+ }
+
+ public EmptyItemDecoration(Integer[] dividerPositions, int height) {
+ this.dividerPositionList = Arrays.asList(dividerPositions);
+ this.height = height;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ int position = parent.getChildAdapterPosition(view);
+ if (dividerPositionList == null || dividerPositionList.contains(position)) {
+ outRect.set(0, 0, 0, height);
+ }
+ }
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/GridSpacingDecorator.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/GridSpacingDecorator.java
new file mode 100644
index 0000000..988ac1d
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/GridSpacingDecorator.java
@@ -0,0 +1,24 @@
+package com.boredream.bdcodehelper.view;
+
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public class GridSpacingDecorator extends RecyclerView.ItemDecoration {
+
+ private int space;
+
+ public GridSpacingDecorator(int space) {
+ this.space = space;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ outRect.left = space / 2;
+ outRect.right = space / 2;
+ outRect.bottom = space;
+ if (parent.getChildAdapterPosition(view) <= 1) { + outRect.top = space; + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PinnedSectionListView.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PinnedSectionListView.java new file mode 100644 index 0000000..b9811bd --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PinnedSectionListView.java @@ -0,0 +1,547 @@ +package com.boredream.bdcodehelper.view; +/* + * Copyright (C) 2013 Sergej Shafarenka, halfbit.de + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file kt in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityEvent; +import android.widget.AbsListView; +import android.widget.HeaderViewListAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.SectionIndexer; + +import com.boredream.bdcodehelper.BuildConfig; + +/** + * ListView, which is capable to pin section views at its top while the rest is still scrolled. + */ +public class PinnedSectionListView extends ListView { + + + //-- inner classes + + /** List adapter to be implemented for being used with PinnedSectionListView adapter. */ + public static interface PinnedSectionListAdapter extends ListAdapter { + /** This method shall return 'true' if views of given type has to be pinned. */ + boolean isItemViewTypePinned(int viewType); + } + + /** Wrapper class for pinned section view and its position in the list. */ + static class PinnedSection { + public View view; + public int position; + public long id; + } + + //-- class fields + + // fields used for handling touch events + private final Rect mTouchRect = new Rect(); + private final PointF mTouchPoint = new PointF(); + private int mTouchSlop; + private View mTouchTarget; + private MotionEvent mDownEvent; + + // fields used for drawing shadow under a pinned section + private GradientDrawable mShadowDrawable; + private int mSectionsDistanceY; + private int mShadowHeight; + + /** Delegating listener, can be null. */ + OnScrollListener mDelegateOnScrollListener; + + /** Shadow for being recycled, can be null. */ + PinnedSection mRecycleSection; + + /** shadow instance with a pinned view, can be null. */ + PinnedSection mPinnedSection; + + /** Pinned view Y-translation. We use it to stick pinned view to the next section. */ + int mTranslateY; + + /** Scroll listener which does the magic */ + private final OnScrollListener mOnScrollListener = new OnScrollListener() { + + // boredream-view which need to hide + private View hideView; + + @Override public void onScrollStateChanged(AbsListView view, int scrollState) { + if (mDelegateOnScrollListener != null) { // delegate + mDelegateOnScrollListener.onScrollStateChanged(view, scrollState); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + + if (mDelegateOnScrollListener != null) { // delegate + mDelegateOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); + } + + // get expected adapter or fail fast + ListAdapter adapter = getAdapter(); + if (adapter == null || visibleItemCount == 0) return; // nothing to do + + final boolean isFirstVisibleItemSection = + isItemViewTypePinned(adapter, adapter.getItemViewType(firstVisibleItem)); + + if (isFirstVisibleItemSection) { + View sectionView = getChildAt(0); + if (sectionView.getTop() == getPaddingTop()) { // view sticks to the top, no need for pinned shadow + destroyPinnedShadow(); + // boredream-re show pinned item of list + if(hideView != null && hideView.getVisibility() == View.INVISIBLE) { + hideView.setVisibility(View.VISIBLE); + } + } else { // section doesn't stick to the top, make sure we have a pinned shadow + ensureShadowForPosition(firstVisibleItem, firstVisibleItem, visibleItemCount); + + // boredream-hide pinned item of list + if(mPinnedSection != null + && firstVisibleItem == mPinnedSection.position + && sectionView.getTop() < 0) { + hideView = sectionView; + sectionView.setVisibility(View.INVISIBLE); + } + } + } else { // section is not at the first visible position + // boredream-re show pinned item of list + if(hideView != null && hideView.getVisibility() == View.INVISIBLE) { + hideView.setVisibility(View.VISIBLE); + } + + int sectionPosition = findCurrentSectionPosition(firstVisibleItem); + if (sectionPosition> -1) { // we have section position
+ ensureShadowForPosition(sectionPosition, firstVisibleItem, visibleItemCount);
+ } else { // there is no section for the first visible item, destroy shadow
+ destroyPinnedShadow();
+ }
+ }
+ };
+
+ };
+
+ /** Default change observer. */
+ private final DataSetObserver mDataSetObserver = new DataSetObserver() {
+ @Override public void onChanged() {
+ recreatePinnedShadow();
+ };
+ @Override public void onInvalidated() {
+ recreatePinnedShadow();
+ }
+ };
+
+ //-- constructors
+
+ public PinnedSectionListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initView();
+ }
+
+ public PinnedSectionListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initView();
+ }
+
+ private void initView() {
+ setOnScrollListener(mOnScrollListener);
+ mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+ initShadow(true);
+ }
+
+ //-- public API methods
+
+ public void setShadowVisible(boolean visible) {
+ initShadow(visible);
+ if (mPinnedSection != null) {
+ View v = mPinnedSection.view;
+ invalidate(v.getLeft(), v.getTop(), v.getRight(), v.getBottom() + mShadowHeight);
+ }
+ }
+
+ //-- pinned section drawing methods
+
+ public void initShadow(boolean visible) {
+ if (visible) {
+ if (mShadowDrawable == null) {
+ mShadowDrawable = new GradientDrawable(Orientation.TOP_BOTTOM,
+ new int[] { Color.parseColor("#ffa0a0a0"), Color.parseColor("#50a0a0a0"), Color.parseColor("#00a0a0a0")});
+ mShadowHeight = (int) (8 * getResources().getDisplayMetrics().density);
+ }
+ } else {
+ if (mShadowDrawable != null) {
+ mShadowDrawable = null;
+ mShadowHeight = 0;
+ }
+ }
+ }
+
+ /** Create shadow wrapper with a pinned view for a view at given position */
+ void createPinnedShadow(int position) {
+
+ // try to recycle shadow
+ PinnedSection pinnedShadow = mRecycleSection;
+ mRecycleSection = null;
+
+ // create new shadow, if needed
+ if (pinnedShadow == null) pinnedShadow = new PinnedSection();
+ // request new view using recycled view, if such
+ View pinnedView = getAdapter().getView(position, pinnedShadow.view, PinnedSectionListView.this);
+
+ // read layout parameters
+ LayoutParams layoutParams = (LayoutParams) pinnedView.getLayoutParams();
+ if (layoutParams == null) {
+// layoutParams = (LayoutParams) generateDefaultLayoutParams();
+ // boredream-fix bug
+ layoutParams = (LayoutParams) new LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT, 0);
+ pinnedView.setLayoutParams(layoutParams);
+ }
+
+ int heightMode = MeasureSpec.getMode(layoutParams.height);
+ int heightSize = MeasureSpec.getSize(layoutParams.height);
+
+ if (heightMode == MeasureSpec.UNSPECIFIED) heightMode = MeasureSpec.EXACTLY;
+
+ int maxHeight = getHeight() - getListPaddingTop() - getListPaddingBottom();
+ if (heightSize> maxHeight) heightSize = maxHeight;
+
+ // measure & layout
+ int ws = MeasureSpec.makeMeasureSpec(getWidth() - getListPaddingLeft() - getListPaddingRight(), MeasureSpec.EXACTLY);
+ int hs = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
+ pinnedView.measure(ws, hs);
+ pinnedView.layout(0, 0, pinnedView.getMeasuredWidth(), pinnedView.getMeasuredHeight());
+ mTranslateY = 0;
+
+ // initialize pinned shadow
+ pinnedShadow.view = pinnedView;
+ pinnedShadow.position = position;
+ pinnedShadow.id = getAdapter().getItemId(position);
+
+ // store pinned shadow
+ mPinnedSection = pinnedShadow;
+ }
+
+ /** Destroy shadow wrapper for currently pinned view */
+ void destroyPinnedShadow() {
+ if (mPinnedSection != null) {
+ // keep shadow for being recycled later
+ mRecycleSection = mPinnedSection;
+ mPinnedSection = null;
+ }
+ }
+
+ /** Makes sure we have an actual pinned shadow for given position. */
+ void ensureShadowForPosition(int sectionPosition, int firstVisibleItem, int visibleItemCount) {
+ if (visibleItemCount < 2) { // no need for creating shadow at all, we have a single visible item + destroyPinnedShadow(); + return; + } + + if (mPinnedSection != null + && mPinnedSection.position != sectionPosition) { // invalidate shadow, if required + destroyPinnedShadow(); + } + + if (mPinnedSection == null) { // create shadow, if empty + createPinnedShadow(sectionPosition); + } + + // align shadow according to next section position, if needed + int nextPosition = sectionPosition + 1; + if (nextPosition < getCount()) { + int nextSectionPosition = findFirstVisibleSectionPosition(nextPosition, + visibleItemCount - (nextPosition - firstVisibleItem)); + if (nextSectionPosition> -1) {
+ View nextSectionView = getChildAt(nextSectionPosition - firstVisibleItem);
+ final int bottom = mPinnedSection.view.getBottom() + getPaddingTop();
+ mSectionsDistanceY = nextSectionView.getTop() - bottom;
+ if (mSectionsDistanceY < 0) { + // next section overlaps pinned shadow, move it up + mTranslateY = mSectionsDistanceY; + } else { + // next section does not overlap with pinned, stick to top + mTranslateY = 0; + } + } else { + // no other sections are visible, stick to top + mTranslateY = 0; + mSectionsDistanceY = Integer.MAX_VALUE; + } + } + + } + + int findFirstVisibleSectionPosition(int firstVisibleItem, int visibleItemCount) { + ListAdapter adapter = getAdapter(); + + int adapterDataCount = adapter.getCount(); + if (getLastVisiblePosition()>= adapterDataCount) return -1; // dataset has changed, no candidate
+
+ if (firstVisibleItem+visibleItemCount>= adapterDataCount){//added to prevent index Outofbound (in case)
+ visibleItemCount = adapterDataCount-firstVisibleItem;
+ }
+
+ for (int childIndex = 0; childIndex < visibleItemCount; childIndex++) { + int position = firstVisibleItem + childIndex; + int viewType = adapter.getItemViewType(position); + if (isItemViewTypePinned(adapter, viewType)) return position; + } + return -1; + } + + int findCurrentSectionPosition(int fromPosition) { + ListAdapter adapter = getAdapter(); + + if (fromPosition>= adapter.getCount()) return -1; // dataset has changed, no candidate
+
+ if (adapter instanceof SectionIndexer) {
+ // try fast way by asking section indexer
+ SectionIndexer indexer = (SectionIndexer) adapter;
+ int sectionPosition = indexer.getSectionForPosition(fromPosition);
+ int itemPosition = indexer.getPositionForSection(sectionPosition);
+ int typeView = adapter.getItemViewType(itemPosition);
+ if (isItemViewTypePinned(adapter, typeView)) {
+ return itemPosition;
+ } // else, no luck
+ }
+
+ // try slow way by looking through to the next section item above
+ for (int position=fromPosition; position>=0; position--) {
+ int viewType = adapter.getItemViewType(position);
+ if (isItemViewTypePinned(adapter, viewType)) return position;
+ }
+ return -1; // no candidate found
+ }
+
+ void recreatePinnedShadow() {
+ destroyPinnedShadow();
+ ListAdapter adapter = getAdapter();
+ if (adapter != null && adapter.getCount()> 0) {
+ int firstVisiblePosition = getFirstVisiblePosition();
+ int sectionPosition = findCurrentSectionPosition(firstVisiblePosition);
+ if (sectionPosition == -1) return; // no views to pin, exit
+ ensureShadowForPosition(sectionPosition,
+ firstVisiblePosition, getLastVisiblePosition() - firstVisiblePosition);
+ }
+ }
+
+ @Override
+ public void setOnScrollListener(OnScrollListener listener) {
+ if (listener == mOnScrollListener) {
+ super.setOnScrollListener(listener);
+ } else {
+ mDelegateOnScrollListener = listener;
+ }
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ super.onRestoreInstanceState(state);
+ post(new Runnable() {
+ @Override public void run() { // restore pinned view after configuration change
+ recreatePinnedShadow();
+ }
+ });
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+
+ // assert adapter in debug mode
+ if (BuildConfig.DEBUG && adapter != null) {
+ if (!(adapter instanceof PinnedSectionListAdapter))
+ throw new IllegalArgumentException("Does your adapter implement PinnedSectionListAdapter?");
+ if (adapter.getViewTypeCount() < 2) + throw new IllegalArgumentException("Does your adapter handle at least two types" + + " of views in getViewTypeCount() method: items and sections?"); + } + + // unregister observer at old adapter and register on new one + ListAdapter oldAdapter = getAdapter(); + if (oldAdapter != null) oldAdapter.unregisterDataSetObserver(mDataSetObserver); + if (adapter != null) adapter.registerDataSetObserver(mDataSetObserver); + + // destroy pinned shadow, if new adapter is not same as old one + if (oldAdapter != adapter) destroyPinnedShadow(); + + super.setAdapter(adapter); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (mPinnedSection != null) { + int parentWidth = r - l - getPaddingLeft() - getPaddingRight(); + int shadowWidth = mPinnedSection.view.getWidth(); + if (parentWidth != shadowWidth) { + recreatePinnedShadow(); + } + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + + if (mPinnedSection != null) { + + // prepare variables + int pLeft = getListPaddingLeft(); + int pTop = getListPaddingTop(); + View view = mPinnedSection.view; + + // draw child + canvas.save(); + + int clipHeight = view.getHeight() + + (mShadowDrawable == null ? 0 : Math.min(mShadowHeight, mSectionsDistanceY)); + canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight); + + canvas.translate(pLeft, pTop + mTranslateY); + drawChild(canvas, mPinnedSection.view, getDrawingTime()); + + if (mShadowDrawable != null && mSectionsDistanceY> 0) {
+ mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),
+ mPinnedSection.view.getBottom(),
+ mPinnedSection.view.getRight(),
+ mPinnedSection.view.getBottom() + mShadowHeight);
+ mShadowDrawable.draw(canvas);
+ }
+
+ canvas.restore();
+ }
+ }
+
+ //-- touch handling methods
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+
+ final float x = ev.getX();
+ final float y = ev.getY();
+ final int action = ev.getAction();
+
+ if (action == MotionEvent.ACTION_DOWN
+ && mTouchTarget == null
+ && mPinnedSection != null
+ && isPinnedViewTouched(mPinnedSection.view, x, y)) { // create touch target
+
+ // user touched pinned view
+ mTouchTarget = mPinnedSection.view;
+ mTouchPoint.x = x;
+ mTouchPoint.y = y;
+
+ // copy down event for eventually be used later
+ mDownEvent = MotionEvent.obtain(ev);
+ }
+
+ if (mTouchTarget != null) {
+ if (isPinnedViewTouched(mTouchTarget, x, y)) { // forward event to pinned view
+ mTouchTarget.dispatchTouchEvent(ev);
+ }
+
+ if (action == MotionEvent.ACTION_UP) { // perform onClick on pinned view
+ super.dispatchTouchEvent(ev);
+ performPinnedItemClick();
+ clearTouchTarget();
+
+ } else if (action == MotionEvent.ACTION_CANCEL) { // cancel
+ clearTouchTarget();
+
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ if (Math.abs(y - mTouchPoint.y)> mTouchSlop) {
+
+ // cancel sequence on touch target
+ MotionEvent event = MotionEvent.obtain(ev);
+ event.setAction(MotionEvent.ACTION_CANCEL);
+ mTouchTarget.dispatchTouchEvent(event);
+ event.recycle();
+
+ // provide correct sequence to super class for further handling
+ super.dispatchTouchEvent(mDownEvent);
+ super.dispatchTouchEvent(ev);
+ clearTouchTarget();
+
+ }
+ }
+
+ return true;
+ }
+
+ // call super if this was not our pinned view
+ return super.dispatchTouchEvent(ev);
+ }
+
+ private boolean isPinnedViewTouched(View view, float x, float y) {
+ view.getHitRect(mTouchRect);
+
+ // by taping top or bottom padding, the list performs on click on a border item.
+ // we don't add top padding here to keep behavior consistent.
+ mTouchRect.top += mTranslateY;
+
+ mTouchRect.bottom += mTranslateY + getPaddingTop();
+ mTouchRect.left += getPaddingLeft();
+ mTouchRect.right -= getPaddingRight();
+ return mTouchRect.contains((int)x, (int)y);
+ }
+
+ private void clearTouchTarget() {
+ mTouchTarget = null;
+ if (mDownEvent != null) {
+ mDownEvent.recycle();
+ mDownEvent = null;
+ }
+ }
+
+ private boolean performPinnedItemClick() {
+ if (mPinnedSection == null) return false;
+
+ OnItemClickListener listener = getOnItemClickListener();
+ if (listener != null && getAdapter().isEnabled(mPinnedSection.position)) {
+ View view = mPinnedSection.view;
+ playSoundEffect(SoundEffectConstants.CLICK);
+ if (view != null) {
+ view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+ }
+ listener.onItemClick(this, view, mPinnedSection.position, mPinnedSection.id);
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isItemViewTypePinned(ListAdapter adapter, int viewType) {
+ if (adapter instanceof HeaderViewListAdapter) {
+ adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
+ }
+ return ((PinnedSectionListAdapter) adapter).isItemViewTypePinned(viewType);
+ }
+
+}
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PositionBar.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PositionBar.java
new file mode 100644
index 0000000..6da966d
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/PositionBar.java
@@ -0,0 +1,106 @@
+package com.boredream.bdcodehelper.view;
+
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.boredream.bdcodehelper.R;
+
+@SuppressLint("ClickableViewAccessibility")
+public class PositionBar extends LinearLayout {
+
+ private String[] mItems = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
+ "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
+ "V", "W", "X", "Y", "Z" };
+
+ private OnPositionChangedListener listener;
+
+ public void setOnPositionChangedListener(OnPositionChangedListener listener) {
+ this.listener = listener;
+ }
+
+ public PositionBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setOrientation(VERTICAL);
+ setBackgroundResource(R.drawable.cirrect_5a_primary_solid);
+ }
+
+ public void setItems(String[] items) {
+ mItems = items;
+ for (CharSequence s : mItems) {
+ TextView t = new TextView(getContext());
+ t.setText(s);
+ t.setTextSize(10);
+ LayoutParams params = new LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, 0);
+ params.weight = 1;
+ t.setLayoutParams(params);
+ t.setTextColor(getResources().getColor(R.color.txt_black));
+ addView(t);
+ }
+ }
+
+ public String[] getItems() {
+ return mItems;
+ }
+
+ public PositionBar(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ final int action = ev.getAction();
+ TextView child = null;
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ setBackgroundResource(R.drawable.cirrect_10a_primary_solid);
+ child = findChildByLocation(ev.getX(), ev.getY());
+ if (listener != null) {
+ listener.onPositionSelected(child==null?"":child.getText().toString());
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ setBackgroundResource(R.drawable.cirrect_10a_primary_solid);
+ child = findChildByLocation(ev.getX(), ev.getY());
+ if (listener != null) {
+ listener.onPositionSelected(child==null?"":child.getText().toString());
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ setBackgroundResource(R.drawable.cirrect_5a_primary_solid);
+ if (listener != null) {
+ listener.onPositionSelected("");
+ }
+ break;
+ }
+
+ return true;
+ }
+
+ private TextView findChildByLocation(float x, float y) {
+ TextView child = null;
+ int mContentTop = getChildAt(0).getTop();
+ int mContentBottom = getChildAt(getChildCount() - 1).getBottom();
+ int defSize = (mContentBottom - mContentTop) / mItems.length;
+
+ int index = (int) ((y - mContentTop) / defSize);
+ if (index>= 0 && index < mItems.length + && x>= 0 && x <= getWidth()) { + child = (TextView) getChildAt(index); + } + return child; + } + + public interface OnPositionChangedListener { + void onPositionSelected(String key); + } + +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightGridView.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightGridView.java new file mode 100644 index 0000000..cdb39f7 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightGridView.java @@ -0,0 +1,29 @@ +package com.boredream.bdcodehelper.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +public class WrapHeightGridView extends GridView { + + public WrapHeightGridView(Context context) { + super(context); + } + + public WrapHeightGridView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WrapHeightGridView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int heightSpec = MeasureSpec.makeMeasureSpec( + Integer.MAX_VALUE>> 2, MeasureSpec.AT_MOST);
+
+ super.onMeasure(widthMeasureSpec, heightSpec);
+ }
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightLinearLayoutManager.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightLinearLayoutManager.java
new file mode 100644
index 0000000..e8e7f1e
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightLinearLayoutManager.java
@@ -0,0 +1,79 @@
+package com.boredream.bdcodehelper.view;
+
+import android.content.Context;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * 用作wrap_content的RecyclerView
+ */
+public class WrapHeightLinearLayoutManager extends LinearLayoutManager {
+
+ public WrapHeightLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
+ super(context, orientation, reverseLayout);
+ }
+
+ private int[] mMeasuredDimension = new int[2];
+
+ @Override
+ public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
+ int widthSpec, int heightSpec) {
+ final int widthMode = View.MeasureSpec.getMode(widthSpec);
+ final int heightMode = View.MeasureSpec.getMode(heightSpec);
+ final int widthSize = View.MeasureSpec.getSize(widthSpec);
+ final int heightSize = View.MeasureSpec.getSize(heightSpec);
+ int width = 0;
+ int height = 0;
+ for (int i = 0; i < getItemCount(); i++) { + measureScrapChild(recycler, i, + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + mMeasuredDimension); + + if (getOrientation() == HORIZONTAL) { + width = width + mMeasuredDimension[0]; + if (i == 0) { + height = mMeasuredDimension[1]; + } + } else { + height = height + mMeasuredDimension[1]; + if (i == 0) { + width = mMeasuredDimension[0]; + } + } + } + switch (widthMode) { + case View.MeasureSpec.EXACTLY: + width = widthSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + switch (heightMode) { + case View.MeasureSpec.EXACTLY: + height = heightSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + setMeasuredDimension(width, height); + } + + private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, + int heightSpec, int[] measuredDimension) { + View view = recycler.getViewForPosition(position); + if (view != null) { + RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, + getPaddingLeft() + getPaddingRight(), p.width); + int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, + getPaddingTop() + getPaddingBottom(), p.height); + view.measure(childWidthSpec, childHeightSpec); + measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; + measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; + recycler.recycleView(view); + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightListView.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightListView.java new file mode 100644 index 0000000..6f9457b --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/WrapHeightListView.java @@ -0,0 +1,29 @@ +package com.boredream.bdcodehelper.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ListView; + +public class WrapHeightListView extends ListView { + + public WrapHeightListView(Context context) { + super(context); + } + + public WrapHeightListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WrapHeightListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int heightSpec = MeasureSpec.makeMeasureSpec( + Integer.MAX_VALUE>> 2, MeasureSpec.AT_MOST);
+
+ super.onMeasure(widthMeasureSpec, heightSpec);
+ }
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/ItemsRange.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/ItemsRange.java
new file mode 100644
index 0000000..ac20fb2
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/ItemsRange.java
@@ -0,0 +1,81 @@
+/*
+ * Android Wheel Control.
+ * https://code.google.com/p/android-wheel/
+ *
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+/**
+ * Range for visible items.
+ */
+public class ItemsRange {
+ // First item number
+ private int first;
+
+ // Items count
+ private int count;
+
+ /**
+ * Default constructor. Creates an empty range
+ */
+ public ItemsRange() {
+ this(0, 0);
+ }
+
+ /**
+ * Constructor
+ * @param first the number of first item
+ * @param count the count of items
+ */
+ public ItemsRange(int first, int count) {
+ this.first = first;
+ this.count = count;
+ }
+
+ /**
+ * Gets number of first item
+ * @return the number of the first item
+ */
+ public int getFirst() {
+ return first;
+ }
+
+ /**
+ * Gets number of last item
+ * @return the number of last item
+ */
+ public int getLast() {
+ return getFirst() + getCount() - 1;
+ }
+
+ /**
+ * Get items count
+ * @return the count of items
+ */
+ public int getCount() {
+ return count;
+ }
+
+ /**
+ * Tests whether item is contained by range
+ * @param index the item number
+ * @return true if item is contained
+ */
+ public boolean contains(int index) {
+ return index>= getFirst() && index <= getLast(); + } +} \ No newline at end of file diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelChangedListener.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelChangedListener.java new file mode 100644 index 0000000..a9ee1ef --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelChangedListener.java @@ -0,0 +1,33 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel; + +/** + * Wheel changed listener interface. + *
The onChanged() method is called whenever current wheel positions is changed:
+ *
New Wheel position is set
+ *
Wheel view is scrolled
+ */
+public interface OnWheelChangedListener {
+ /**
+ * Callback method to be invoked when current item changed
+ * @param wheel the wheel view whose state has changed
+ * @param oldValue the old value of current item
+ * @param newValue the new value of current item
+ */
+ void onChanged(WheelView wheel, int oldValue, int newValue);
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelClickedListener.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelClickedListener.java
new file mode 100644
index 0000000..c3d24d9
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelClickedListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+/**
+ * Wheel clicked listener interface.
+ *
The onItemClicked() method is called whenever a wheel item is clicked
+ *
New Wheel position is set
+ *
Wheel view is scrolled
+ */
+public interface OnWheelClickedListener {
+ /**
+ * Callback method to be invoked when current item clicked
+ * @param wheel the wheel view
+ * @param itemIndex the index of clicked item
+ */
+ void onItemClicked(WheelView wheel, int itemIndex);
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelScrollListener.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelScrollListener.java
new file mode 100644
index 0000000..b491ebe
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/OnWheelScrollListener.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+/**
+ * Wheel scrolled listener interface.
+ */
+public interface OnWheelScrollListener {
+ /**
+ * Callback method to be invoked when scrolling started.
+ * @param wheel the wheel view whose state has changed.
+ */
+ void onScrollingStarted(WheelView wheel);
+
+ /**
+ * Callback method to be invoked when scrolling ended.
+ * @param wheel the wheel view whose state has changed.
+ */
+ void onScrollingFinished(WheelView wheel);
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelAdapter.java
new file mode 100644
index 0000000..7d3f6a6
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+/**
+ * Wheel adapter interface
+ *
+ * @deprecated Use WheelViewAdapter
+ */
+public interface WheelAdapter {
+ /**
+ * Gets items count
+ * @return the count of wheel items
+ */
+ public int getItemsCount();
+
+ /**
+ * Gets a wheel item by index.
+ *
+ * @param index the item index
+ * @return the wheel item text or null
+ */
+ public String getItem(int index);
+
+ /**
+ * Gets maximum item length. It is used to determine the wheel width.
+ * If -1 is returned there will be used the default wheel width.
+ *
+ * @return the maximum item length or -1
+ */
+ public int getMaximumLength();
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelRecycle.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelRecycle.java
new file mode 100644
index 0000000..9a5aa4b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelRecycle.java
@@ -0,0 +1,153 @@
+/*
+ * Android Wheel Control.
+ * https://code.google.com/p/android-wheel/
+ *
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+import android.view.View;
+import android.widget.LinearLayout;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Recycle stores wheel items to reuse.
+ */
+public class WheelRecycle {
+ // Cached items
+ private List items;
+
+ // Cached empty items
+ private List emptyItems;
+
+ // Wheel view
+ private WheelView wheel;
+
+ /**
+ * Constructor
+ * @param wheel the wheel view
+ */
+ public WheelRecycle(WheelView wheel) {
+ this.wheel = wheel;
+ }
+
+ /**
+ * Recycles items from specified layout.
+ * There are saved only items not included to specified range.
+ * All the cached items are removed from original layout.
+ *
+ * @param layout the layout containing items to be cached
+ * @param firstItem the number of first item in layout
+ * @param range the range of current wheel items
+ * @return the new value of first item number
+ */
+ public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) {
+ int index = firstItem;
+ for (int i = 0; i < layout.getChildCount();) { + if (!range.contains(index)) { + recycleView(layout.getChildAt(i), index); + layout.removeViewAt(i); + if (i == 0) { // first item + firstItem++; + } + } else { + i++; // go to next item + } + index++; + } + return firstItem; + } + + /** + * Gets item view + * @return the cached view + */ + public View getItem() { + return getCachedView(items); + } + + /** + * Gets empty item view + * @return the cached empty view + */ + public View getEmptyItem() { + return getCachedView(emptyItems); + } + + /** + * Clears all views + */ + public void clearAll() { + if (items != null) { + items.clear(); + } + if (emptyItems != null) { + emptyItems.clear(); + } + } + + /** + * Adds view to specified cache. Creates a cache list if it is null. + * @param view the view to be cached + * @param cache the cache list + * @return the cache list + */ + private List addView(View view, List cache) {
+ if (cache == null) {
+ cache = new LinkedList();
+ }
+
+ cache.add(view);
+ return cache;
+ }
+
+ /**
+ * Adds view to cache. Determines view type (item view or empty one) by index.
+ * @param view the view to be cached
+ * @param index the index of view
+ */
+ private void recycleView(View view, int index) {
+ int count = wheel.getViewAdapter().getItemsCount();
+
+ if ((index < 0 || index>= count) && !wheel.isCyclic()) {
+ // empty view
+ emptyItems = addView(view, emptyItems);
+ } else {
+ while (index < 0) { + index = count + index; + } + index %= count; + items = addView(view, items); + } + } + + /** + * Gets view from specified cache. + * @param cache the cache + * @return the first view from cache. + */ + private View getCachedView(List cache) {
+ if (cache != null && cache.size()> 0) {
+ View view = cache.get(0);
+ cache.remove(0);
+ return view;
+ }
+ return null;
+ }
+
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelScroller.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelScroller.java
new file mode 100644
index 0000000..fe42f8b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelScroller.java
@@ -0,0 +1,252 @@
+/*
+ * Android Wheel Control.
+ * https://code.google.com/p/android-wheel/
+ *
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.boredream.bdcodehelper.view.wheel;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+/**
+ * Scroller class handles scrolling events and updates the
+ */
+public class WheelScroller {
+ /**
+ * Scrolling listener interface
+ */
+ public interface ScrollingListener {
+ /**
+ * Scrolling callback called when scrolling is performed.
+ * @param distance the distance to scroll
+ */
+ void onScroll(int distance);
+
+ /**
+ * Starting callback called when scrolling is started
+ */
+ void onStarted();
+
+ /**
+ * Finishing callback called after justifying
+ */
+ void onFinished();
+
+ /**
+ * Justifying callback called to justify a view when scrolling is ended
+ */
+ void onJustify();
+ }
+
+ /** Scrolling duration */
+ private static final int SCROLLING_DURATION = 400;
+
+ /** Minimum delta for scrolling */
+ public static final int MIN_DELTA_FOR_SCROLLING = 1;
+
+ // Listener
+ private ScrollingListener listener;
+
+ // Context
+ private Context context;
+
+ // Scrolling
+ private GestureDetector gestureDetector;
+ private Scroller scroller;
+ private int lastScrollY;
+ private float lastTouchedY;
+ private boolean isScrollingPerformed;
+
+ /**
+ * Constructor
+ * @param context the current context
+ * @param listener the scrolling listener
+ */
+ public WheelScroller(Context context, ScrollingListener listener) {
+ gestureDetector = new GestureDetector(context, gestureListener);
+ gestureDetector.setIsLongpressEnabled(false);
+
+ scroller = new Scroller(context);
+
+ this.listener = listener;
+ this.context = context;
+ }
+
+ /**
+ * Set the the specified scrolling interpolator
+ * @param interpolator the interpolator
+ */
+ public void setInterpolator(Interpolator interpolator) {
+ scroller.forceFinished(true);
+ scroller = new Scroller(context, interpolator);
+ }
+
+ /**
+ * Scroll the wheel
+ * @param distance the scrolling distance
+ * @param time the scrolling duration
+ */
+ public void scroll(int distance, int time) {
+ scroller.forceFinished(true);
+
+ lastScrollY = 0;
+
+ scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION);
+ setNextMessage(MESSAGE_SCROLL);
+
+ startScrolling();
+ }
+
+ /**
+ * Stops scrolling
+ */
+ public void stopScrolling() {
+ scroller.forceFinished(true);
+ }
+
+ /**
+ * Handles Touch event
+ * @param event the motion event
+ * @return
+ */
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ lastTouchedY = event.getY();
+ scroller.forceFinished(true);
+ clearMessages();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ // perform scrolling
+ int distanceY = (int)(event.getY() - lastTouchedY);
+ if (distanceY != 0) {
+ startScrolling();
+ listener.onScroll(distanceY);
+ lastTouchedY = event.getY();
+ }
+ break;
+ }
+
+ if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
+ justify();
+ }
+
+ return true;
+ }
+
+ // gesture listener
+ private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ // Do scrolling in onTouchEvent() since onScroll() are not call immediately
+ // when user touch and move the wheel
+ return true;
+ }
+
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ lastScrollY = 0;
+ final int maxY = 0x7FFFFFFF;
+ final int minY = -maxY;
+ scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY);
+ setNextMessage(MESSAGE_SCROLL);
+ return true;
+ }
+ };
+
+ // Messages
+ private final int MESSAGE_SCROLL = 0;
+ private final int MESSAGE_JUSTIFY = 1;
+
+ /**
+ * Set next message to queue. Clears queue before.
+ *
+ * @param message the message to set
+ */
+ private void setNextMessage(int message) {
+ clearMessages();
+ animationHandler.sendEmptyMessage(message);
+ }
+
+ /**
+ * Clears messages from queue
+ */
+ private void clearMessages() {
+ animationHandler.removeMessages(MESSAGE_SCROLL);
+ animationHandler.removeMessages(MESSAGE_JUSTIFY);
+ }
+
+ // animation handler
+ private Handler animationHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ scroller.computeScrollOffset();
+ int currY = scroller.getCurrY();
+ int delta = lastScrollY - currY;
+ lastScrollY = currY;
+ if (delta != 0) {
+ listener.onScroll(delta);
+ }
+
+ // scrolling is not finished when it comes to final Y
+ // so, finish it manually
+ if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) { + currY = scroller.getFinalY(); + scroller.forceFinished(true); + } + if (!scroller.isFinished()) { + animationHandler.sendEmptyMessage(msg.what); + } else if (msg.what == MESSAGE_SCROLL) { + justify(); + } else { + finishScrolling(); + } + } + }; + + /** + * Justifies wheel + */ + private void justify() { + listener.onJustify(); + setNextMessage(MESSAGE_JUSTIFY); + } + + /** + * Starts scrolling + */ + private void startScrolling() { + if (!isScrollingPerformed) { + isScrollingPerformed = true; + listener.onStarted(); + } + } + + /** + * Finishes scrolling + */ + void finishScrolling() { + if (isScrollingPerformed) { + listener.onFinished(); + isScrollingPerformed = false; + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelView.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelView.java new file mode 100644 index 0000000..379c5f6 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/WheelView.java @@ -0,0 +1,957 @@ +/* + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.animation.Interpolator; +import android.widget.LinearLayout; + +import com.boredream.bdcodehelper.R; +import com.boredream.bdcodehelper.view.wheel.adapters.WheelViewAdapter; + +import java.util.LinkedList; +import java.util.List; + +/** + * Numeric wheel view. + * + * @author Yuri Kanivets + */ +public class WheelView extends View { + + /** Top and bottom shadows colors */ + /*/ Modified by wulianghuan 2014-11-25 + private int[] SHADOWS_COLORS = new int[] { 0xFF111111, + 0x00AAAAAA, 0x00AAAAAA }; + //*/ + private int[] SHADOWS_COLORS = new int[] { 0xefE9E9E9, + 0xcfE9E9E9, 0x3fE9E9E9 }; + + /** Top and bottom items offset (to hide that) */ + private static final int ITEM_OFFSET_PERCENT = 0; + + /** Left and right padding value */ + private static final int PADDING = 10; + + /** Default count of visible items */ + private static final int DEF_VISIBLE_ITEMS = 5; + + // Wheel Values + private int currentItem = 0; + + // Count of visible items + private int visibleItems = DEF_VISIBLE_ITEMS; + + // Item height + private int itemHeight = 0; + + // Center Line + private Drawable centerDrawable; + + // Wheel drawables + private int wheelBackground = R.drawable.wheel_bg; + private int wheelForeground = R.drawable.wheel_val; + + // Shadows drawables + private GradientDrawable topShadow; + private GradientDrawable bottomShadow; + + // Draw Shadows + private boolean drawShadows = true; + + // Scrolling + private WheelScroller scroller; + private boolean isScrollingPerformed; + private int scrollingOffset; + + // Cyclic + boolean isCyclic = false; + + // Items layout + private LinearLayout itemsLayout; + + // The number of first item in layout + private int firstItem; + + // View adapter + private WheelViewAdapter viewAdapter; + + // Recycle + private WheelRecycle recycle = new WheelRecycle(this); + + // Listeners + private List changingListeners = new LinkedList();
+ private List scrollingListeners = new LinkedList();
+ private List clickingListeners = new LinkedList();
+
+ /**
+ * Constructor
+ */
+ public WheelView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initData(context);
+ }
+
+ /**
+ * Constructor
+ */
+ public WheelView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initData(context);
+ }
+
+ /**
+ * Constructor
+ */
+ public WheelView(Context context) {
+ super(context);
+ initData(context);
+ }
+
+ /**
+ * Initializes class data
+ * @param context the context
+ */
+ private void initData(Context context) {
+ scroller = new WheelScroller(getContext(), scrollingListener);
+ }
+
+ // Scrolling listener
+ WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() {
+ @Override
+ public void onStarted() {
+ isScrollingPerformed = true;
+ notifyScrollingListenersAboutStart();
+ }
+
+ @Override
+ public void onScroll(int distance) {
+ doScroll(distance);
+
+ int height = getHeight();
+ if (scrollingOffset> height) {
+ scrollingOffset = height;
+ scroller.stopScrolling();
+ } else if (scrollingOffset < -height) { + scrollingOffset = -height; + scroller.stopScrolling(); + } + } + + @Override + public void onFinished() { + if (isScrollingPerformed) { + notifyScrollingListenersAboutEnd(); + isScrollingPerformed = false; + } + + scrollingOffset = 0; + invalidate(); + } + + @Override + public void onJustify() { + if (Math.abs(scrollingOffset)> WheelScroller.MIN_DELTA_FOR_SCROLLING) {
+ scroller.scroll(scrollingOffset, 0);
+ }
+ }
+ };
+
+ /**
+ * Set the the specified scrolling interpolator
+ * @param interpolator the interpolator
+ */
+ public void setInterpolator(Interpolator interpolator) {
+ scroller.setInterpolator(interpolator);
+ }
+
+ /**
+ * Gets count of visible items
+ *
+ * @return the count of visible items
+ */
+ public int getVisibleItems() {
+ return visibleItems;
+ }
+
+ /**
+ * Sets the desired count of visible items.
+ * Actual amount of visible items depends on wheel layout parameters.
+ * To apply changes and rebuild view call measure().
+ *
+ * @param count the desired count for visible items
+ */
+ public void setVisibleItems(int count) {
+ visibleItems = count;
+ }
+
+ /**
+ * Gets view adapter
+ * @return the view adapter
+ */
+ public WheelViewAdapter getViewAdapter() {
+ return viewAdapter;
+ }
+
+ // Adapter listener
+ private DataSetObserver dataObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ invalidateWheel(false);
+ }
+
+ @Override
+ public void onInvalidated() {
+ invalidateWheel(true);
+ }
+ };
+
+ /**
+ * Sets view adapter. Usually new adapters contain different views, so
+ * it needs to rebuild view by calling measure().
+ *
+ * @param viewAdapter the view adapter
+ */
+ public void setViewAdapter(WheelViewAdapter viewAdapter) {
+ if (this.viewAdapter != null) {
+ this.viewAdapter.unregisterDataSetObserver(dataObserver);
+ }
+ this.viewAdapter = viewAdapter;
+ if (this.viewAdapter != null) {
+ this.viewAdapter.registerDataSetObserver(dataObserver);
+ }
+
+ invalidateWheel(true);
+ }
+
+ /**
+ * Adds wheel changing listener
+ * @param listener the listener
+ */
+ public void addChangingListener(OnWheelChangedListener listener) {
+ changingListeners.add(listener);
+ }
+
+ /**
+ * Removes wheel changing listener
+ * @param listener the listener
+ */
+ public void removeChangingListener(OnWheelChangedListener listener) {
+ changingListeners.remove(listener);
+ }
+
+ /**
+ * Notifies changing listeners
+ * @param oldValue the old wheel value
+ * @param newValue the new wheel value
+ */
+ protected void notifyChangingListeners(int oldValue, int newValue) {
+ for (OnWheelChangedListener listener : changingListeners) {
+ listener.onChanged(this, oldValue, newValue);
+ }
+ }
+
+ /**
+ * Adds wheel scrolling listener
+ * @param listener the listener
+ */
+ public void addScrollingListener(OnWheelScrollListener listener) {
+ scrollingListeners.add(listener);
+ }
+
+ /**
+ * Removes wheel scrolling listener
+ * @param listener the listener
+ */
+ public void removeScrollingListener(OnWheelScrollListener listener) {
+ scrollingListeners.remove(listener);
+ }
+
+ /**
+ * Notifies listeners about starting scrolling
+ */
+ protected void notifyScrollingListenersAboutStart() {
+ for (OnWheelScrollListener listener : scrollingListeners) {
+ listener.onScrollingStarted(this);
+ }
+ }
+
+ /**
+ * Notifies listeners about ending scrolling
+ */
+ protected void notifyScrollingListenersAboutEnd() {
+ for (OnWheelScrollListener listener : scrollingListeners) {
+ listener.onScrollingFinished(this);
+ }
+ }
+
+ /**
+ * Adds wheel clicking listener
+ * @param listener the listener
+ */
+ public void addClickingListener(OnWheelClickedListener listener) {
+ clickingListeners.add(listener);
+ }
+
+ /**
+ * Removes wheel clicking listener
+ * @param listener the listener
+ */
+ public void removeClickingListener(OnWheelClickedListener listener) {
+ clickingListeners.remove(listener);
+ }
+
+ /**
+ * Notifies listeners about clicking
+ */
+ protected void notifyClickListenersAboutClick(int item) {
+ for (OnWheelClickedListener listener : clickingListeners) {
+ listener.onItemClicked(this, item);
+ }
+ }
+
+ /**
+ * Gets current value
+ *
+ * @return the current value
+ */
+ public int getCurrentItem() {
+ return currentItem;
+ }
+
+ /**
+ * Sets the current item. Does nothing when index is wrong.
+ *
+ * @param index the item index
+ * @param animated the animation flag
+ */
+ public void setCurrentItem(int index, boolean animated) {
+ if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
+ return; // throw?
+ }
+
+ int itemCount = viewAdapter.getItemsCount();
+ if (index < 0 || index>= itemCount) {
+ if (isCyclic) {
+ while (index < 0) { + index += itemCount; + } + index %= itemCount; + } else{ + return; // throw? + } + } + if (index != currentItem) { + if (animated) { + int itemsToScroll = index - currentItem; + if (isCyclic) { + int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem); + if (scroll < Math.abs(itemsToScroll)) { + itemsToScroll = itemsToScroll < 0 ? scroll : -scroll; + } + } + scroll(itemsToScroll, 0); + } else { + scrollingOffset = 0; + + int old = currentItem; + currentItem = index; + + notifyChangingListeners(old, currentItem); + + invalidate(); + } + } + } + + /** + * Sets the current item w/o animation. Does nothing when index is wrong. + * + * @param index the item index + */ + public void setCurrentItem(int index) { + setCurrentItem(index, false); + } + + /** + * Tests if wheel is cyclic. That means before the 1st item there is shown the last one + * @return true if wheel is cyclic + */ + public boolean isCyclic() { + return isCyclic; + } + + /** + * Set wheel cyclic flag + * @param isCyclic the flag to set + */ + public void setCyclic(boolean isCyclic) { + this.isCyclic = isCyclic; + invalidateWheel(false); + } + + /** + * Determine whether shadows are drawn + * @return true is shadows are drawn + */ + public boolean drawShadows() { + return drawShadows; + } + + /** + * Set whether shadows should be drawn + * @param drawShadows flag as true or false + */ + public void setDrawShadows(boolean drawShadows) { + this.drawShadows = drawShadows; + } + + /** + * Set the shadow gradient color + * @param start + * @param middle + * @param end + */ + public void setShadowColor(int start, int middle, int end) { + SHADOWS_COLORS = new int[] {start, middle, end}; + } + + /** + * Sets the drawable for the wheel background + * @param resource + */ + public void setWheelBackground(int resource) { + wheelBackground = resource; + setBackgroundResource(wheelBackground); + } + + /** + * Sets the drawable for the wheel foreground + * @param resource + */ + public void setWheelForeground(int resource) { + wheelForeground = resource; + centerDrawable = getContext().getResources().getDrawable(wheelForeground); + } + + /** + * Invalidates wheel + * @param clearCaches if true then cached views will be clear + */ + public void invalidateWheel(boolean clearCaches) { + if (clearCaches) { + recycle.clearAll(); + if (itemsLayout != null) { + itemsLayout.removeAllViews(); + } + scrollingOffset = 0; + } else if (itemsLayout != null) { + // cache all items + recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); + } + + invalidate(); + } + + /** + * Initializes resources + */ + private void initResourcesIfNecessary() { + if (centerDrawable == null) { + centerDrawable = getContext().getResources().getDrawable(wheelForeground); + } + + if (topShadow == null) { + topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS); + } + + if (bottomShadow == null) { + bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS); + } + + setBackgroundResource(wheelBackground); + } + + /** + * Calculates desired height for layout + * + * @param layout + * the source layout + * @return the desired layout height + */ + private int getDesiredHeight(LinearLayout layout) { + if (layout != null && layout.getChildAt(0) != null) { + itemHeight = layout.getChildAt(0).getMeasuredHeight(); + } + + int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50; + + return Math.max(desired, getSuggestedMinimumHeight()); + } + + /** + * Returns height of wheel item + * @return the item height + */ + private int getItemHeight() { + if (itemHeight != 0) { + return itemHeight; + } + + if (itemsLayout != null && itemsLayout.getChildAt(0) != null) { + itemHeight = itemsLayout.getChildAt(0).getHeight(); + return itemHeight; + } + + return getHeight() / visibleItems; + } + + /** + * Calculates control width and creates text layouts + * @param widthSize the input layout width + * @param mode the layout mode + * @return the calculated control width + */ + private int calculateLayoutWidth(int widthSize, int mode) { + initResourcesIfNecessary(); + + // TODO: make it static + itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int width = itemsLayout.getMeasuredWidth(); + + if (mode == MeasureSpec.EXACTLY) { + width = widthSize; + } else { + width += 2 * PADDING; + + // Check against our minimum width + width = Math.max(width, getSuggestedMinimumWidth()); + + if (mode == MeasureSpec.AT_MOST && widthSize < width) { + width = widthSize; + } + } + + itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + + return width; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + buildViewForMeasuring(); + + int width = calculateLayoutWidth(widthSize, widthMode); + + int height; + if (heightMode == MeasureSpec.EXACTLY) { + height = heightSize; + } else { + height = getDesiredHeight(itemsLayout); + + if (heightMode == MeasureSpec.AT_MOST) { + height = Math.min(height, heightSize); + } + } + + setMeasuredDimension(width, height); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + layout(r - l, b - t); + } + + /** + * Sets layouts width and height + * @param width the layout width + * @param height the layout height + */ + private void layout(int width, int height) { + int itemsWidth = width - 2 * PADDING; + + itemsLayout.layout(0, 0, itemsWidth, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (viewAdapter != null && viewAdapter.getItemsCount()> 0) {
+ updateView();
+
+ drawItems(canvas);
+ drawCenterRect(canvas);
+ }
+
+ if (drawShadows) drawShadows(canvas);
+ }
+
+ /**
+ * Draws shadows on top and bottom of control
+ * @param canvas the canvas for drawing
+ */
+ private void drawShadows(Canvas canvas) {
+ /*/ Modified by wulianghuan 2014年11月25日
+ int height = (int)(1.5 * getItemHeight());
+ //*/
+ int height = (int)(3 * getItemHeight());
+ //*/
+ topShadow.setBounds(0, 0, getWidth(), height);
+ topShadow.draw(canvas);
+
+ bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
+ bottomShadow.draw(canvas);
+ }
+
+ /**
+ * Draws items
+ * @param canvas the canvas for drawing
+ */
+ private void drawItems(Canvas canvas) {
+ canvas.save();
+
+ int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2;
+ canvas.translate(PADDING, - top + scrollingOffset);
+
+ itemsLayout.draw(canvas);
+
+ canvas.restore();
+ }
+
+ /**
+ * Draws rect for current value
+ * @param canvas the canvas for drawing
+ */
+ private void drawCenterRect(Canvas canvas) {
+ int center = getHeight() / 2;
+ int offset = (int) (getItemHeight() / 2 * 1.2);
+ /*/ Remarked by wulianghuan 2014年11月27日 使用自己的画线,而不是描边
+ Rect rect = new Rect(left, top, right, bottom)
+ centerDrawable.setBounds(bounds)
+ centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
+ centerDrawable.draw(canvas);
+ //*/
+ Paint paint = new Paint();
+ paint.setColor(getResources().getColor(R.color.province_line_border));
+ // 设置线宽
+ paint.setStrokeWidth((float) 3);
+ // 绘制上边直线
+ canvas.drawLine(0, center - offset, getWidth(), center - offset, paint);
+ // 绘制下边直线
+ canvas.drawLine(0, center + offset, getWidth(), center + offset, paint);
+ //*/
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!isEnabled() || getViewAdapter() == null) {
+ return true;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ if (getParent() != null) {
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ if (!isScrollingPerformed) {
+ int distance = (int) event.getY() - getHeight() / 2;
+ if (distance> 0) {
+ distance += getItemHeight() / 2;
+ } else {
+ distance -= getItemHeight() / 2;
+ }
+ int items = distance / getItemHeight();
+ if (items != 0 && isValidItemIndex(currentItem + items)) {
+ notifyClickListenersAboutClick(currentItem + items);
+ }
+ }
+ break;
+ }
+
+ return scroller.onTouchEvent(event);
+ }
+
+ /**
+ * Scrolls the wheel
+ * @param delta the scrolling value
+ */
+ private void doScroll(int delta) {
+ scrollingOffset += delta;
+
+ int itemHeight = getItemHeight();
+ int count = scrollingOffset / itemHeight;
+
+ int pos = currentItem - count;
+ int itemCount = viewAdapter.getItemsCount();
+
+ int fixPos = scrollingOffset % itemHeight;
+ if (Math.abs(fixPos) <= itemHeight / 2) { + fixPos = 0; + } + if (isCyclic && itemCount> 0) {
+ if (fixPos> 0) {
+ pos--;
+ count++;
+ } else if (fixPos < 0) { + pos++; + count--; + } + // fix position by rotating + while (pos < 0) { + pos += itemCount; + } + pos %= itemCount; + } else { + // + if (pos < 0) { + count = currentItem; + pos = 0; + } else if (pos>= itemCount) {
+ count = currentItem - itemCount + 1;
+ pos = itemCount - 1;
+ } else if (pos> 0 && fixPos> 0) {
+ pos--;
+ count++;
+ } else if (pos < itemCount - 1 && fixPos < 0) { + pos++; + count--; + } + } + + int offset = scrollingOffset; + if (pos != currentItem) { + setCurrentItem(pos, false); + } else { + invalidate(); + } + + // update offset + scrollingOffset = offset - count * itemHeight; + if (scrollingOffset> getHeight()) {
+ scrollingOffset = scrollingOffset % getHeight() + getHeight();
+ }
+ }
+
+ /**
+ * Scroll the wheel
+ * @param itemsToScroll items to scroll
+ * @param time scrolling duration
+ */
+ public void scroll(int itemsToScroll, int time) {
+ int distance = itemsToScroll * getItemHeight() - scrollingOffset;
+ scroller.scroll(distance, time);
+ }
+
+ /**
+ * Calculates range for wheel items
+ * @return the items range
+ */
+ private ItemsRange getItemsRange() {
+ if (getItemHeight() == 0) {
+ return null;
+ }
+
+ int first = currentItem;
+ int count = 1;
+
+ while (count * getItemHeight() < getHeight()) { + first--; + count += 2; // top + bottom items + } + + if (scrollingOffset != 0) { + if (scrollingOffset> 0) {
+ first--;
+ }
+ count++;
+
+ // process empty items above the first or below the second
+ int emptyItems = scrollingOffset / getItemHeight();
+ first -= emptyItems;
+ count += Math.asin(emptyItems);
+ }
+ return new ItemsRange(first, count);
+ }
+
+ /**
+ * Rebuilds wheel items if necessary. Caches all unused items.
+ *
+ * @return true if items are rebuilt
+ */
+ private boolean rebuildItems() {
+ boolean updated = false;
+ ItemsRange range = getItemsRange();
+ if (itemsLayout != null) {
+ int first = recycle.recycleItems(itemsLayout, firstItem, range);
+ updated = firstItem != first;
+ firstItem = first;
+ } else {
+ createItemsLayout();
+ updated = true;
+ }
+
+ if (!updated) {
+ updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount();
+ }
+
+ if (firstItem> range.getFirst() && firstItem <= range.getLast()) { + for (int i = firstItem - 1; i>= range.getFirst(); i--) {
+ if (!addViewItem(i, true)) {
+ break;
+ }
+ firstItem = i;
+ }
+ } else {
+ firstItem = range.getFirst();
+ }
+
+ int first = firstItem;
+ for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) { + if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) { + first++; + } + } + firstItem = first; + + return updated; + } + + /** + * Updates view. Rebuilds items and label if necessary, recalculate items sizes. + */ + private void updateView() { + if (rebuildItems()) { + calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY); + layout(getWidth(), getHeight()); + } + } + + /** + * Creates item layouts if necessary + */ + private void createItemsLayout() { + if (itemsLayout == null) { + itemsLayout = new LinearLayout(getContext()); + itemsLayout.setOrientation(LinearLayout.VERTICAL); + } + } + + /** + * Builds view for measuring + */ + private void buildViewForMeasuring() { + // clear all items + if (itemsLayout != null) { + recycle.recycleItems(itemsLayout, firstItem, new ItemsRange()); + } else { + createItemsLayout(); + } + + // add views + int addItems = visibleItems / 2; + for (int i = currentItem + addItems; i>= currentItem - addItems; i--) {
+ if (addViewItem(i, true)) {
+ firstItem = i;
+ }
+ }
+ }
+
+ /**
+ * Adds view for item to items layout
+ * @param index the item index
+ * @param first the flag indicates if view should be first
+ * @return true if corresponding item exists and is added
+ */
+ private boolean addViewItem(int index, boolean first) {
+ View view = getItemView(index);
+ if (view != null) {
+ if (first) {
+ itemsLayout.addView(view, 0);
+ } else {
+ itemsLayout.addView(view);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether intem index is valid
+ * @param index the item index
+ * @return true if item index is not out of bounds or the wheel is cyclic
+ */
+ private boolean isValidItemIndex(int index) {
+ return viewAdapter != null && viewAdapter.getItemsCount()> 0 &&
+ (isCyclic || index>= 0 && index < viewAdapter.getItemsCount()); + } + + /** + * Returns view for specified item + * @param index the item index + * @return item view or empty view if index is out of bounds + */ + private View getItemView(int index) { + if (viewAdapter == null || viewAdapter.getItemsCount() == 0) { + return null; + } + int count = viewAdapter.getItemsCount(); + if (!isValidItemIndex(index)) { + return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout); + } else { + while (index < 0) { + index = count + index; + } + } + + index %= count; + return viewAdapter.getItem(index, recycle.getItem(), itemsLayout); + } + + /** + * Stops scrolling + */ + public void stopScrolling() { + scroller.stopScrolling(); + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelAdapter.java new file mode 100644 index 0000000..7692a02 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelAdapter.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract Wheel adapter. + */ +public abstract class AbstractWheelAdapter implements WheelViewAdapter { + // Observers + private List datasetObservers;
+
+ @Override
+ public View getEmptyItem(View convertView, ViewGroup parent) {
+ return null;
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ if (datasetObservers == null) {
+ datasetObservers = new LinkedList();
+ }
+ datasetObservers.add(observer);
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ if (datasetObservers != null) {
+ datasetObservers.remove(observer);
+ }
+ }
+
+ /**
+ * Notifies observers about data changing
+ */
+ protected void notifyDataChangedEvent() {
+ if (datasetObservers != null) {
+ for (DataSetObserver observer : datasetObservers) {
+ observer.onChanged();
+ }
+ }
+ }
+
+ /**
+ * Notifies observers about invalidating data
+ */
+ protected void notifyDataInvalidatedEvent() {
+ if (datasetObservers != null) {
+ for (DataSetObserver observer : datasetObservers) {
+ observer.onInvalidated();
+ }
+ }
+ }
+}
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelTextAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelTextAdapter.java
new file mode 100644
index 0000000..8bf3003
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AbstractWheelTextAdapter.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.boredream.bdcodehelper.view.wheel.adapters;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Abstract wheel adapter provides common functionality for adapters.
+ */
+public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter {
+
+ /** Text view resource. Used as a default view for adapter. */
+ public static final int TEXT_VIEW_ITEM_RESOURCE = -1;
+
+ /** No resource constant. */
+ protected static final int NO_RESOURCE = 0;
+
+ /** Default text color */
+ public static final int DEFAULT_TEXT_COLOR = 0xFF585858;
+
+ /** Default text color */
+ public static final int LABEL_COLOR = 0xFF700070;
+
+ /** Default text size */
+ public static final int DEFAULT_TEXT_SIZE = 18;
+
+ // Text settings
+ private int textColor = DEFAULT_TEXT_COLOR;
+ private int textSize = DEFAULT_TEXT_SIZE;
+
+ // Current context
+ protected Context context;
+ // Layout inflater
+ protected LayoutInflater inflater;
+
+ // Items resources
+ protected int itemResourceId;
+ protected int itemTextResourceId;
+
+ // Empty items resources
+ protected int emptyItemResourceId;
+
+ /**
+ * Constructor
+ * @param context the current context
+ */
+ protected AbstractWheelTextAdapter(Context context) {
+ this(context, TEXT_VIEW_ITEM_RESOURCE);
+ }
+
+ /**
+ * Constructor
+ * @param context the current context
+ * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
+ */
+ protected AbstractWheelTextAdapter(Context context, int itemResource) {
+ this(context, itemResource, NO_RESOURCE);
+ }
+
+ /**
+ * Constructor
+ * @param context the current context
+ * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
+ * @param itemTextResource the resource ID for a text view in the item layout
+ */
+ protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) {
+ this.context = context;
+ itemResourceId = itemResource;
+ itemTextResourceId = itemTextResource;
+
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ * Gets text color
+ * @return the text color
+ */
+ public int getTextColor() {
+ return textColor;
+ }
+
+ /**
+ * Sets text color
+ * @param textColor the text color to set
+ */
+ public void setTextColor(int textColor) {
+ this.textColor = textColor;
+ }
+
+ /**
+ * Gets text size
+ * @return the text size
+ */
+ public int getTextSize() {
+ return textSize;
+ }
+
+ /**
+ * Sets text size
+ * @param textSize the text size to set
+ */
+ public void setTextSize(int textSize) {
+ this.textSize = textSize;
+ }
+
+ /**
+ * Gets resource Id for items views
+ * @return the item resource Id
+ */
+ public int getItemResource() {
+ return itemResourceId;
+ }
+
+ /**
+ * Sets resource Id for items views
+ * @param itemResourceId the resource Id to set
+ */
+ public void setItemResource(int itemResourceId) {
+ this.itemResourceId = itemResourceId;
+ }
+
+ /**
+ * Gets resource Id for text view in item layout
+ * @return the item text resource Id
+ */
+ public int getItemTextResource() {
+ return itemTextResourceId;
+ }
+
+ /**
+ * Sets resource Id for text view in item layout
+ * @param itemTextResourceId the item text resource Id to set
+ */
+ public void setItemTextResource(int itemTextResourceId) {
+ this.itemTextResourceId = itemTextResourceId;
+ }
+
+ /**
+ * Gets resource Id for empty items views
+ * @return the empty item resource Id
+ */
+ public int getEmptyItemResource() {
+ return emptyItemResourceId;
+ }
+
+ /**
+ * Sets resource Id for empty items views
+ * @param emptyItemResourceId the empty item resource Id to set
+ */
+ public void setEmptyItemResource(int emptyItemResourceId) {
+ this.emptyItemResourceId = emptyItemResourceId;
+ }
+
+
+ /**
+ * Returns text for specified item
+ * @param index the item index
+ * @return the text of specified items
+ */
+ protected abstract CharSequence getItemText(int index);
+
+ @Override
+ public View getItem(int index, View convertView, ViewGroup parent) {
+ if (index>= 0 && index < getItemsCount()) { + if (convertView == null) { + convertView = getView(itemResourceId, parent); + } + TextView textView = getTextView(convertView, itemTextResourceId); + if (textView != null) { + CharSequence text = getItemText(index); + if (text == null) { + text = ""; + } + textView.setText(text); + + if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { + configureTextView(textView); + } + } + return convertView; + } + return null; + } + + @Override + public View getEmptyItem(View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = getView(emptyItemResourceId, parent); + } + if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) { + configureTextView((TextView)convertView); + } + + return convertView; + } + + /** + * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. + * @param view the text view to be configured + */ + protected void configureTextView(TextView view) { + view.setTextColor(textColor); + view.setGravity(Gravity.CENTER); + view.setTextSize(textSize); + view.setEllipsize(TextUtils.TruncateAt.END); + view.setLines(1); +// view.setCompoundDrawablePadding(20); +// view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); + } + + /** + * Loads a text view from view + * @param view the text view or layout containing it + * @param textResource the text resource Id in layout + * @return the loaded text view + */ + private TextView getTextView(View view, int textResource) { + TextView text = null; + try { + if (textResource == NO_RESOURCE && view instanceof TextView) { + text = (TextView) view; + } else if (textResource != NO_RESOURCE) { + text = (TextView) view.findViewById(textResource); + } + } catch (ClassCastException e) { + Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); + throw new IllegalStateException( + "AbstractWheelAdapter requires the resource ID to be a TextView", e); + } + + return text; + } + + /** + * Loads view from resources + * @param resource the resource Id + * @return the loaded view or null if resource is not set + */ + private View getView(int resource, ViewGroup parent) { + switch (resource) { + case NO_RESOURCE: + return null; + case TEXT_VIEW_ITEM_RESOURCE: + return new TextView(context); + default: + return inflater.inflate(resource, parent, false); + } + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AdapterWheel.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AdapterWheel.java new file mode 100644 index 0000000..862c061 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/AdapterWheel.java @@ -0,0 +1,63 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel.adapters; + + +import android.content.Context; + +import com.boredream.bdcodehelper.view.wheel.WheelAdapter; + +/** + * Adapter class for old wheel adapter (deprecated WheelAdapter class). + * + * @deprecated Will be removed soon + */ +public class AdapterWheel extends AbstractWheelTextAdapter { + + // Source adapter + private WheelAdapter adapter; + + /** + * Constructor + * @param context the current context + * @param adapter the source adapter + */ + public AdapterWheel(Context context, WheelAdapter adapter) { + super(context); + + this.adapter = adapter; + } + + /** + * Gets original adapter + * @return the original adapter + */ + public WheelAdapter getAdapter() { + return adapter; + } + + @Override + public int getItemsCount() { + return adapter.getItemsCount(); + } + + @Override + protected CharSequence getItemText(int index) { + return adapter.getItem(index); + } + +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/ArrayWheelAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/ArrayWheelAdapter.java new file mode 100644 index 0000000..60c4aba --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/ArrayWheelAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.boredream.bdcodehelper.view.wheel.adapters; + +import android.content.Context; + +import com.boredream.bdcodehelper.entity.city.BaseAddressModel; + +import java.util.ArrayList; + +/** + * The simple Array wheel adapter + * + * @param the element type
+ */
+public class ArrayWheelAdapter extends AbstractWheelTextAdapter {
+
+ // items
+ private ArrayList items;
+
+ /**
+ * Constructor
+ *
+ * @param context the current context
+ * @param items the items
+ */
+ public ArrayWheelAdapter(Context context, ArrayList items) {
+ super(context);
+
+ //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE);
+ this.items = items;
+ }
+
+ @Override
+ public CharSequence getItemText(int index) {
+ if (index>= 0 && index < items.size()) { + T item = items.get(index); + if (item instanceof BaseAddressModel) { + return ((BaseAddressModel) item).name; + } else if(item instanceof String) { + return item.toString(); + } + } + return null; + } + + @Override + public int getItemsCount() { + return items.size(); + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/NumericWheelAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/NumericWheelAdapter.java new file mode 100644 index 0000000..b5abeb3 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/NumericWheelAdapter.java @@ -0,0 +1,85 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel.adapters; + +import android.content.Context; + +/** + * Numeric Wheel adapter. + */ +public class NumericWheelAdapter extends AbstractWheelTextAdapter { + + /** The default min value */ + public static final int DEFAULT_MAX_VALUE = 9; + + /** The default max value */ + private static final int DEFAULT_MIN_VALUE = 0; + + // Values + private int minValue; + private int maxValue; + + // format + private String format; + + /** + * Constructor + * @param context the current context + */ + public NumericWheelAdapter(Context context) { + this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); + } + + /** + * Constructor + * @param context the current context + * @param minValue the wheel min value + * @param maxValue the wheel max value + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue) { + this(context, minValue, maxValue, null); + } + + /** + * Constructor + * @param context the current context + * @param minValue the wheel min value + * @param maxValue the wheel max value + * @param format the format string + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) { + super(context); + + this.minValue = minValue; + this.maxValue = maxValue; + this.format = format; + } + + @Override + public CharSequence getItemText(int index) { + if (index>= 0 && index < getItemsCount()) { + int value = minValue + index; + return format != null ? String.format(format, value) : Integer.toString(value); + } + return null; + } + + @Override + public int getItemsCount() { + return maxValue - minValue + 1; + } +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/WheelViewAdapter.java b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/WheelViewAdapter.java new file mode 100644 index 0000000..25c4d52 --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/java/com/boredream/bdcodehelper/view/wheel/adapters/WheelViewAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.boredream.bdcodehelper.view.wheel.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +/** + * Wheel items adapter interface + */ +public interface WheelViewAdapter { + /** + * Gets items count + * @return the count of wheel items + */ + public int getItemsCount(); + + /** + * Get a View that displays the data at the specified position in the data set + * + * @param index the item index + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the wheel item View + */ + public View getItem(int index, View convertView, ViewGroup parent); + + /** + * Get a View that displays an empty wheel item placed before the first or after + * the last wheel item. + * + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the empty item View + */ + public View getEmptyItem(View convertView, ViewGroup parent); + + /** + * Register an observer that is called when changes happen to the data used by this adapter. + * @param observer the observer to be registered + */ + public void registerDataSetObserver(DataSetObserver observer); + + /** + * Unregister an observer that has previously been registered + * @param observer the observer to be unregistered + */ + void unregisterDataSetObserver(DataSetObserver observer); +} diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/libs/nineoldandroids-2.2.0.jar b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/libs/nineoldandroids-2.2.0.jar new file mode 100644 index 0000000..3fad2ea Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/libs/nineoldandroids-2.2.0.jar differ diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_in.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_in.xml new file mode 100644 index 0000000..9b1b02d --- /dev/null +++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_in.xml @@ -0,0 +1,8 @@ +
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_out.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_out.xml
new file mode 100644
index 0000000..4512c46
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_mask_out.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_in.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_in.xml
new file mode 100644
index 0000000..c3b3599
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_in.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_out.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_out.xml
new file mode 100644
index 0000000..008ede2
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/anim/dd_menu_out.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_blue2gray_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_blue2gray_sel.xml
new file mode 100644
index 0000000..41948c6
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_blue2gray_sel.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_gray2primarydark_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_gray2primarydark_sel.xml
new file mode 100644
index 0000000..4f3273e
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_gray2primarydark_sel.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_lgray2white_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_lgray2white_sel.xml
new file mode 100644
index 0000000..554c85f
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_lgray2white_sel.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_primary2white_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_primary2white_sel.xml
new file mode 100644
index 0000000..272b49e
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_primary2white_sel.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_white2gray_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_white2gray_sel.xml
new file mode 100644
index 0000000..4c9815b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/color/txt_white2gray_sel.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_gray2dark_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_gray2dark_sel.xml
new file mode 100644
index 0000000..37e6784
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_gray2dark_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primary2dark_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primary2dark_sel.xml
new file mode 100644
index 0000000..ca9961b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primary2dark_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primarydark_indicator_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primarydark_indicator_sel.xml
new file mode 100644
index 0000000..d707a2b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_primarydark_indicator_sel.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_tran2gray_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_tran2gray_sel.xml
new file mode 100644
index 0000000..37b3161
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_tran2gray_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_white2gray_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_white2gray_sel.xml
new file mode 100644
index 0000000..51627f4
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/bg_white2gray_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_10a_primary_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_10a_primary_solid.xml
new file mode 100644
index 0000000..21b05ab
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_10a_primary_solid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_5a_primary_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_5a_primary_solid.xml
new file mode 100644
index 0000000..e57ab2e
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_5a_primary_solid.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_primary_stroke.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_primary_stroke.xml
new file mode 100644
index 0000000..e565d38
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/cirrect_primary_stroke.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_gray_stroke.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_gray_stroke.xml
new file mode 100644
index 0000000..b450c19
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_gray_stroke.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary.xml
new file mode 100644
index 0000000..3217db0
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary2dark_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary2dark_sel.xml
new file mode 100644
index 0000000..0aa3bc0
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary2dark_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_dark.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_dark.xml
new file mode 100644
index 0000000..78afd1f
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_dark.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_light.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_light.xml
new file mode 100644
index 0000000..d11d6f2
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_light.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke.xml
new file mode 100644
index 0000000..e69f474
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke2solid_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke2solid_sel.xml
new file mode 100644
index 0000000..c784de9
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/correct_primary_stroke2solid_sel.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/layerlist_primarydark_indicator.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/layerlist_primarydark_indicator.xml
new file mode 100644
index 0000000..c899dd5
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/layerlist_primarydark_indicator.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_light_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_light_solid.xml
new file mode 100644
index 0000000..d8f9526
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_light_solid.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_solid.xml
new file mode 100644
index 0000000..3ef7599
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/oval_primary_solid.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_bottom_line.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_bottom_line.xml
new file mode 100644
index 0000000..dcfed99
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_bottom_line.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary2white_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary2white_sel.xml
new file mode 100644
index 0000000..17b996f
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary2white_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke.xml
new file mode 100644
index 0000000..b719088
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke2solid_sel.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke2solid_sel.xml
new file mode 100644
index 0000000..627165c
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_primary_stroke2solid_sel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_red_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_red_solid.xml
new file mode 100644
index 0000000..43b6e3f
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_red_solid.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_white_solid.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_white_solid.xml
new file mode 100644
index 0000000..0468e80
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_oval_white_solid.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_top_line.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_top_line.xml
new file mode 100644
index 0000000..3acffa9
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/shape_top_line.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_bg.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_bg.xml
new file mode 100644
index 0000000..73a24f6
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_bg.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_val.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_val.xml
new file mode 100644
index 0000000..35f5148
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/drawable/wheel_val.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_image_browser.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_image_browser.xml
new file mode 100644
index 0000000..3322aac
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_image_browser.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_web_view.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_web_view.xml
new file mode 100644
index 0000000..61f6c3f
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/activity_web_view.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/footer_progress.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/footer_progress.xml
new file mode 100644
index 0000000..1bb5f08
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/footer_progress.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_input.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_input.xml
new file mode 100644
index 0000000..80f4a69
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_input.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_select.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_select.xml
new file mode 100644
index 0000000..1744f6c
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/formitem_select.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_banner_with_indicator.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_banner_with_indicator.xml
new file mode 100644
index 0000000..32ff2b3
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_banner_with_indicator.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_ddm_listview.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_ddm_listview.xml
new file mode 100644
index 0000000..4b78553
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_ddm_listview.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_group_divider.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_group_divider.xml
new file mode 100644
index 0000000..12b7800
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_group_divider.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_refresh_list.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_refresh_list.xml
new file mode 100644
index 0000000..009e80e
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_refresh_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_titlebar.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_titlebar.xml
new file mode 100644
index 0000000..ae3d95a
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/include_titlebar.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_default_drop_down.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_default_drop_down.xml
new file mode 100644
index 0000000..257898b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_default_drop_down.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_banner.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_banner.xml
new file mode 100644
index 0000000..07082bc
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_banner.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_browser.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_browser.xml
new file mode 100644
index 0000000..4b4c694
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_image_browser.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_setting.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_setting.xml
new file mode 100644
index 0000000..e40889b
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/item_setting.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/listview_dropdown_menu.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/listview_dropdown_menu.xml
new file mode 100644
index 0000000..ac646e9
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/listview_dropdown_menu.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/wheel_dialog_address.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/wheel_dialog_address.xml
new file mode 100644
index 0000000..d0c664d
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/layout/wheel_dialog_address.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_checked.png b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_checked.png
new file mode 100644
index 0000000..64096f7
Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_checked.png differ
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_selected_icon.png b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_selected_icon.png
new file mode 100644
index 0000000..7bcc8c9
Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_selected_icon.png differ
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_unselected_icon.png b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_unselected_icon.png
new file mode 100644
index 0000000..bb049fa
Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/drop_down_unselected_icon.png differ
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/ic_back.png b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/ic_back.png
new file mode 100644
index 0000000..f867126
Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/mipmap-hdpi/ic_back.png differ
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/attrs.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..11b443a
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/attrs.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/colors.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/colors.xml
new file mode 100644
index 0000000..bdf4594
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/colors.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ #8BC34A
+ #76A63E
+ #E8F3BD
+ #FF4081
+ #ff9900
+ #d88200
+
+ #212121
+
+ #808080
+
+ #CCCCCC
+
+ #f1f1f1
+
+ #e8e8e8
+
+ #d54c1c
+
+ #cbcbcb
+
+ #1ea5ff
+
+
+ #C7C7C7
+
+
+ #ffffff
+ #cccccc
+
+ #8BC34A
+ #808080
+
+ #88888888
+ #f1f1f1
+ #8BC34A
+
+
+ #0D8BC34A
+ #1A8BC34A
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/dimens.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..4618632
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/dimens.xml
@@ -0,0 +1,27 @@
+
+
+
+ 16dp
+ 16dp
+
+
+ 4dp
+ 8dp
+ 16dp
+ 32dp
+ 64dp
+ 48dp
+
+
+ 34sp
+ 24sp
+ 20sp
+ 16sp
+ 14sp
+ 12sp
+
+
+ 2dp
+ 136dp
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/strings.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/strings.xml
new file mode 100644
index 0000000..11d0f63
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+ 确定
+ 取消
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/styles.xml b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/styles.xml
new file mode 100644
index 0000000..d5792f5
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/bdcodehelper/src/main/res/values/styles.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/build.gradle b/DesignResCollection_MVP-Dagger2/build.gradle
new file mode 100644
index 0000000..2187d19
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/build.gradle
@@ -0,0 +1,52 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.1.2'
+ classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
+
+// Define versions in a single place
+ext {
+ // Sdk and tools
+ minSdkVersion = 15
+ targetSdkVersion = 23
+ compileSdkVersion = 23
+ buildToolsVersion = '23.0.3'
+
+ // App dependencies
+ supportLibraryVersion = '23.4.0'
+ guavaVersion = '18.0'
+ junitVersion = '4.12'
+ mockitoVersion = '1.10.19'
+ powerMockito = '1.6.2'
+ hamcrestVersion = '1.3'
+ runnerVersion = '0.5'
+ rulesVersion = '0.5'
+ espressoVersion = '2.2.2'
+ retrofitVersion = '2.0.0-beta2'
+ okhttploggingVersion = '2.6.0'
+ rxjavaVersion = '1.1.0'
+ rxbindingVersion = '0.2.0'
+ glideVersion = '3.6.1'
+ glideokhttpVersion = '1.3.1'
+ photoviewVersion = '1.2.4'
+ daggerVersion = '2.5'
+}
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/gradle.properties b/DesignResCollection_MVP-Dagger2/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.jar b/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.properties b/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..122a0dc
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/DesignResCollection_MVP-Dagger2/gradlew b/DesignResCollection_MVP-Dagger2/gradlew
new file mode 100644
index 0000000..9d82f78
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "0ドル"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: 0ドル may be a link
+PRG="0ドル"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*'> /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/">/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED">/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java>/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/DesignResCollection_MVP-Dagger2/gradlew.bat b/DesignResCollection_MVP-Dagger2/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version>NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/DesignResCollection_MVP-Dagger2/settings.gradle b/DesignResCollection_MVP-Dagger2/settings.gradle
new file mode 100644
index 0000000..86753a8
--- /dev/null
+++ b/DesignResCollection_MVP-Dagger2/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':bdcodehelper'
diff --git a/DesignResCollection_MVP/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java b/DesignResCollection_MVP/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java
index 5fa0e91..fd29dd6 100644
--- a/DesignResCollection_MVP/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java
+++ b/DesignResCollection_MVP/app/src/main/java/com/boredream/designrescollection/ui/register/RegisterPresenter.java
@@ -80,7 +80,7 @@ public void register(String phone, String password, String code) {
user.setPassword(password);
user.setSmsCode(code);
Observable observable = HttpRequest.getInstance().service.register(user);
- observable.subscribe(new Subscriber() {
+ ObservableDecorator.decorate(observable).subscribe(new Subscriber() {
@Override
public void onCompleted() {
diff --git a/README.md b/README.md
index ab96516..8811312 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,6 @@
### 待开发的示例
- * [DesignResCollection_MVP-Dagger2/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP-Dagger2) - 基于 Model-View-Presenter 结构,添加Dagger2框架。
* [DesignResCollection_LeanCloud/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP-Dagger2) - 基于 LeanCloud 服务,不用自己写后台服务端代码,非全栈开发也可以完成完整网络应用。
* [DesignResCollection_IM/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP-Dagger2) - 基于 LeanCloud 服务,实现IM及时聊天业务,提供最基本的IM相关功能。
* [DesignResCollection_Espresso/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP-Dagger2) - 单独抽取出来一个项目,详细介绍Espresso针对各种常用场景的测试写法。
@@ -35,9 +34,6 @@
* 2016年8月17日 ~ 9.20(已完成)
[DesignResCollection_MVP/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP)
-* 2016年9月20日 ~
-[DesignResCollection_MVP-Dagger2/](https://github.com/boredream/DesignResCollection/tree/master/DesignResCollection_MVP-Dagger2)
-
## 通用依赖框架