This commit is contained in:
2025-11-18 15:12:24 +08:00
parent c173c425ce
commit a7d2035e70
1361 changed files with 367452 additions and 0 deletions
@@ -0,0 +1,65 @@
package cn.shangyu.gdxzExpert.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
/**
* Date:2019/8/21
* Time:9:27
* author:xiayile
*
* //隐藏键盘
*/
public class AutoHideIMEFrameLayout extends FrameLayout {
public AutoHideIMEFrameLayout(Context context) {
super(context);
}
public AutoHideIMEFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoHideIMEFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Context context = getContext();
if (context == null || !(context instanceof Activity)) {
return super.dispatchTouchEvent(ev);
}
Activity activity = (Activity) context;
View focusView = activity.getCurrentFocus();
if (focusView != null && shouldHideInputMethod(focusView, ev)) {
hideInputMethod(focusView);
}
}
return super.dispatchTouchEvent(ev);
}
private boolean shouldHideInputMethod(View focusView, MotionEvent event) {
Rect rect = new Rect();
focusView.getHitRect(rect);
return !rect.contains((int) event.getX(), (int) event.getY());
}
private void hideInputMethod(View currentFocus) {
if (currentFocus == null) {
return;
}
InputMethodManager imm = (InputMethodManager) currentFocus.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(currentFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
@@ -0,0 +1,98 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import androidx.appcompat.widget.AppCompatTextView;
import cn.shangyu.gdxzExpert.R;
public class AutoScaleTextView extends AppCompatTextView {
private float preferredTextSize;
private float minTextSize;
private Paint textPaint;
public AutoScaleTextView(Context context) {
super(context, null);
}
public AutoScaleTextView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.autoScaleTextViewStyle);
}
public AutoScaleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.textPaint = new Paint();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoScaleTextView, defStyleAttr, 0);
this.minTextSize = a.getDimension(R.styleable.AutoScaleTextView_minTextSize, 5f);
a.recycle();
this.preferredTextSize = this.getTextSize();
}
/**
* 设置最小的size
*
* @param minTextSize
*/
public void setMinTextSize(float minTextSize) {
this.minTextSize = minTextSize;
}
/**
* 根据填充内容调整textview
*
* @param text
* @param textWidth
*/
private void refitText(String text, int textWidth) {
if (textWidth <= 0 || text == null || text.length() == 0) {
return;
}
int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
final float threshold = 0.5f;
this.textPaint.set(this.getPaint());
this.textPaint.setTextSize(this.preferredTextSize);
if (this.textPaint.measureText(text) <= targetWidth) {
this.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.preferredTextSize);
return;
}
float tempMinTextSize = this.minTextSize;
float tempPreferredTextSize = this.preferredTextSize;
while ((tempPreferredTextSize - tempMinTextSize) > threshold) {
float size = (tempPreferredTextSize + tempMinTextSize) / 2;
this.textPaint.setTextSize(size);
if (this.textPaint.measureText(text) >= targetWidth) {
tempPreferredTextSize = size;
} else {
tempMinTextSize = size;
}
}
this.setTextSize(TypedValue.COMPLEX_UNIT_PX, tempMinTextSize);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
this.refitText(text.toString(), this.getWidth());
}
@Override
protected void onSizeChanged(int width, int h, int oldw, int oldh) {
if (width != oldw) {
this.refitText(this.getText().toString(), width);
}
}
}
@@ -0,0 +1,176 @@
package cn.shangyu.gdxzExpert.view;
import java.text.NumberFormat;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.widget.ProgressBar;
import android.widget.TextView;
import cn.shangyu.gdxzExpert.R;
/**
* 自定义进度条
*
* @author 黄淑媛
*
*/
public class CommonProgressDialog extends AlertDialog {
private ProgressBar mProgress;
private TextView mProgressNumber;
private TextView mProgressPercent;
private TextView mProgressMessage;
private Handler mViewUpdateHandler;
private int mMax;
private CharSequence mMessage;
private boolean mHasStarted;
private int mProgressVal;
private String TAG = "CommonProgressDialog";
private String mProgressNumberFormat;
private NumberFormat mProgressPercentFormat;
public CommonProgressDialog(Context context) {
super(context);
// TODO Auto-generated constructor stub
initFormats();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.common_progress_dialog);
mProgress = (ProgressBar) findViewById(R.id.progress);
mProgressNumber = (TextView) findViewById(R.id.progress_number);
mProgressPercent = (TextView) findViewById(R.id.progress_percent);
mProgressMessage = (TextView) findViewById(R.id.progress_message);
// LayoutInflater inflater = LayoutInflater.from(getContext());
mViewUpdateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
int progress = mProgress.getProgress();
int max = mProgress.getMax();
double dProgress = (double) progress / (double) (1024 * 1024);
double dMax = (double) max / (double) (1024 * 1024);
if (mProgressNumberFormat != null) {
String format = mProgressNumberFormat;
mProgressNumber.setText(String.format(format, dProgress,
dMax));
} else {
mProgressNumber.setText("");
}
if (mProgressPercentFormat != null) {
double percent = (double) progress / (double) max;
SpannableString tmp = new SpannableString(
mProgressPercentFormat.format(percent));
tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mProgressPercent.setText(tmp);
} else {
mProgressPercent.setText("");
}
}
};
// View view = inflater.inflate(R.layout.common_progress_dialog, null);
// mProgress = (ProgressBar) view.findViewById(R.id.progress);
// mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
// mProgressPercent = (TextView)
// view.findViewById(R.id.progress_percent);
// setView(view);
// mProgress.setMax(100);
onProgressChanged();
if (mMessage != null) {
setMessage(mMessage);
}
if (mMax > 0) {
setMax(mMax);
}
if (mProgressVal > 0) {
setProgress(mProgressVal);
}
}
private void initFormats() {
mProgressNumberFormat = "%1.2fM/%2.2fM";
mProgressPercentFormat = NumberFormat.getPercentInstance();
mProgressPercentFormat.setMaximumFractionDigits(0);
}
private void onProgressChanged() {
mViewUpdateHandler.sendEmptyMessage(0);
}
public void setProgressStyle(int style) {
// mProgressStyle = style;
}
public int getMax() {
if (mProgress != null) {
return mProgress.getMax();
}
return mMax;
}
public void setMax(int max) {
if (mProgress != null) {
mProgress.setMax(max);
onProgressChanged();
} else {
mMax = max;
}
}
public void setIndeterminate(boolean indeterminate) {
if (mProgress != null) {
mProgress.setIndeterminate(indeterminate);
}
// else {
// mIndeterminate = indeterminate;
// }
}
public void setProgress(int value) {
if (mHasStarted) {
mProgress.setProgress(value);
onProgressChanged();
} else {
mProgressVal = value;
}
}
@Override
public void setMessage(CharSequence message) {
// TODO Auto-generated method stub
// super.setMessage(message);
if (mProgressMessage != null) {
mProgressMessage.setText(message);
} else {
mMessage = message;
}
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
mHasStarted = true;
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
mHasStarted = false;
}
}
@@ -0,0 +1,44 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.TextView;
public class DrawableCenterButton extends TextView {
public DrawableCenterButton(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public DrawableCenterButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawableCenterButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableLeft = drawables[0];
if (drawableLeft != null) {
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = 0;
drawableWidth = drawableLeft.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth) / 2, 0);
}
}
super.onDraw(canvas);
}
}
@@ -0,0 +1,47 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
public class DrawableCenterButtonR extends TextView {
public DrawableCenterButtonR(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public DrawableCenterButtonR(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawableCenterButtonR(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableRight = drawables[2];
if (drawableRight != null) {
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = 0;
drawableWidth = drawableRight.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
setPadding(0, 0, (int) (getWidth() - bodyWidth), 0);
canvas.translate((getWidth() - bodyWidth) / 2, 0);
}
}
super.onDraw(canvas);
}
}
@@ -0,0 +1,47 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
public class DrawableCenterCheckBox extends CheckBox {
public DrawableCenterCheckBox(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public DrawableCenterCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawableCenterCheckBox(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableRight = drawables[2];
if (drawableRight != null) {
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = 0;
drawableWidth = drawableRight.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
setPadding(0, 0, (int) (getWidth() - bodyWidth), 0);
canvas.translate((getWidth() - bodyWidth) / 2, 0);
}
}
super.onDraw(canvas);
}
}
@@ -0,0 +1,322 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import cn.shangyu.gdxzExpert.R;
/**
* Created by WANGChengXin on 2019/7/30.
*/
public class DrugView<X extends TextView> extends ViewGroup {
public static final String BTN_MODE = "BTNMODE"; //按钮模式
public static final String TEV_MODE = "TEVMODE"; //文本模式
private static final String TAG = "IViewGroup";
private final int HorInterval = 45; //水平间隔
private final int VerInterval = 45; //垂直间隔
private int viewWidth; //控件的宽度
private int viewHeight; //控件的高度
private ArrayList<String> mTexts = new ArrayList<>();
private Context mContext;
private int textModePaddingx = 20;
private int textModePaddingy = 15;
//正常样式
private float itemTextSize = 12;
private int itemBGResNor = R.drawable.rect_false_drug;
private int itemTextColorNor = Color.parseColor("#8D2316");
//选中的样式
private int itemBGResPre = R.drawable.rect_false_drug;
private int itemTextColorPre = Color.parseColor("#8D2316");
public DrugView(Context context) {
this(context, null);
}
public DrugView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
/**
* 计算控件的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = measureWidth(widthMeasureSpec);
viewHeight = measureHeight(heightMeasureSpec);
Log.e(TAG, "onMeasure:" + viewWidth + ":" + viewHeight);
// 计算自定义的ViewGroup中所有子控件的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 设置自定义的控件MyViewGroup的大小
setMeasuredDimension(viewWidth, getViewHeight());
}
private int measureWidth(int pWidthMeasureSpec) {
int result = 0;
int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);
int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);
switch (widthMode) {
/**
* mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
* MeasureSpec.AT_MOST。
*
*
* MeasureSpec.EXACTLY是精确尺寸,
* 当我们将控件的layout_width或layout_height指定为具体数值时如andorid
* :layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
*
*
* MeasureSpec.AT_MOST是最大尺寸,
* 当控件的layout_width或layout_height指定为WRAP_CONTENT时
* ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可
* 。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
*
*
* MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,
* 通过measure方法传入的模式。
*/
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = widthSize;
break;
}
return result;
}
private int measureHeight(int pHeightMeasureSpec) {
int result = 0;
int heightMode = MeasureSpec.getMode(pHeightMeasureSpec);
int heightSize = MeasureSpec.getSize(pHeightMeasureSpec);
switch (heightMode) {
case MeasureSpec.UNSPECIFIED:
result = getSuggestedMinimumHeight();
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = heightSize;
break;
}
return result;
}
/**
* 覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,
* 才能确定怎么摆放
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 遍历所有子视图
int posLeft = HorInterval;
int posTop = VerInterval;
int posRight;
int posBottom;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (posLeft + getNextHorLastPos(i) > viewWidth) {
posLeft = HorInterval;
posTop += (measureHeight + VerInterval);
}
posRight = posLeft + measuredWidth;
posBottom = posTop + measureHeight;
childView.layout(posLeft, posTop, posRight, posBottom);
posLeft += (measuredWidth + HorInterval);
}
}
//获取控件的自适应高度
private int getViewHeight() {
int viewwidth = HorInterval;
int viewheight = VerInterval;
if (getChildCount() > 0) {
viewheight = getChildAt(0).getMeasuredHeight() + VerInterval;
}
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (viewwidth + getNextHorLastPos(i) > viewWidth) {
viewwidth = HorInterval+measureHeight;
viewheight += (measureHeight + VerInterval);
} else {
viewwidth += (measuredWidth + HorInterval);
}
}
viewheight= viewheight+300;
return viewheight;
}
private int getNextHorLastPos(int i) {
return getChildAt(i).getMeasuredWidth() + HorInterval;
}
private OnGroupItemClickListener onGroupItemClickListener;
public void setGroupClickListener(OnGroupItemClickListener listener) {
onGroupItemClickListener = listener;
for (int i = 0; i < getChildCount(); i++) {
final X childView = (X) getChildAt(i);
final int itemPos = i;
childView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
onGroupItemClickListener.onGroupItemClick(itemPos);
chooseItemStyle(itemPos);
}
});
}
}
//选中那个的样式
public void chooseItemStyle(int pos) {
clearItemsStyle();
if (pos < getChildCount()) {
X childView = (X) getChildAt(pos);
childView.setBackgroundResource(itemBGResPre);
childView.setTextColor(itemTextColorPre);
setItemPadding(childView);
}
}
private void setItemPadding(X view) {
if (view instanceof Button) {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
} else {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
}
}
//清除Group所有的样式
private void clearItemsStyle() {
for (int i = 0; i < getChildCount(); i++) {
X childView = (X) getChildAt(i);
childView.setBackgroundResource(itemBGResNor);
childView.setTextColor(itemTextColorNor);
setItemPadding(childView);
}
}
public void addItemViews(ArrayList<String> texts, String mode) {
mTexts = texts;
removeAllViews();
for (int i = 0;i<texts.size();i++){
addItemView(texts.get(i), mode,i);
}
// for (String text : texts) {
// addItemView(text, mode);
// }
}
public void addBigItemViews(ArrayList<String> texts, String mode,int textsize) {
mTexts = texts;
removeAllViews();
for (int i = 0;i<texts.size();i++){
addBigItemView(texts.get(i), mode,i,textsize);
}
}
private void addBigItemView(String text, String mode,int i,int textsize) {
X childView = null;
switch (mode) {
case BTN_MODE:
childView = (X) new Button(mContext);
break;
case TEV_MODE:
childView = (X) new TextView(mContext);
break;
}
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
childView.setTextSize(textsize);
if (i==0){
childView.setBackgroundResource(itemBGResPre);
setItemPadding(childView);
childView.setTextColor(itemTextColorPre);
childView.setText(text);
this.addView(childView);
}else {
childView.setBackgroundResource(itemBGResNor);
setItemPadding(childView);
childView.setTextColor(itemTextColorNor);
childView.setText(text);
this.addView(childView);
}
}
private void addItemView(String text, String mode,int i) {
X childView = null;
switch (mode) {
case BTN_MODE:
childView = (X) new Button(mContext);
break;
case TEV_MODE:
childView = (X) new TextView(mContext);
break;
}
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
childView.setTextSize(itemTextSize);
if (i==0){
childView.setBackgroundResource(itemBGResPre);
setItemPadding(childView);
childView.setTextColor(itemTextColorPre);
childView.setText(text);
this.addView(childView);
}else {
childView.setBackgroundResource(itemBGResNor);
setItemPadding(childView);
childView.setTextColor(itemTextColorNor);
childView.setText(text);
this.addView(childView);
}
}
public String getChooseText(int itemID) {
if (itemID >= 0) {
return mTexts.get(itemID);
}
return null;
}
public void setItemTextSize(float itemTextSize) {
this.itemTextSize = itemTextSize;
}
public void setItemBGResNor(int itemBGResNor) {
this.itemBGResNor = itemBGResNor;
}
public void setItemTextColorNor(int itemTextColorNor) {
this.itemTextColorNor = itemTextColorNor;
}
public void setItemBGResPre(int itemBGResPre) {
this.itemBGResPre = itemBGResPre;
}
public void setItemTextColorPre(int itemTextColorPre) {
this.itemTextColorPre = itemTextColorPre;
}
public interface OnGroupItemClickListener {
void onGroupItemClick(int item);
}
}
@@ -0,0 +1,262 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import static cn.shangyu.gdxzExpert.utils.DensityUtil.dip2px;
public class GSpaceItemDecoration extends RecyclerView.ItemDecoration {
private static final String TAG = "GridDividerItemDeco";
private Context mContext;
private int mFirstAndLastColumnW; //您所需指定的间隔宽度,主要为第一列和最后一列与父控件的间隔;行间距,列间距将动态分配
private int mFirstRowTopMargin = 0; //第一行顶部是否需要间隔
private int mLastRowBottomMargin = 0;
private int mSpanCount = 0;
private int mScreenW = 0;
private int mItemDistance;
/**
* @param firstAndLastColumnW 间隔宽度
* @param firstRowTopMargin 第一行顶部是否需要间隔
*/
public GSpaceItemDecoration(Context context, int firstAndLastColumnW, int firstRowTopMargin, int lastRowBottomMargin) {
mContext = context;
mFirstAndLastColumnW = dip2px(firstAndLastColumnW);
mFirstRowTopMargin = dip2px(firstRowTopMargin);
mLastRowBottomMargin = dip2px(lastRowBottomMargin);
}
public void setFirstRowTopMargin(int firstRowTopMargin) {
mFirstRowTopMargin = firstRowTopMargin;
}
public void setLastRowBottomMargin(int lastRowBottomMargin) {
mLastRowBottomMargin = lastRowBottomMargin;
}
public void setItemDistance(int itemDistance) {
mItemDistance = itemDistance;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int top = 0;
int left;
int right;
int bottom;
int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
mSpanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
// 屏幕宽度-View的宽度*spanCount 得到屏幕剩余空间
int maxDividerWidth = getMaxDividerWidth(view);
int spaceWidth = mFirstAndLastColumnW;//首尾两列与父布局之间的间隔
// 除去首尾两列,item与item之间的距离
int eachItemWidth = maxDividerWidth / mSpanCount;
int dividerItemWidth = (maxDividerWidth - 2 * spaceWidth) / (mSpanCount - 1);//item与item之间的距离
left = itemPosition % mSpanCount * (dividerItemWidth - eachItemWidth) + spaceWidth;
right = eachItemWidth - left;
bottom = dividerItemWidth;
// 首行
if (mFirstRowTopMargin > 0 && isFirstRow(parent, itemPosition, mSpanCount, childCount)) {
top = mFirstRowTopMargin;
}
//最后一行
if (isLastRow(parent, itemPosition, mSpanCount, childCount)) {
if (mLastRowBottomMargin < 0) {
bottom = 0;
} else {
bottom = mLastRowBottomMargin;
}
}
outRect.set(left, top, right, bottom);
}
/**
* 获取Item View的大小,若无则自动分配空间
* 并根据 屏ge幕宽度-View的宽度*spanCount 得到屏幕剩余空间
*
* @param view
* @return
*/
private int getMaxDividerWidth(View view) {
int itemWidth = view.getLayoutParams().width;
int itemHeight = view.getLayoutParams().height;
int screenWidth = getScreenWidth();
int maxDividerWidth = screenWidth - itemWidth * mSpanCount;
if (itemHeight < 0 || itemWidth < 0 || maxDividerWidth <= (mSpanCount - 1) * mFirstAndLastColumnW) {
view.getLayoutParams().width = getAttachCloumnWidth();
view.getLayoutParams().height = getAttachCloumnWidth();
maxDividerWidth = screenWidth - view.getLayoutParams().width * mSpanCount;
}
return maxDividerWidth;
}
private int getScreenWidth() {
if (mScreenW > 0) {
return mScreenW;
}
mScreenW = mContext.getResources().getDisplayMetrics().widthPixels > mContext.getResources().getDisplayMetrics().heightPixels
? mContext.getResources().getDisplayMetrics().heightPixels : mContext.getResources().getDisplayMetrics().widthPixels;
return mScreenW;
}
/**
* 根据屏幕宽度和item数量分配 item View的width和height
*
* @return
*/
private int getAttachCloumnWidth() {
int itemWidth = 0;
int spaceWidth = 0;
try {
int width = getScreenWidth();
spaceWidth = 2 * mFirstAndLastColumnW;
itemWidth = (width - spaceWidth) / mSpanCount - 40;
} catch (Exception e) {
e.printStackTrace();
}
return itemWidth;
}
/**
* 判读是否是第一列
*
* @param parent
* @param pos
* @param spanCount
* @return
*/
private boolean isFirstColumn(RecyclerView parent, int pos, int spanCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
if (pos % spanCount == 0) {
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
if (pos % spanCount == 0) {// 第一列
return true;
}
} else {
}
}
return false;
}
/**
* 判断是否是最后一列
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isLastColumn(RecyclerView parent, int pos, int spanCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
if ((pos + 1) % spanCount == 0) {// 如果是最后一列,则不需要绘制右边
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
if ((pos + 1) % spanCount == 0) {// 最后一列
return true;
}
} else {
}
}
return false;
}
/**
* 判读是否是最后一行
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isLastRow(RecyclerView parent, int pos, int spanCount, int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
int lines = childCount % spanCount == 0 ? childCount / spanCount : childCount / spanCount + 1;
return lines == pos / spanCount + 1;
}
return false;
}
/**
* 判断是否是第一行
*
* @param parent
* @param pos
* @param spanCount
* @param childCount
* @return
*/
private boolean isFirstRow(RecyclerView parent, int pos, int spanCount, int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
if ((pos / spanCount + 1) == 1) {
return true;
} else {
return false;
}
}
return false;
}
/**
* 获取列数
*
* @param parent
* @return
*/
private int getSpanCount(RecyclerView parent) {
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
return spanCount;
}
}
@@ -0,0 +1,287 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import cn.shangyu.gdxzExpert.R;
/**
* Created by WANGChengXin on 2019/10/21.单选
*/
public class GroupManageSingleView<X extends TextView> extends ViewGroup {
public static final String BTN_MODE = "BTNMODE"; //按钮模式
public static final String TEV_MODE = "TEVMODE"; //文本模式
private static final String TAG = "IViewGroup";
private final int HorInterval = 45; //水平间隔
private final int VerInterval = 45; //垂直间隔
private int viewWidth; //控件的宽度
private int viewHeight; //控件的高度
private ArrayList<String> mTexts = new ArrayList<>();
private Context mContext;
private int textModePaddingx = 30;
private int textModePaddingy = 15;
//正常样式
private float itemTextSize = 12;
private int itemBGResNor = R.drawable.rect_normal_group;
private int itemTextColorNor = Color.parseColor("#ff999999");
//选中的样式
private int itemBGResPre = R.drawable.rect_false_drug;
private int itemTextColorPre = Color.parseColor("#8D2316");
public GroupManageSingleView(Context context) {
this(context, null);
}
public GroupManageSingleView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
/**
* 计算控件的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = measureWidth(widthMeasureSpec);
viewHeight = measureHeight(heightMeasureSpec);
Log.e(TAG, "onMeasure:" + viewWidth + ":" + viewHeight);
// 计算自定义的ViewGroup中所有子控件的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 设置自定义的控件MyViewGroup的大小
setMeasuredDimension(viewWidth, getViewHeight());
}
private int measureWidth(int pWidthMeasureSpec) {
int result = 0;
int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);
int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);
switch (widthMode) {
/**
* mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
* MeasureSpec.AT_MOST。
*
*
* MeasureSpec.EXACTLY是精确尺寸,
* 当我们将控件的layout_width或layout_height指定为具体数值时如andorid
* :layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
*
*
* MeasureSpec.AT_MOST是最大尺寸,
* 当控件的layout_width或layout_height指定为WRAP_CONTENT时
* ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可
* 。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
*
*
* MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,
* 通过measure方法传入的模式。
*/
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = widthSize;
break;
}
return result;
}
private int measureHeight(int pHeightMeasureSpec) {
int result = 0;
int heightMode = MeasureSpec.getMode(pHeightMeasureSpec);
int heightSize = MeasureSpec.getSize(pHeightMeasureSpec);
switch (heightMode) {
case MeasureSpec.UNSPECIFIED:
result = getSuggestedMinimumHeight();
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = heightSize;
break;
}
return result;
}
/**
* 覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,
* 才能确定怎么摆放
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 遍历所有子视图
int posLeft = HorInterval;
int posTop = VerInterval;
int posRight;
int posBottom;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (posLeft + getNextHorLastPos(i) > viewWidth) {
posLeft = HorInterval+measuredWidth;
posTop += (measureHeight + VerInterval);
}
posRight = posLeft + measuredWidth;
posBottom = posTop + measureHeight;
childView.layout(posLeft, posTop, posRight, posBottom);
posLeft += (measuredWidth + HorInterval);
}
}
//获取控件的自适应高度
private int getViewHeight() {
int viewwidth = HorInterval;
int viewheight = VerInterval;
if (getChildCount() > 0) {
viewheight = getChildAt(0).getMeasuredHeight() + VerInterval;
}
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (viewwidth + getNextHorLastPos(i) > viewWidth) {
viewwidth = HorInterval;
viewheight += (measureHeight + VerInterval);
} else {
viewwidth += (measuredWidth + HorInterval);
}
}
return viewheight;
}
private int getNextHorLastPos(int i) {
return getChildAt(i).getMeasuredWidth() + HorInterval;
}
private OnGroupItemClickListener onGroupItemClickListener;
public void setGroupClickListener(OnGroupItemClickListener listener) {
onGroupItemClickListener = listener;
for (int i = 0; i < getChildCount(); i++) {
final X childView = (X) getChildAt(i);
final int itemPos = i;
childView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
onGroupItemClickListener.onGroupItemClick(itemPos);
chooseItemStyle(itemPos);
}
});
}
}
//选中那个的样式
public void chooseItemStyle(int pos) {
clearItemsStyle();
if (pos < getChildCount()) {
X childView = (X) getChildAt(pos);
childView.setBackgroundResource(itemBGResPre);
childView.setTextColor(itemTextColorPre);
setItemPadding(childView);
}
}
private void setItemPadding(X view) {
if (view instanceof Button) {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
} else {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
}
}
//清除Group所有的样式
private void clearItemsStyle() {
for (int i = 0; i < getChildCount(); i++) {
X childView = (X) getChildAt(i);
childView.setBackgroundResource(itemBGResNor);
childView.setTextColor(itemTextColorNor);
setItemPadding(childView);
}
}
public void addItemViews(ArrayList<String> texts, String mode,int position) {
mTexts = texts;
removeAllViews();
for (int i = 0;i<texts.size();i++){
addItemView(texts.get(i), mode,i,position);
}
// for (String text : texts) {
// addItemView(text, mode);
// }
}
private void addItemView(String text, String mode,int i,int position) {
X childView = null;
switch (mode) {
case BTN_MODE:
childView = (X) new Button(mContext);
break;
case TEV_MODE:
childView = (X) new TextView(mContext);
break;
}
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
childView.setTextSize(itemTextSize);
if (i==position){
childView.setBackgroundResource(itemBGResPre);
setItemPadding(childView);
childView.setTextColor(itemTextColorPre);
childView.setText(text);
this.addView(childView);
}else {
childView.setBackgroundResource(itemBGResNor);
setItemPadding(childView);
childView.setTextColor(itemTextColorNor);
childView.setText(text);
this.addView(childView);
}
}
public String getChooseText(int itemID) {
if (itemID >= 0) {
return mTexts.get(itemID);
}
return null;
}
public void setItemTextSize(float itemTextSize) {
this.itemTextSize = itemTextSize;
}
public void setItemBGResNor(int itemBGResNor) {
this.itemBGResNor = itemBGResNor;
}
public void setItemTextColorNor(int itemTextColorNor) {
this.itemTextColorNor = itemTextColorNor;
}
public void setItemBGResPre(int itemBGResPre) {
this.itemBGResPre = itemBGResPre;
}
public void setItemTextColorPre(int itemTextColorPre) {
this.itemTextColorPre = itemTextColorPre;
}
public interface OnGroupItemClickListener {
void onGroupItemClick(int item);
}
}
@@ -0,0 +1,333 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import cn.shangyu.gdxzExpert.R;
import cn.shangyu.gdxzExpert.bean.GroupManageBean;
/**
* Created by WANGChengXin on 2019/7/30.//多选
*/
public class GroupmanageView<X extends TextView> extends ViewGroup {
public static final String BTN_MODE = "BTNMODE"; //按钮模式
public static final String TEV_MODE = "TEVMODE"; //文本模式
private static final String TAG = "IViewGroup";
private final int HorInterval = 45; //水平间隔
private final int VerInterval = 45; //垂直间隔
private int viewWidth; //控件的宽度
private int viewHeight; //控件的高度
private ArrayList<GroupManageBean> mTexts = new ArrayList<>();
private Context mContext;
private int textModePaddingx = 20;
private int textModePaddingy = 15;
//正常样式
private float itemTextSize = 12;
private int itemBGResNor = R.drawable.rect_normal_group;
private int itemTextColorNor = Color.parseColor("#ff999999");
//选中的样式
private int itemBGResPre = R.drawable.rect_false_drug;
private int itemTextColorPre = Color.parseColor("#8D2316");
public GroupmanageView(Context context) {
this(context, null);
}
public GroupmanageView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
/**
* 计算控件的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = measureWidth(widthMeasureSpec);
viewHeight = measureHeight(heightMeasureSpec);
Log.e(TAG, "onMeasure:" + viewWidth + ":" + viewHeight);
// 计算自定义的ViewGroup中所有子控件的大小
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 设置自定义的控件MyViewGroup的大小
setMeasuredDimension(viewWidth, getViewHeight());
}
private int measureWidth(int pWidthMeasureSpec) {
int result = 0;
int widthMode = MeasureSpec.getMode(pWidthMeasureSpec);
int widthSize = MeasureSpec.getSize(pWidthMeasureSpec);
switch (widthMode) {
/**
* mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,
* MeasureSpec.AT_MOST。
*
*
* MeasureSpec.EXACTLY是精确尺寸,
* 当我们将控件的layout_width或layout_height指定为具体数值时如andorid
* :layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
*
*
* MeasureSpec.AT_MOST是最大尺寸,
* 当控件的layout_width或layout_height指定为WRAP_CONTENT时
* ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可
* 。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
*
*
* MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,
* 通过measure方法传入的模式。
*/
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = widthSize;
break;
}
return result;
}
private int measureHeight(int pHeightMeasureSpec) {
int result = 0;
int heightMode = MeasureSpec.getMode(pHeightMeasureSpec);
int heightSize = MeasureSpec.getSize(pHeightMeasureSpec);
switch (heightMode) {
case MeasureSpec.UNSPECIFIED:
result = getSuggestedMinimumHeight();
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = heightSize;
break;
}
return result;
}
/**
* 覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,
* 才能确定怎么摆放
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 遍历所有子视图
int posLeft = HorInterval;
int posTop = VerInterval;
int posRight;
int posBottom;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (posLeft + getNextHorLastPos(i) > viewWidth) {
posLeft = HorInterval;
posTop += (measureHeight + VerInterval);
}
posRight = posLeft + measuredWidth;
posBottom = posTop + measureHeight;
childView.layout(posLeft, posTop, posRight, posBottom);
posLeft += (measuredWidth + HorInterval);
}
}
//获取控件的自适应高度
private int getViewHeight() {
int viewwidth = HorInterval;
int viewheight = VerInterval;
if (getChildCount() > 0) {
viewheight = getChildAt(0).getMeasuredHeight() + VerInterval;
}
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
if (viewwidth + getNextHorLastPos(i) > viewWidth) {
viewwidth = HorInterval+measureHeight;
viewheight += (measureHeight + VerInterval);
} else {
viewwidth += (measuredWidth + HorInterval);
}
}
viewheight= viewheight+200;
return viewheight;
}
private int getNextHorLastPos(int i) {
return getChildAt(i).getMeasuredWidth() + HorInterval;
}
private OnGroupItemClickListener onGroupItemClickListener;
public void setGroupClickListener(OnGroupItemClickListener listener) {
onGroupItemClickListener = listener;
for (int i = 0; i < getChildCount(); i++) {
final X childView = (X) getChildAt(i);
final int itemPos = i;
childView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// chooseItemStyle(itemPos);
onGroupItemClickListener.onGroupItemClick(itemPos);
}
});
}
}
//选中那个的样式,如果ischoose,false,true判断
public void chooseItemStyle(int pos) {
// clearItemsStyle();
if (pos < getChildCount()) {
if (!mTexts.get(pos).isIschoose()){
X childView = (X) getChildAt(pos);
childView.setBackgroundResource(itemBGResPre);
childView.setTextColor(itemTextColorPre);
setItemPadding(childView);
mTexts.get(pos).setIschoose(true);
}else {
X childView = (X) getChildAt(pos);
childView.setBackgroundResource(itemBGResNor);
childView.setTextColor(itemTextColorNor);
setItemPadding(childView);
mTexts.get(pos).setIschoose(false);
}
}
}
private void setItemPadding(X view) {
if (view instanceof Button) {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
} else {
view.setPadding(textModePaddingx, textModePaddingy, textModePaddingx, textModePaddingy);
}
}
//清除Group所有的样式
private void clearItemsStyle() {
for (int i = 0; i < getChildCount(); i++) {
X childView = (X) getChildAt(i);
childView.setBackgroundResource(itemBGResNor);
childView.setTextColor(itemTextColorNor);
setItemPadding(childView);
}
}
public void addBigItemViews(ArrayList<GroupManageBean> texts, String mode,int textsize) {
mTexts = texts;
removeAllViews();
for (int i = 0;i<texts.size();i++){
addBigItemView(texts.get(i), mode,i,textsize);
}
}
private void addBigItemView(GroupManageBean bean, String mode,int i,int textsize) {
X childView = null;
switch (mode) {
case BTN_MODE:
childView = (X) new Button(mContext);
break;
case TEV_MODE:
childView = (X) new TextView(mContext);
break;
}
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
childView.setTextSize(textsize);
if (bean.isIschoose()){
childView.setBackgroundResource(itemBGResPre);
setItemPadding(childView);
childView.setTextColor(itemTextColorPre);
childView.setText(bean.getName());
this.addView(childView);
}else {
childView.setBackgroundResource(itemBGResNor);
setItemPadding(childView);
childView.setTextColor(itemTextColorNor);
childView.setText(bean.getName());
this.addView(childView);
}
}
public void addItemViews(ArrayList<GroupManageBean> texts, String mode) {
mTexts = texts;
removeAllViews();
for (int i = 0;i<texts.size();i++){
addItemView(texts.get(i), mode,i);
}
// for (String text : texts) {
// addItemView(text, mode);
// }
}
private void addItemView(GroupManageBean bean, String mode,int i) {
X childView = null;
switch (mode) {
case BTN_MODE:
childView = (X) new Button(mContext);
break;
case TEV_MODE:
childView = (X) new TextView(mContext);
break;
}
childView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
childView.setTextSize(itemTextSize);
if (bean.isIschoose()){
childView.setBackgroundResource(itemBGResPre);
setItemPadding(childView);
childView.setTextColor(itemTextColorPre);
childView.setText(bean.getName());
this.addView(childView);
}else {
childView.setBackgroundResource(itemBGResNor);
setItemPadding(childView);
childView.setTextColor(itemTextColorNor);
childView.setText(bean.getName());
this.addView(childView);
}
}
// public String getChooseText(int itemID) {
// if (itemID >= 0) {
// return mTexts.get(itemID);
// }
// return null;
// }
public void setItemTextSize(float itemTextSize) {
this.itemTextSize = itemTextSize;
}
public void setItemBGResNor(int itemBGResNor) {
this.itemBGResNor = itemBGResNor;
}
public void setItemTextColorNor(int itemTextColorNor) {
this.itemTextColorNor = itemTextColorNor;
}
public void setItemBGResPre(int itemBGResPre) {
this.itemBGResPre = itemBGResPre;
}
public void setItemTextColorPre(int itemTextColorPre) {
this.itemTextColorPre = itemTextColorPre;
}
public interface OnGroupItemClickListener {
void onGroupItemClick(int item);
}
}
@@ -0,0 +1,37 @@
package cn.shangyu.gdxzExpert.view;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
/**
* Date:2019/8/21
* Time:9:28
* author:xiayile
*/
public class HideIMEUtil {
public static void wrap(Activity activity) {
ViewGroup contentParent = (ViewGroup) activity.findViewById(android.R.id.content);
wrap(contentParent);
}
public static void wrap(Fragment fragment) {
ViewGroup contentParent = (ViewGroup) fragment.getView().getParent();
wrap(contentParent);
}
public static void wrap(ViewGroup contentParent) {
View content = contentParent.getChildAt(0);
contentParent.removeView(content);
ViewGroup.LayoutParams p = content.getLayoutParams();
AutoHideIMEFrameLayout layout = new AutoHideIMEFrameLayout(content.getContext());
layout.addView(content);
contentParent.addView(layout, new ViewGroup.LayoutParams(p.width, p.height));
}
}
@@ -0,0 +1,68 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
/**
* 自定义的不可左右滑动的viewpager
* @author gaopeng
*
*/
public class IndexViewPager extends ViewPager {
private boolean isCanScroll = false;
public IndexViewPager(Context context) {
super(context);
}
public IndexViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScanScroll(boolean isCanScroll) {
this.isCanScroll = isCanScroll;
}
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
if (isCanScroll) {
return super.onTouchEvent(arg0);
} else {
return false;
}
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
// TODO Auto-generated method stub
super.setCurrentItem(item, smoothScroll);
}
@Override
public void setCurrentItem(int item) {
// TODO Auto-generated method stub
super.setCurrentItem(item);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
if (isCanScroll) {
return super.onInterceptTouchEvent(arg0);
} else {
return false;
}
}
}
@@ -0,0 +1,40 @@
package cn.shangyu.gdxzExpert.view;
import android.graphics.PointF;
import android.graphics.RectF;
import android.widget.ImageView;
/**
* Created by liuheng on 2015/8/19.
*/
public class Info {
// 内部图片在整个手机界面的位置
RectF mRect = new RectF();
// 控件在窗口的位置
RectF mImgRect = new RectF();
RectF mWidgetRect = new RectF();
RectF mBaseRect = new RectF();
PointF mScreenCenter = new PointF();
float mScale;
float mDegrees;
ImageView.ScaleType mScaleType;
public Info(RectF rect, RectF img, RectF widget, RectF base, PointF screenCenter, float scale, float degrees, ImageView.ScaleType scaleType) {
mRect.set(rect);
mImgRect.set(img);
mWidgetRect.set(widget);
mScale = scale;
mScaleType = scaleType;
mDegrees = degrees;
mBaseRect.set(base);
mScreenCenter.set(screenCenter);
}
}
@@ -0,0 +1,81 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.PopupWindow;
import cn.shangyu.gdxzExpert.R;
public class ItemLongClickedPopWindow extends PopupWindow {
/**
* 书签条目弹出菜单 * @value * {@value} *
*/
public static final int FAVORITES_ITEM_POPUPWINDOW = 0;
/**
* 书签页面弹出菜单 * @value * {@value} *
*/
public static final int FAVORITES_VIEW_POPUPWINDOW = 1;
/**
* 历史条目弹出菜单 * @value * {@value} *
*/
public static final int HISTORY_ITEM_POPUPWINDOW = 3;
/**
* 历史页面弹出菜单 * @value * {@value} *
*/
public static final int HISTORY_VIEW_POPUPWINDOW = 4;
/**
* 图片项目弹出菜单 * @value * {@value} *
*/
public static final int IMAGE_VIEW_POPUPWINDOW = 5;
/**
* 超链接项目弹出菜单 * @value * {@value} *
*/
public static final int ACHOR_VIEW_POPUPWINDOW = 6;
private LayoutInflater itemLongClickedPopWindowInflater;
private View itemLongClickedPopWindowView;
private Context context;
private int type;
/**
* 构造函数 * @param context 上下文 * @param width 宽度 * @param height 高度 *
*/
public ItemLongClickedPopWindow(Context context, int type, int width, int height) {
super(context);
this.context = context;
this.type = type;
//创建
this.initTab();
//设置默认选项
setWidth(width);
setHeight(height);
setContentView(this.itemLongClickedPopWindowView);
setOutsideTouchable(true);
setFocusable(true);
}
//实例化
private void initTab() {
this.itemLongClickedPopWindowInflater = LayoutInflater.from(this.context);
switch (type) {
// case FAVORITES_ITEM_POPUPWINDOW:
// this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_favorites, null);
// break;
// case FAVORITES_VIEW_POPUPWINDOW: //对于书签内容弹出菜单,未作处理
// break;
// case HISTORY_ITEM_POPUPWINDOW:
// this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_history, null);
// break;
// case HISTORY_VIEW_POPUPWINDOW: //对于历史内容弹出菜单,未作处理
// break;
// case ACHOR_VIEW_POPUPWINDOW: //超链接
// break;
case IMAGE_VIEW_POPUPWINDOW: //图片
this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_img, null);
break;
}
}
public View getView(int id) {
return this.itemLongClickedPopWindowView.findViewById(id);
}
}
@@ -0,0 +1,67 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class KeyboardLayout extends RelativeLayout {
private static final String TAG = KeyboardLayout.class.getSimpleName();
public static final byte KEYBOARD_STATE_SHOW = -3;
public static final byte KEYBOARD_STATE_HIDE = -2;
public static final byte KEYBOARD_STATE_INIT = -1;
private boolean mHasInit;
private boolean mHasKeybord;
private int mHeight;
private onKeyboaddsChangeListener mListener;
public KeyboardLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public KeyboardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public KeyboardLayout(Context context) {
super(context);
}
/**
* set keyboard state listener
*/
public void setOnkbdStateListener(onKeyboaddsChangeListener listener){
mListener = listener;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!mHasInit) {
mHasInit = true;
mHeight = b;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_INIT);
}
} else {
mHeight = mHeight < b ? b : mHeight;
}
if (mHasInit && mHeight > b) {
mHasKeybord = true;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_SHOW);
}
}
if (mHasInit && mHasKeybord && mHeight == b) {
mHasKeybord = false;
if (mListener != null) {
mListener.onKeyBoardStateChange(KEYBOARD_STATE_HIDE);
}
// Log.w(TAG, "hide keyboard.......");
}
}
public interface onKeyboaddsChangeListener{
public void onKeyBoardStateChange(int state);
}
}
@@ -0,0 +1,131 @@
package cn.shangyu.gdxzExpert.view;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import cn.shangyu.gdxzExpert.R;
import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
public class MyDatePickerDialog extends DatePicker {
Context context;
public MyDatePickerDialog(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
this.context = context;
}
public MyDatePickerDialog(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
this.context = context;
}
public MyDatePickerDialog(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.context = context;
}
/**
*
* 设置时间选择器的分割线颜色
*
* @param datePicker
*/
private void setDatePickerDividerColor(DatePicker datePicker) {
// Divider changing:
// 获取 mSpinners
LinearLayout llFirst = (LinearLayout) datePicker.getChildAt(0);
// 获取 NumberPicker
LinearLayout mSpinners = (LinearLayout) llFirst.getChildAt(0);
for (int i = 0; i < mSpinners.getChildCount(); i++) {
NumberPicker picker = (NumberPicker) mSpinners.getChildAt(i);
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
pf.set(picker, new ColorDrawable(context.getResources()
.getColor(R.color.top_title)));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
}
}
/**
* 调整FrameLayout大小
*
* @param tp
*/
private void resizePikcer() {
List<NumberPicker> npList = findNumberPicker(this);
for (NumberPicker np : npList) {
resizeNumberPicker(np);
}
}
/**
* 得到viewGroup里面的numberpicker组件
*
* @param viewGroup
* @return
*/
private List<NumberPicker> findNumberPicker(ViewGroup viewGroup) {
List<NumberPicker> npList = new ArrayList<NumberPicker>();
View child = null;
if (null != viewGroup) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {
child = viewGroup.getChildAt(i);
if (child instanceof NumberPicker) {
npList.add((NumberPicker) child);
} else if (child instanceof LinearLayout) {
List<NumberPicker> result = findNumberPicker((ViewGroup) child);
if (result.size() > 0) {
return result;
}
}
}
}
return npList;
}
/*
* 调整numberpicker大小
*/
private void resizeNumberPicker(NumberPicker np) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
dip2px(context, 47), LayoutParams.WRAP_CONTENT);
params.setMargins(dip2px(context, 5), 0, dip2px(context, 5), 0);
np.setLayoutParams(params);
}
public static int dip2px(Context context, double d) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (d * scale + 0.5f);
}
}
@@ -0,0 +1,31 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.EditText;
public class MyEditext extends EditText {
public MyEditext(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyEditext(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyEditext(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
}
@@ -0,0 +1,33 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
/**
* 自定义gridview,解决ListView中嵌套gridview显示不正常的问题(1行半)
*
* @author wangyx
* @version 1.0.0 2012-9-14
*/
public class MyGridView extends GridView {
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
@@ -0,0 +1,39 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
public class MyLine extends ImageView {
public MyLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyLine(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyLine(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Path clipPath = new Path();
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(0, 0, w, h), 5.0f, 5.0f,
Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
@@ -0,0 +1,35 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ListView;
public class MyListView extends ListView {
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
// TODO Auto-generated method stub
// int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
// MeasureSpec.AT_MOST);
Log.d("gdxzbig",""+heightMeasureSpec+" ");
// super.onMeasure(widthMeasureSpec, expandSpec);
}
}
@@ -0,0 +1,24 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class MyScrollView extends ScrollView {
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyScrollView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
@@ -0,0 +1,45 @@
package cn.shangyu.gdxzExpert.view;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.widget.TextView;
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setSpecifiedTextsColor(String text, String specifiedTexts,
int color,SpannableStringBuilder styledText) {
List<Integer> sTextsStartList = new ArrayList<>();
int sTextLength = specifiedTexts.length();
String temp = text;
int lengthFront = 0;// 记录被找出后前面的字段的长度
int start = -1;
do {
start = temp.indexOf(specifiedTexts);
if (start != -1) {
start = start + lengthFront;
sTextsStartList.add(start);
lengthFront = start + sTextLength;
temp = text.substring(lengthFront);
}
} while (start != -1);
for (Integer i : sTextsStartList) {
styledText.setSpan(new ForegroundColorSpan(color), i, i
+ sTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(styledText);
}
}
@@ -0,0 +1,83 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import cn.shangyu.gdxzExpert.R;
import me.majiajie.pagerbottomtabstrip.item.BaseTabItem;
public class NormalItemView extends BaseTabItem {
TextView tv_title;
ImageView im_selector;
public NormalItemView(@NonNull Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.item_kejianna, this, true);
tv_title=findViewById(R.id.tv_title);
im_selector=findViewById(R.id.im_selector);
}
/**
* 方便初始化的方法
*
* @param title 标题
*/
public void initialize( String title) {
tv_title.setText(title);
}
@Override
public void setChecked(boolean checked) {
if (checked) {
tv_title.setTextColor(Color.parseColor("#ff000000"));
tv_title.setTextSize(17);
tv_title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
im_selector.setVisibility(VISIBLE);
} else {
tv_title.setTextColor(Color.parseColor("#ff666666"));
tv_title.setTextSize(14);
tv_title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
im_selector.setVisibility(GONE);
}
}
@Override
public void setMessageNumber(int number) {
}
@Override
public void setHasMessage(boolean hasMessage) {
}
@Override
public void setTitle(String title) {
tv_title.setText(title);
}
@Override
public void setDefaultDrawable(Drawable drawable) {
}
@Override
public void setSelectedDrawable(Drawable drawable) {
}
@Override
public String getTitle() {
return tv_title.getText().toString();
}
}
@@ -0,0 +1,84 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import cn.shangyu.gdxzExpert.R;
import me.majiajie.pagerbottomtabstrip.item.BaseTabItem;
public class NotNormalItemView extends BaseTabItem {
TextView tv_title;
ImageView im_selector;
public NotNormalItemView(@NonNull Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.item_zhazhi, this, true);
tv_title=findViewById(R.id.tv_title);
im_selector=findViewById(R.id.im_selector);
}
/**
* 方便初始化的方法
*
* @param title 标题
*/
public void initialize( String title) {
tv_title.setText(title);
}
@Override
public void setChecked(boolean checked) {
if (checked) {
tv_title.setTextColor(Color.parseColor("#ff000000"));
tv_title.setTextSize(20);
tv_title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
im_selector.setVisibility(VISIBLE);
} else {
tv_title.setTextColor(Color.parseColor("#ff666666"));
tv_title.setTextSize(16);
tv_title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
im_selector.setVisibility(GONE);
}
}
@Override
public void setMessageNumber(int number) {
}
@Override
public void setHasMessage(boolean hasMessage) {
}
@Override
public void setTitle(String title) {
tv_title.setText(title);
}
@Override
public void setDefaultDrawable(Drawable drawable) {
}
@Override
public void setSelectedDrawable(Drawable drawable) {
}
@Override
public String getTitle() {
return tv_title.getText().toString();
}
}
@@ -0,0 +1,64 @@
package cn.shangyu.gdxzExpert.view;
import cn.shangyu.gdxzExpert.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class PhotoGridItem extends RelativeLayout implements Checkable {
private Context mContext;
private boolean mCheck;
private ImageView mImageView;
private ImageView mSelect;
public PhotoGridItem(Context context) {
this(context, null, 0);
}
public PhotoGridItem(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PhotoGridItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
LayoutInflater.from(mContext).inflate(R.layout.photoalbum_gridview_item, this);
mImageView = (ImageView)findViewById(R.id.photo_img_view);
mSelect = (ImageView)findViewById(R.id.photo_select);
}
@Override
public void setChecked(boolean checked) {
mCheck = checked;
// mSelect.setImageDrawable(getResources().getDrawable(R.drawable.cb_on));
mSelect.setImageDrawable(checked ? getResources().getDrawable(R.drawable.cb_on) : getResources().getDrawable(R.drawable.cb_normal));
//mSelect.setVisibility(checked?View.VISIBLE:View.GONE);
}
@Override
public boolean isChecked() {
return mCheck;
}
@Override
public void toggle() {
setChecked(!mCheck);
}
public void setImgResID(int id){
if(mImageView != null){
mImageView.setBackgroundResource(id);
}
}
public void SetBitmap(Bitmap bit){
if(mImageView != null){
mImageView.setImageBitmap(bit);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,372 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.ArrayList;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import cn.shangyu.gdxzExpert.R;
import cn.shangyu.gdxzExpert.utils.ImageOptions;
import cn.shangyu.gdxzExpert.utils.LogUtil;
public class RollViewPager extends ViewPager {
private Context context;
private int currentItem = Integer.MAX_VALUE / 2;
private ArrayList<String> uriList;
private ArrayList<View> dots;
private TextView title;
private ArrayList<String> titles;
private int[] resImageIds;
private int dot_focus_resId;
private int dot_normal_resId;
private OnPagerClickCallback onPagerClickCallback;
private boolean isShowResImage = false;
MyOnTouchListener myOnTouchListener;
ViewPagerTask viewPagerTask;
private PagerAdapter pageradapter;
/** 触摸时按下的点 **/
PointF downP = new PointF();
/** 触摸时当前的点 **/
PointF curP = new PointF();
private int abc = 1;
private float mLastMotionX;
private float mLastMotionY;
private long start = 0;
public class MyOnTouchListener implements OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
curP.x = event.getX();
curP.y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
start = System.currentTimeMillis();
handler.removeCallbacksAndMessages(null);
// 记录按下时候的坐标
// 切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变
downP.x = event.getX();
downP.y = event.getY();
// 此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
// getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
handler.removeCallbacks(viewPagerTask);
LogUtil.i("ACTION_MOVE", (curP.x - downP.x) + "----"
+ (curP.y - downP.y));
/*
* if (Math.abs(curP.x - downP.x) > Math.abs(curP.y - downP.y)
* && (getCurrentItem() == 0 || getCurrentItem() == getAdapter()
* .getCount() - 1)) {
* getParent().requestDisallowInterceptTouchEvent(false); } else
* { getParent().requestDisallowInterceptTouchEvent(false); }
*/
// 此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
break;
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);
startRoll();
break;
case MotionEvent.ACTION_UP:
downP.x = event.getX();
downP.y = event.getY();
long duration = System.currentTimeMillis() - start;
if (duration <= 500 && downP.x == curP.x) {
currentItem %= uriList.size();
if (currentItem < 0) {
currentItem = uriList.size() + currentItem;
}
onPagerClickCallback.onPagerClick(currentItem);
} else {
onPagerClickCallback.onPagerClick(RollViewPager.this
.getCurrentItem());
}
startRoll();
break;
}
return true;
}
}
public boolean dispatchTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
abc = 1;
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
if (abc == 1) {
if (Math.abs(x - mLastMotionX) < Math.abs(y - mLastMotionY)) {
abc = 0;
getParent().requestDisallowInterceptTouchEvent(false);
} else {
getParent().requestDisallowInterceptTouchEvent(true);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.dispatchTouchEvent(ev);
}
public class ViewPagerTask implements Runnable {
@Override
public void run() {
// currentItem ++;
// LogUtil.i("getCurrentItem="+RollViewPager.this.getCurrentItem());
currentItem = RollViewPager.this.getCurrentItem() + 1;
// currentItem = (currentItem + 1)
// % (isShowResImage ? resImageIds.length : uriList.size());
handler.obtainMessage().sendToTarget();
// startRoll();
}
}
public Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
RollViewPager.this.setCurrentItem(currentItem);
startRoll();
}
};
public RollViewPager(Context context, ArrayList<View> dots,
int dot_focus_resId, int dot_normal_resId,
OnPagerClickCallback onPagerClickCallback) {
super(context);
this.currentItem = 0;
this.context = context;
this.dots = dots;
this.dot_focus_resId = dot_focus_resId;
this.dot_normal_resId = dot_normal_resId;
this.onPagerClickCallback = onPagerClickCallback;
viewPagerTask = new ViewPagerTask();
myOnTouchListener = new MyOnTouchListener();
}
public void setUriList(ArrayList<String> uriList) {
isShowResImage = false;
this.uriList = uriList;
}
public void notifyDataChange() {
pageradapter.notifyDataSetChanged();
}
public ArrayList<View> getDots() {
return dots;
}
public void setDots(ArrayList<View> dots) {
this.dots = dots;
}
public void setResImageIds(int[] resImageIds) {
isShowResImage = true;
this.resImageIds = resImageIds;
}
public void setTitle(TextView title, ArrayList<String> titles) {
this.title = title;
this.titles = titles;
if (title != null && titles != null && titles.size() > 0)
title.setText(titles.get(0));//
}
private boolean hasSetAdapter = false;
/**
*
*/
public void startRoll() {
handler.removeCallbacksAndMessages(null);
if (!hasSetAdapter) {
hasSetAdapter = true;
pageradapter = new ViewPagerAdapter();
this.setAdapter(pageradapter);
// RollViewPager.this.setCurrentItem(Integer.MAX_VALUE/2 -
// (Integer.MAX_VALUE/2%uriList.size()));
// LogUtil.i("vvvvvvvvv="+(Integer.MAX_VALUE/2 -
// (Integer.MAX_VALUE/2%uriList.size())));
this.setOnPageChangeListener(new MyOnPageChangeListener());
isRunning = true;
}
// LogUtil.i("sssss="+currentItem);
// if (isRunning) {
handler.postDelayed(viewPagerTask, 5000);
// }
}
private boolean isRunning = false;
public boolean isRunning() {
return isRunning;
}
public void setRunning(boolean isRunning) {
LogUtil.i("isRunning==" + isRunning);
this.isRunning = isRunning;
}
class MyOnPageChangeListener implements OnPageChangeListener {
int oldPosition = 0;
@Override
public void onPageSelected(int position) {
// **********
currentItem = position;
position %= uriList.size();
if (position < 0) {
position = uriList.size() + position;
}
if (title != null)
title.setText(titles.get(position));
if (dots != null && dots.size() > 0) {
dots.get(oldPosition).setBackgroundResource(dot_normal_resId);
dots.get(position).setBackgroundResource(dot_focus_resId);
}
oldPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
}
class ViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
// return isShowResImage ? resImageIds.length : uriList.size();
// 设置成最大,使用户看不到边界
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(View container, int position) {
// 对ViewPager页号求模取出View列表中要显示的项
position %= uriList.size();
if (position < 0) {
position = uriList.size() + position;
}
View view = View.inflate(context, R.layout.viewpager_item, null);
// 如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。
ViewParent vp = view.getParent();
if (vp != null) {
ViewGroup parent = (ViewGroup) vp;
parent.removeView(view);
}
((ViewPager) container).addView(view);
view.setOnTouchListener(myOnTouchListener);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
if (isShowResImage) {
imageView.setImageResource(resImageIds[position]);
} else {
if (!TextUtils.isEmpty(uriList.get(position))) {
// 显示图片的配置
// DisplayImageOptions options = new
// DisplayImageOptions.Builder()
// .showImageOnLoading(R.drawable.home_scroll_default)
// .showImageOnFail(R.drawable.home_scroll_default)
// .showImageForEmptyUri(R.drawable.home_scroll_default)
// //加载失败的图片
// .cacheInMemory(true)
// .cacheOnDisk(true)
// .bitmapConfig(Bitmap.Config.RGB_565)
// .build();
ImageLoader.getInstance().displayImage(uriList.get(position),imageView,ImageOptions.getImageOptions(R.drawable.home_scroll_default));
}
}
return view;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
// Warning:不要在这里调用removeView
}
@Override
public void finishUpdate(View arg0) {
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View arg0) {
}
}
// @Override
// protected void onAttachedToWindow() {
// // TODO Auto-generated method stub
// super.onAttachedToWindow();
// }
// @Override
// protected void onDetachedFromWindow() {
// handler.removeCallbacksAndMessages(null);
// super.onDetachedFromWindow();
// }
public void stopRunning() {
if (viewPagerTask != null) {
handler.removeCallbacks(viewPagerTask);
handler.removeCallbacksAndMessages(null);
}
}
public interface OnPagerClickCallback {
public abstract void onPagerClick(int position);
}
}
@@ -0,0 +1,67 @@
package cn.shangyu.gdxzExpert.view;
import android.util.Log;
import android.view.MotionEvent;
/**
* Created by q2366 on 2015/10/12.
*/
public class RotateGestureDetector {
private static final int MAX_DEGREES_STEP = 120;
private OnRotateListener mListener;
private float mPrevSlope;
private float mCurrSlope;
private float x1;
private float y1;
private float x2;
private float y2;
public RotateGestureDetector(OnRotateListener l) {
mListener = l;
}
public void onTouchEvent(MotionEvent event) {
final int Action = event.getActionMasked();
switch (Action) {
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerCount() == 2) mPrevSlope = caculateSlope(event);
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() > 1) {
mCurrSlope = caculateSlope(event);
double currDegrees = Math.toDegrees(Math.atan(mCurrSlope));
double prevDegrees = Math.toDegrees(Math.atan(mPrevSlope));
double deltaSlope = currDegrees - prevDegrees;
if (Math.abs(deltaSlope) <= MAX_DEGREES_STEP) {
mListener.onRotate((float) deltaSlope, (x2 + x1) / 2, (y2 + y1) / 2);
}
mPrevSlope = mCurrSlope;
}
break;
default:
break;
}
}
private float caculateSlope(MotionEvent event) {
x1 = event.getX(0);
y1 = event.getY(0);
x2 = event.getX(1);
y2 = event.getY(1);
return (y2 - y1) / (x2 - x1);
}
}
interface OnRotateListener {
void onRotate(float degrees, float focusX, float focusY);
}
@@ -0,0 +1,38 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RoundImageView extends ImageView {
public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public RoundImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Path clipPath = new Path();
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(0, 0, w, h), 10.0f, 10.0f,
Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
@@ -0,0 +1,29 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
/**
* Created by wangchengxin on 2019/8/8.
*/
public class ScollViewGridView extends GridView {
public ScollViewGridView(Context context) {
super(context);
}
public ScollViewGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScollViewGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
@@ -0,0 +1,29 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* Created by wangchengxin on 2019/8/8.
*/
public class ScollViewListView extends ListView {
public ScollViewListView(Context context) {
super(context);
}
public ScollViewListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScollViewListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
@@ -0,0 +1,51 @@
package cn.shangyu.gdxzExpert.view;
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import static cn.shangyu.gdxzExpert.utils.DensityUtil.dip2px;
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
int mSpace;
int mSpacebottom;
/**
* Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies
* the number of pixels that the item view should be inset by, similar to padding or margin.
* The default implementation sets the bounds of outRect to 0 and returns.
* <p>
* <p>
* If this ItemDecoration does not affect the positioning of item views, it should set
* all four fields of <code>outRect</code> (left, top, right, bottom) to zero
* before returning.
* <p>
* <p>
* If you need to access Adapter for additional data, you can call
* {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the
* View.
*
* @param outRect Rect to receive the output.
* @param view The child view to decorate
* @param parent RecyclerView this ItemDecoration is decorating
* @param state The current state of RecyclerView.
*/
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.left = mSpace;
// outRect.right = mSpace;
outRect.bottom = mSpacebottom;
// if (parent.getChildAdapterPosition(view) == 0) {
// outRect.top = mSpace;
// }
}
public SpaceItemDecoration(int space,int mSpacebottom) {
this.mSpace = dip2px(space);
this.mSpacebottom=dip2px(mSpacebottom);
}
}
@@ -0,0 +1,46 @@
package cn.shangyu.gdxzExpert.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;
//四个圆角imageview
public class TwoRoundImageView extends ImageView {
/* 圆角的半径,依次为左上角xy半径,右上角,右下角,左下角 */
private float[] rids = { 12.0f, 12.0f, 12.0f, 12.0f, 0.0f, 0.0f, 0.0f,
0.0f, };
public TwoRoundImageView(Context context) {
super(context);
}
public TwoRoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TwoRoundImageView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 画图 by Hankkin at:2015-08-30 21:15:53
*
* @param canvas
*/
protected void onDraw(Canvas canvas) {
Path path = new Path();
int w = this.getWidth();
int h = this.getHeight();
/* 向路径中添加圆角矩形。radii数组定义圆角矩形的四个圆角的x,y半径。radii长度必须为8 */
path.addRoundRect(new RectF(0, 0, w, h), rids, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
}
@@ -0,0 +1,90 @@
package cn.shangyu.gdxzExpert.view;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
*
* 名字为X5实际上是原生自定义
* 方便Webview设置管理
*/
public class X5WebView extends WebView {
private WebViewClient client = new WebViewClient() {
/**
* 防止加载网页时调起系统浏览器
*/
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
};
@SuppressLint("SetJavaScriptEnabled")
public X5WebView(Context arg0, AttributeSet arg1) {
super(arg0, arg1);
this.setWebViewClient(client);
// this.setWebChromeClient(chromeClient);
// WebStorage webStorage = WebStorage.getInstance();
initWebViewSettings();
this.setClickable(true);
}
private void initWebViewSettings() {
CookieSyncManager.createInstance(getContext());
CookieManager.getInstance().removeAllCookie();
WebSettings webSetting = this.getSettings();
webSetting.setJavaScriptEnabled(true);
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
webSetting.setAllowFileAccess(true);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSetting.setSupportZoom(true);
webSetting.setBuiltInZoomControls(true);
webSetting.setUseWideViewPort(true);
webSetting.setSupportMultipleWindows(true);
webSetting.setLoadWithOverviewMode(true);
// webSetting.setAppCacheEnabled(true); // 已弃用,在 Android API 33+ 中移除
// webSetting.setDatabaseEnabled(true);
webSetting.setDomStorageEnabled(true);
webSetting.setGeolocationEnabled(true);
// webSetting.setAppCacheMaxSize(Long.MAX_VALUE); // 已弃用,在 Android API 33+ 中移除
// webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
// webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);
webSetting.setBlockNetworkImage(false); // 解决图片不显示
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
webSetting.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
// this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
// settings 的设计
}
public X5WebView(Context arg0) {
super(arg0);
setBackgroundColor(85621);
}
/**
* 启用硬件加速
*/
public static void initHardwareAccelerate(Activity context) {
try {
if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
context.getWindow()
.setFlags(
android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
} catch (Exception e) {
}
}
}
@@ -0,0 +1,19 @@
package cn.shangyu.gdxzExpert.view.pullable;
public interface Pullable
{
/**
* 判断是否可以下拉,如果不需要下拉功能可以直接return false
*
* @return true如果可以下拉否则返回false
*/
boolean canPullDown();
/**
* 判断是否可以上拉,如果不需要上拉功能可以直接return false
*
* @return true如果可以上拉否则返回false
*/
boolean canPullUp();
}
@@ -0,0 +1,85 @@
package cn.shangyu.gdxzExpert.view.pullable;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class PullableScrollView extends ScrollView implements Pullable
{
public PullableScrollView(Context context)
{
super(context);
}
public PullableScrollView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PullableScrollView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public boolean canPullDown()
{
if (getScrollY() == 0)
return true;
else
return false;
}
@Override
public boolean canPullUp()
{
if (getScrollY() >= (getChildAt(0).getHeight() - getMeasuredHeight()))
return true;
else
return false;
}
// Edge-effects don't mix well with the translucent action bar in Android 2.X
private boolean mDisableEdgeEffects = true;
/**
* @author Cyril Mottier
*/
public interface OnScrollChangedListener {
void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt);
}
private OnScrollChangedListener mOnScrollChangedListener;
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mOnScrollChangedListener != null) {
mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
}
}
public void setOnScrollChangedListener(OnScrollChangedListener listener) {
mOnScrollChangedListener = listener;
}
@Override
protected float getTopFadingEdgeStrength() {
// http://stackoverflow.com/a/6894270/244576
if (mDisableEdgeEffects && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 0.0f;
}
return super.getTopFadingEdgeStrength();
}
@Override
protected float getBottomFadingEdgeStrength() {
// http://stackoverflow.com/a/6894270/244576
if (mDisableEdgeEffects && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 0.0f;
}
return super.getBottomFadingEdgeStrength();
}
}
@@ -0,0 +1,472 @@
package cn.shangyu.gdxzExpert.view.viewbadger;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TabWidget;
import android.widget.TextView;
/**
* A simple text label view that can be applied as a "badge" to any given {@link View}.
* This class is intended to be instantiated at runtime rather than included in XML layouts.
*
* @author Jeff Gilfelt
*/
public class BadgeView extends TextView {
public static final int POSITION_TOP_LEFT = 1;
public static final int POSITION_TOP_RIGHT = 2;
public static final int POSITION_BOTTOM_LEFT = 3;
public static final int POSITION_BOTTOM_RIGHT = 4;
public static final int POSITION_CENTER = 5;
public static final int POSITION_RED_RIGHT = 9;
private static final int DEFAULT_MARGIN_DIP = 5;
private static final int DEFAULT_LR_PADDING_DIP = 5;
private static final int DEFAULT_CORNER_RADIUS_DIP = 8;
private static final int DEFAULT_POSITION = POSITION_TOP_RIGHT;
private static final int DEFAULT_BADGE_COLOR = Color.parseColor("#CCFF0000"); //Color.RED;
private static final int DEFAULT_TEXT_COLOR = Color.WHITE;
private static Animation fadeIn;
private static Animation fadeOut;
private Context context;
private View target;
private int badgePosition;
private int badgeMarginH;
private int badgeMarginV;
private int badgeColor;
private boolean isShown;
private ShapeDrawable badgeBg;
private int targetTabIndex;
public BadgeView(Context context) {
this(context, (AttributeSet) null, android.R.attr.textViewStyle);
}
public BadgeView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
/**
* Constructor -
*
* create a new BadgeView instance attached to a target {@link View}.
*
* @param context context for this view.
* @param target the View to attach the badge to.
*/
public BadgeView(Context context, View target) {
this(context, null, android.R.attr.textViewStyle, target, 0);
}
/**
* Constructor -
*
* create a new BadgeView instance attached to a target {@link TabWidget}
* tab at a given index.
*
* @param context context for this view.
* @param target the TabWidget to attach the badge to.
* @param index the position of the tab within the target.
*/
public BadgeView(Context context, TabWidget target, int index) {
this(context, null, android.R.attr.textViewStyle, target, index);
}
public BadgeView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs, defStyle, null, 0);
}
public BadgeView(Context context, AttributeSet attrs, int defStyle, View target, int tabIndex) {
super(context, attrs, defStyle);
init(context, target, tabIndex);
}
private void init(Context context, View target, int tabIndex) {
this.context = context;
this.target = target;
this.targetTabIndex = tabIndex;
// apply defaults
badgePosition = DEFAULT_POSITION;
badgeMarginH = dipToPixels(DEFAULT_MARGIN_DIP);
badgeMarginV = badgeMarginH;
badgeColor = DEFAULT_BADGE_COLOR;
setTypeface(Typeface.DEFAULT_BOLD);
int paddingPixels = dipToPixels(DEFAULT_LR_PADDING_DIP);
setPadding(paddingPixels, 0, paddingPixels, 0);
setTextColor(DEFAULT_TEXT_COLOR);
fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(200);
fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(200);
isShown = false;
if (this.target != null) {
applyTo(this.target);
} else {
show();
}
}
private void applyTo(View target) {
LayoutParams lp = target.getLayoutParams();
ViewParent parent = target.getParent();
FrameLayout container = new FrameLayout(context);
if (target instanceof TabWidget) {
// set target to the relevant tab child container
target = ((TabWidget) target).getChildTabViewAt(targetTabIndex);
this.target = target;
((ViewGroup) target).addView(container,
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
this.setVisibility(View.GONE);
container.addView(this);
} else {
// TODO verify that parent is indeed a ViewGroup
ViewGroup group = (ViewGroup) parent;
int index = group.indexOfChild(target);
group.removeView(target);
group.addView(container, index, lp);
container.addView(target);
this.setVisibility(View.GONE);
container.addView(this);
group.invalidate();
}
}
/**
* Make the badge visible in the UI.
*
*/
public void show() {
show(false, null);
}
/**
* Make the badge visible in the UI.
*
* @param animate flag to apply the default fade-in animation.
*/
public void show(boolean animate) {
show(animate, fadeIn);
}
/**
* Make the badge visible in the UI.
*
* @param anim Animation to apply to the view when made visible.
*/
public void show(Animation anim) {
show(true, anim);
}
/**
* Make the badge non-visible in the UI.
*
*/
public void hide() {
hide(false, null);
}
/**
* Make the badge non-visible in the UI.
*
* @param animate flag to apply the default fade-out animation.
*/
public void hide(boolean animate) {
hide(animate, fadeOut);
}
/**
* Make the badge non-visible in the UI.
*
* @param anim Animation to apply to the view when made non-visible.
*/
public void hide(Animation anim) {
hide(true, anim);
}
/**
* Toggle the badge visibility in the UI.
*
*/
public void toggle() {
toggle(false, null, null);
}
/**
* Toggle the badge visibility in the UI.
*
* @param animate flag to apply the default fade-in/out animation.
*/
public void toggle(boolean animate) {
toggle(animate, fadeIn, fadeOut);
}
/**
* Toggle the badge visibility in the UI.
*
* @param animIn Animation to apply to the view when made visible.
* @param animOut Animation to apply to the view when made non-visible.
*/
public void toggle(Animation animIn, Animation animOut) {
toggle(true, animIn, animOut);
}
private void show(boolean animate, Animation anim) {
if (getBackground() == null) {
if (badgeBg == null) {
badgeBg = getDefaultBackground();
}
setBackgroundDrawable(badgeBg);
}
applyLayoutParams();
if (animate) {
this.startAnimation(anim);
}
this.setVisibility(View.VISIBLE);
isShown = true;
}
private void hide(boolean animate, Animation anim) {
this.setVisibility(View.GONE);
if (animate) {
this.startAnimation(anim);
}
isShown = false;
}
private void toggle(boolean animate, Animation animIn, Animation animOut) {
if (isShown) {
hide(animate && (animOut != null), animOut);
} else {
show(animate && (animIn != null), animIn);
}
}
/**
* Increment the numeric badge label. If the current badge label cannot be converted to
* an integer value, its label will be set to "0".
*
* @param offset the increment offset.
*/
public int increment(int offset) {
CharSequence txt = getText();
int i;
if (txt != null) {
try {
i = Integer.parseInt(txt.toString());
} catch (NumberFormatException e) {
i = 0;
}
} else {
i = 0;
}
i = i + offset;
setText(String.valueOf(i));
return i;
}
/**
* Decrement the numeric badge label. If the current badge label cannot be converted to
* an integer value, its label will be set to "0".
*
* @param offset the decrement offset.
*/
public int decrement(int offset) {
return increment(-offset);
}
private ShapeDrawable getDefaultBackground() {
int r = dipToPixels(DEFAULT_CORNER_RADIUS_DIP);
float[] outerR = new float[] {r, r, r, r, r, r, r, r};
RoundRectShape rr = new RoundRectShape(outerR, null, null);
ShapeDrawable drawable = new ShapeDrawable(rr);
drawable.getPaint().setColor(badgeColor);
return drawable;
}
private void applyLayoutParams() {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
switch (badgePosition) {
case POSITION_TOP_LEFT:
lp.gravity = Gravity.LEFT | Gravity.TOP;
lp.setMargins(badgeMarginH, badgeMarginV, 0, 0);
break;
case POSITION_TOP_RIGHT:
lp.gravity = Gravity.RIGHT | Gravity.TOP;
lp.setMargins(0, badgeMarginV, badgeMarginH, 0);
break;
case POSITION_RED_RIGHT:
lp.gravity = Gravity.RIGHT | Gravity.TOP;
lp.setMargins(0, badgeMarginV, -badgeMarginH, 0);
break;
case POSITION_BOTTOM_LEFT:
lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
lp.setMargins(badgeMarginH, 0, 0, badgeMarginV);
break;
case POSITION_BOTTOM_RIGHT:
lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
lp.setMargins(0, 0, badgeMarginH, badgeMarginV);
break;
case POSITION_CENTER:
lp.gravity = Gravity.CENTER;
lp.setMargins(0, 0, 0, 0);
break;
default:
break;
}
setLayoutParams(lp);
}
/**
* Returns the target View this badge has been attached to.
*
*/
public View getTarget() {
return target;
}
/**
* Is this badge currently visible in the UI?
*
*/
@Override
public boolean isShown() {
return isShown;
}
/**
* Returns the positioning of this badge.
*
* one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT, POSTION_CENTER.
*
*/
public int getBadgePosition() {
return badgePosition;
}
/**
* Set the positioning of this badge.
*
* @param layoutPosition one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT, POSTION_CENTER.
*
*/
public void setBadgePosition(int layoutPosition) {
this.badgePosition = layoutPosition;
}
/**
* Returns the horizontal margin from the target View that is applied to this badge.
*
*/
public int getHorizontalBadgeMargin() {
return badgeMarginH;
}
/**
* Returns the vertical margin from the target View that is applied to this badge.
*
*/
public int getVerticalBadgeMargin() {
return badgeMarginV;
}
/**
* Set the horizontal/vertical margin from the target View that is applied to this badge.
*
* @param badgeMargin the margin in pixels.
*/
public void setBadgeMargin(int badgeMargin) {
this.badgeMarginH = badgeMargin;
this.badgeMarginV = badgeMargin;
}
/**
* Set the horizontal/vertical margin from the target View that is applied to this badge.
*
* @param horizontal margin in pixels.
* @param vertical margin in pixels.
*/
public void setBadgeMargin(int horizontal, int vertical) {
this.badgeMarginH = horizontal;
this.badgeMarginV = vertical;
}
/**
* Returns the color value of the badge background.
*
*/
public int getBadgeBackgroundColor() {
return badgeColor;
}
/**
* Set the color value of the badge background.
*
* @param badgeColor the badge background color.
*/
public void setBadgeBackgroundColor(int badgeColor) {
this.badgeColor = badgeColor;
badgeBg = getDefaultBackground();
}
private int dipToPixels(int dip) {
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, r.getDisplayMetrics());
return (int) px;
}
}