實用小技巧(持續更新)
阿新 • • 發佈:2019-01-09
掃描Activity
public static Activity scanForActivity(Context ctx) {
if (ctx == null)
return null;
else if (ctx instanceof Activity)
return (Activity) ctx;
else if (ctx instanceof ContextWrapper)
return scanForActivity(((ContextWrapper) ctx).getBaseContext());
return null;
}
一般用於在Dialog中show的時候判斷Activity的引用是否有效,例如:
@Override
public void show() {
Activity activity = UIUtils.scanForActivity(getContext());
if (null != activity && !activity.isFinishing())
super.show();
}
給drawableRight設定點選事件
例如EditText右側有一個刪除按鈕是通過drawableRight屬性設定的,此時如果想讓其響應點選事件,這可以通過判斷點選的座標位置與刪除按鈕的位置對比,下面是通過處理點選刪除按鈕刪除EditText框的內容
/**
* 給EditText的右側drawableRight屬性的圖片設定點選事件
*
* @param editText
*/
public static void registerEditRightDrawableClickListener(final EditText editText) {
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// et.getCompoundDrawables()得到一個長度為4的陣列,分別表示左上右下四張圖片
Drawable drawable = editText.getCompoundDrawables()[2];
//如果右邊沒有圖片,不再處理
if (drawable == null)
return false;
//如果不是按下事件,不再處理
if (event.getAction() != MotionEvent.ACTION_UP)
return false;
if (event.getX() > editText.getWidth() - editText.getPaddingRight() - drawable.getIntrinsicWidth()) {
editText.setText("");
return true;
}
return false;
}
});
}
限制EditText可輸入的字數,超出後提示文案
/**
* 限制EditText可輸入的字數,超出後提示文案
*
* @param editText 目標view
* @param maxLength 最大字數
* @param msg 提示文案
* @param callback 回撥介面
*/
public static void registerEditMaxTextShow(final EditText editText, final int maxLength, final String msg, final Callback callback) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String currMsg = editText.getText().toString().trim();
if (null != callback) callback.onEditTextChange(currMsg);
if (currMsg.length() > maxLength) {
ToastUtils.showShort(msg);
int editStart = editText.getSelectionStart();
int editEnd = editText.getSelectionEnd();
s.delete(editStart - 1, editEnd);
String finalMsg = s.toString();
editText.removeTextChangedListener(this);
editText.setText(finalMsg);
editText.setSelection(finalMsg.length());
if (null != callback) callback.onEditTextChange(finalMsg);
editText.addTextChangedListener(this);
}
}
});
}
//回撥介面
public interface Callback {
void onEditTextChange(String msg);
}
解決RecycleView佈局中GridLayoutManager和StaggeredGridLayoutManager新增頭部和底部不佔用一行的問題
重寫RecyclerView.Adapter的2個方法
/**
* 解決GridLayoutManager新增頭部和底部不佔用一行的問題
*
* @param recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (isHeaderViewPosition(position) || isFooterViewPosition(position))
? gridManager.getSpanCount() : 1;
}
});
}
mAdapter.onAttachedToRecyclerView(recyclerView);
}
/**
* 解決StaggeredGridLayoutManager新增頭部和底部不佔用一行的問題
*
* @param holder
*/
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
int position = holder.getLayoutPosition();
if (lp != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& (isHeaderViewPosition(position) || isFooterViewPosition(position))) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
mAdapter.onViewAttachedToWindow(holder);
}
重寫RecycleView的setLayoutManager方法
/**
* 解決GridLayoutManager新增頭部和底部不佔用一行的問題
*
* @param layout
*/
@Override
public void setLayoutManager(LayoutManager layout) {
super.setLayoutManager(layout);
if (mWrapAdapter != null) {
if (layout instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) layout);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (mWrapAdapter.isHeaderViewPosition(position) || mWrapAdapter.isFooterViewPosition(position))
? gridManager.getSpanCount() : 1;
}
});
}
}
}
解決由於RecyclerView有重新整理頭存在,導致canScrollVertically(-1)時始終返回true的bug
@Override
public boolean canScrollVertically(int direction) {
if (direction < 1) {
boolean original = super.canScrollVertically(direction);
if (!original || getChildAt(0) != null && getChildAt(0).getTop() >= 0) {
return false;
} else {
return true;
}
}
return super.canScrollVertically(direction);
}
獲取RecycleView第一個和最後一個可見Item的位置
/**
* 獲取第一個可見的item位置
* @return
*/
public int getFirstVisiablePosition() {
LayoutManager layoutManager = getLayoutManager();
int firstVisibleItemPosition;
if (layoutManager instanceof GridLayoutManager) {
firstVisibleItemPosition = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(into);
firstVisibleItemPosition = findMin(into);
} else {
firstVisibleItemPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
}
return firstVisibleItemPosition;
}
/**
* 獲取可見列表內最後一個item的位置
*
* @return
*/
public int getLastVisibleItemPosition() {
int lastVisibleItemPosition;
LayoutManager layoutManager = getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);
lastVisibleItemPosition = findMax(into);
} else {
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
}
return lastVisibleItemPosition;
}
private int findMin(int[] firstPositions) {
int min = firstPositions[0];
for (int value : firstPositions) {
if (value < min) {
min = value;
}
}
return min;
}
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
for (int value : lastPositions) {
if (value > max) {
max = value;
}
}
return max;
}
修改RadioButton的drawableRight圖片與文字相隔的距離太大,導致drawablePadding設定無效
重寫AppCompatRadioButton的onDraw方法
@Override
protected void onDraw(Canvas canvas) {
//得到Drawable集合 分別對應 左上右下
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
//獲取右邊圖片,修改drawableRight的圖片緊貼著文字
Drawable drawableRight = drawables[2];
if (drawableRight != null) {
//獲取文字佔用長寬
int textWidth = (int) getPaint().measureText(getText().toString());
int textHeight = (int) getPaint().getTextSize();
//獲取圖片實際長寬
int drawableWidth = drawableRight.getIntrinsicWidth();
int drawableHeight = drawableRight.getIntrinsicHeight();
//setBounds修改Drawable在View所佔的位置和大小,對應引數同樣的 左上右下()
int bodyWidth = textWidth + drawableWidth + getCompoundDrawablePadding();
int left = (bodyWidth - getWidth()) / 2;
int right = left + drawableWidth;
drawableRight.setBounds(left, 0, right, drawableHeight);
}
}
super.onDraw(canvas);
}
解決RadioButton無法重複點選取消選中的狀態
重寫AppCompatRadioButton的toggle方法
@Override
public void toggle() {
setChecked(!isChecked());
if (!isChecked()) {
if (null != getParent() && getParent() instanceof RadioGroup)
((RadioGroup) getParent()).clearCheck();
}
}
解決手動設定Switch的setChecked方法導致setOnCheckedChangeListener觸發響應
mPushSwt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isPressed()) { //避免程式碼設定setChecked狀態導致回撥監聽
//do sth...
}
}
});
避免SwipeRefreshLayout重複下拉導致重新整理按鈕異常顯示
重寫SwipeRefreshLayout的onStartNestedScroll方法
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
//避免重複下拉重新整理導致動畫異常
return !isRefreshing() && super.onStartNestedScroll(child, target, nestedScrollAxes);
}
更新於2019-01-03
TextView的drawableLeft與文字無法一起居中顯示
TextView設定的文字預設是存在一個上下間距的,也就是上下空白,當我們在使用drawableLeft的時候,這個預設的空白會使TextView中的文字向下偏移,當你的drawableLeft使用的icon很小,文字的size也很小的時候,即使你設定了android:gravity=“center”,也能很明顯的看到你的TextView中的文字基本上是與icon處於底邊對其,而不是居中對其
只要TextView中加上android:includeFontPadding=“false” 這個屬性屬性就可以了!