实用小技巧(持续更新)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mChenys/article/details/85707203

扫描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” 这个属性属性就可以了!


更新于2019-01-08

猜你喜欢

转载自blog.csdn.net/mChenys/article/details/85707203