当前位置: 首页 > news >正文

人像写真哔哩哔哩win10优化大师官网

人像写真哔哩哔哩,win10优化大师官网,扁平化中文网站模板下载,住房和城乡建设部网站公布信息文章目录 前言一、效果图二、实现步骤1.OnSelectListener2.SelectionInfo类3.TextLayoutUtil类4.复制弹框的xml布局5.弹框背景Drawable6.倒三角Drawable7.复制工具类8.调用 总结 前言 根据时代进步,那些干产品的也叼砖起来了,今天就遇到一个需求&#x…

文章目录

  • 前言
  • 一、效果图
  • 二、实现步骤
    • 1.OnSelectListener
    • 2.SelectionInfo类
    • 3.TextLayoutUtil类
    • 4.复制弹框的xml布局
    • 5.弹框背景Drawable
    • 6.倒三角Drawable
    • 7.复制工具类
    • 8.调用
  • 总结


前言

根据时代进步,那些干产品的也叼砖起来了,今天就遇到一个需求,需要对TextView的文案进行自由选择复制,不怕,我们是勇敢牛牛。


一、效果图

在这里插入图片描述

二、实现步骤

1.OnSelectListener

public interface OnSelectListener {void onTextSelected(CharSequence content);
}

2.SelectionInfo类

代码如下(示例):

public class SelectionInfo {public int mStart;public int mEnd;public String mSelectionContent;
}

3.TextLayoutUtil类

package com.example.merchant.utils;import android.content.Context;
import android.text.Layout;
import android.widget.TextView;public class TextLayoutUtil {public static int getScreenWidth(Context context) {return context.getResources().getDisplayMetrics().widthPixels;}public static int getPreciseOffset(TextView textView, int x, int y) {Layout layout = textView.getLayout();if (layout != null) {int topVisibleLine = layout.getLineForVertical(y);int offset = layout.getOffsetForHorizontal(topVisibleLine, x);int offsetX = (int) layout.getPrimaryHorizontal(offset);if (offsetX > x) {return layout.getOffsetToLeftOf(offset);} else {return offset;}} else {return -1;}}public static int getHysteresisOffset(TextView textView, int x, int y, int previousOffset) {final Layout layout = textView.getLayout();if (layout == null) return -1;int line = layout.getLineForVertical(y);if (isEndOfLineOffset(layout, previousOffset)) {// we have to minus one from the offset so that the code below to find// the previous line can work correctly.int left = (int) layout.getPrimaryHorizontal(previousOffset - 1);int right = (int) layout.getLineRight(line);int threshold = (right - left) / 2; // half the width of the last characterif (x > right - threshold) {previousOffset -= 1;}}final int previousLine = layout.getLineForOffset(previousOffset);final int previousLineTop = layout.getLineTop(previousLine);final int previousLineBottom = layout.getLineBottom(previousLine);final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2;if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) || ((line == previousLine - 1) && ((previousLineTop- y) < hysteresisThreshold))) {line = previousLine;}int offset = layout.getOffsetForHorizontal(line, x);if (offset < textView.getText().length() - 1) {if (isEndOfLineOffset(layout, offset + 1)) {int left = (int) layout.getPrimaryHorizontal(offset);int right = (int) layout.getLineRight(line);int threshold = (right - left) / 2; // half the width of the last characterif (x > right - threshold) {offset += 1;}}}return offset;}private static boolean isEndOfLineOffset(Layout layout, int offset) {return offset > 0 && layout.getLineForOffset(offset) == layout.getLineForOffset(offset - 1) + 1;}public static int dp2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}
}

4.复制弹框的xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/linearLayout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/bg_operate_window"android:orientation="horizontal"android:paddingLeft="5dp"android:paddingRight="5dp"><TextViewandroid:id="@+id/tv_copy"style="@style/OperateTextView"android:text="@string/Copy" /><TextViewandroid:id="@+id/tv_select_all"style="@style/OperateTextView"android:text="@string/SelectAll" /></LinearLayout><ImageViewandroid:id="@+id/iv_triangle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/linearLayout"android:layout_centerHorizontal="true"android:src="@drawable/triangle_down" />
</RelativeLayout>

5.弹框背景Drawable

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><corners android:radius="5dp" /><solid android:color="#454545" /></shape>

6.倒三角Drawable

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item><rotateandroid:fromDegrees="45"android:pivotX="135%"android:pivotY="15%"><shape android:shape="rectangle"><sizeandroid:width="16dp"android:height="16dp" /><solid android:color="#454545" /></shape></rotate></item>
</layer-list>

7.复制工具类

package com.example.merchant.utils;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.text.Layout;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.PopupWindow;
import android.widget.TextView;import androidx.annotation.ColorInt;import com.example.merchant.R;/*** 复制utils*/
public class SelectableTextHelper {private final static int DEFAULT_SELECTION_LENGTH = 1;private static final int DEFAULT_SHOW_DURATION = 100;private CursorHandle mStartHandle;private CursorHandle mEndHandle;private OperateWindow mOperateWindow;private SelectionInfo mSelectionInfo = new SelectionInfo();private OnSelectListener mSelectListener;private Context mContext;private TextView mTextView;private Spannable mSpannable;private int mTouchX;private int mTouchY;private int mSelectedColor;private int mCursorHandleColor;private int mCursorHandleSize;private BackgroundColorSpan mSpan;private boolean isHideWhenScroll;private boolean isHide = true;private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener;ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener;public SelectableTextHelper(Builder builder) {mTextView = builder.mTextView;mContext = mTextView.getContext();mSelectedColor = builder.mSelectedColor;mCursorHandleColor = builder.mCursorHandleColor;mCursorHandleSize = TextLayoutUtil.dp2px(mContext, builder.mCursorHandleSizeInDp);init();}private void init() {mTextView.setText(mTextView.getText(), TextView.BufferType.SPANNABLE);mTextView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {showSelectView(mTouchX, mTouchY);return true;}});mTextView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {mTouchX = (int) event.getX();mTouchY = (int) event.getY();return false;}});mTextView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {resetSelectionInfo();hideSelectView();}});mTextView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {}@Overridepublic void onViewDetachedFromWindow(View v) {destroy();}});mOnPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {if (isHideWhenScroll) {isHideWhenScroll = false;postShowSelectView(DEFAULT_SHOW_DURATION);}return true;}};mTextView.getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);mOnScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {@Overridepublic void onScrollChanged() {if (!isHideWhenScroll && !isHide) {isHideWhenScroll = true;if (mOperateWindow != null) {mOperateWindow.dismiss();}if (mStartHandle != null) {mStartHandle.dismiss();}if (mEndHandle != null) {mEndHandle.dismiss();}}}};mTextView.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener);mOperateWindow = new OperateWindow(mContext);}private void postShowSelectView(int duration) {mTextView.removeCallbacks(mShowSelectViewRunnable);if (duration <= 0) {mShowSelectViewRunnable.run();} else {mTextView.postDelayed(mShowSelectViewRunnable, duration);}}private final Runnable mShowSelectViewRunnable = new Runnable() {@Overridepublic void run() {if (isHide) return;if (mOperateWindow != null) {mOperateWindow.show();}if (mStartHandle != null) {showCursorHandle(mStartHandle);}if (mEndHandle != null) {showCursorHandle(mEndHandle);}}};private void hideSelectView() {isHide = true;if (mStartHandle != null) {mStartHandle.dismiss();}if (mEndHandle != null) {mEndHandle.dismiss();}if (mOperateWindow != null) {mOperateWindow.dismiss();}}private void resetSelectionInfo() {mSelectionInfo.mSelectionContent = null;if (mSpannable != null && mSpan != null) {mSpannable.removeSpan(mSpan);mSpan = null;}}private void showSelectView(int x, int y) {hideSelectView();resetSelectionInfo();isHide = false;if (mStartHandle == null) mStartHandle = new CursorHandle(true);if (mEndHandle == null) mEndHandle = new CursorHandle(false);int startOffset = TextLayoutUtil.getPreciseOffset(mTextView, x, y);int endOffset = startOffset + DEFAULT_SELECTION_LENGTH;if (mTextView.getText() instanceof Spannable) {mSpannable = (Spannable) mTextView.getText();}if (mSpannable == null || startOffset >= mTextView.getText().length()) {return;}selectText(startOffset, endOffset);showCursorHandle(mStartHandle);showCursorHandle(mEndHandle);mOperateWindow.show();}private void showCursorHandle(CursorHandle cursorHandle) {Layout layout = mTextView.getLayout();int offset = cursorHandle.isLeft ? mSelectionInfo.mStart : mSelectionInfo.mEnd;cursorHandle.show((int) layout.getPrimaryHorizontal(offset), layout.getLineBottom(layout.getLineForOffset(offset)));}private void selectText(int startPos, int endPos) {if (startPos != -1) {mSelectionInfo.mStart = startPos;}if (endPos != -1) {mSelectionInfo.mEnd = endPos;}if (mSelectionInfo.mStart > mSelectionInfo.mEnd) {int temp = mSelectionInfo.mStart;mSelectionInfo.mStart = mSelectionInfo.mEnd;mSelectionInfo.mEnd = temp;}if (mSpannable != null) {if (mSpan == null) {mSpan = new BackgroundColorSpan(mSelectedColor);}mSelectionInfo.mSelectionContent = mSpannable.subSequence(mSelectionInfo.mStart, mSelectionInfo.mEnd).toString();mSpannable.setSpan(mSpan, mSelectionInfo.mStart, mSelectionInfo.mEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);if (mSelectListener != null) {mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);}}}public void setSelectListener(OnSelectListener selectListener) {mSelectListener = selectListener;}public void destroy() {mTextView.getViewTreeObserver().removeOnScrollChangedListener(mOnScrollChangedListener);mTextView.getViewTreeObserver().removeOnPreDrawListener(mOnPreDrawListener);resetSelectionInfo();hideSelectView();mStartHandle = null;mEndHandle = null;mOperateWindow = null;}/*** Operate windows : copy, select all*/private class OperateWindow {private PopupWindow mWindow;private int[] mTempCoors = new int[2];private int mWidth;private int mHeight;public OperateWindow(final Context context) {View contentView = LayoutInflater.from(context).inflate(R.layout.layout_operate_windows2, null);contentView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));mWidth = contentView.getMeasuredWidth();mHeight = contentView.getMeasuredHeight();mWindow =new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, false);mWindow.setClippingEnabled(false);TextView tv_copy = contentView.findViewById(R.id.tv_copy);TextView tv_select_all = contentView.findViewById(R.id.tv_select_all);tv_copy.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//复制点击实现功能AppTk.Companion.showTimeDailog(mSelectionInfo.mSelectionContent, mContext);if (mSelectListener != null) {mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);}SelectableTextHelper.this.resetSelectionInfo();SelectableTextHelper.this.hideSelectView();}});tv_select_all.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {hideSelectView();selectText(0, mTextView.getText().length());isHide = false;showCursorHandle(mStartHandle);showCursorHandle(mEndHandle);mOperateWindow.show();}});}public void show() {mTextView.getLocationInWindow(mTempCoors);Layout layout = mTextView.getLayout();int posX = (int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) + mTempCoors[0];int posY = layout.getLineTop(layout.getLineForOffset(mSelectionInfo.mStart)) + mTempCoors[1] - mHeight - 16;if (posX <= 0) posX = 16;if (posY < 0) posY = 16;if (posX + mWidth > TextLayoutUtil.getScreenWidth(mContext)) {posX = TextLayoutUtil.getScreenWidth(mContext) - mWidth - 16;}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mWindow.setElevation(8f);}mWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, posX, posY);}public void dismiss() {mWindow.dismiss();}public boolean isShowing() {return mWindow.isShowing();}}private class CursorHandle extends View {private PopupWindow mPopupWindow;private Paint mPaint;private int mCircleRadius = mCursorHandleSize / 2;private int mWidth = mCircleRadius * 2;private int mHeight = mCircleRadius * 2;private int mPadding = 25;private boolean isLeft;public CursorHandle(boolean isLeft) {super(mContext);this.isLeft = isLeft;mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(mCursorHandleColor);mPopupWindow = new PopupWindow(this);mPopupWindow.setClippingEnabled(false);mPopupWindow.setWidth(mWidth + mPadding * 2);mPopupWindow.setHeight(mHeight + mPadding / 2);invalidate();}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawCircle(mCircleRadius + mPadding, mCircleRadius, mCircleRadius, mPaint);if (isLeft) {canvas.drawRect(mCircleRadius + mPadding, 0, mCircleRadius * 2 + mPadding, mCircleRadius, mPaint);} else {canvas.drawRect(mPadding, 0, mCircleRadius + mPadding, mCircleRadius, mPaint);}}private int mAdjustX;private int mAdjustY;private int mBeforeDragStart;private int mBeforeDragEnd;@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mBeforeDragStart = mSelectionInfo.mStart;mBeforeDragEnd = mSelectionInfo.mEnd;mAdjustX = (int) event.getX();mAdjustY = (int) event.getY();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:mOperateWindow.show();break;case MotionEvent.ACTION_MOVE:mOperateWindow.dismiss();int rawX = (int) event.getRawX();int rawY = (int) event.getRawY();update(rawX + mAdjustX - mWidth, rawY + mAdjustY - mHeight);break;}return true;}private void changeDirection() {isLeft = !isLeft;invalidate();}public void dismiss() {mPopupWindow.dismiss();}private int[] mTempCoors = new int[2];public void update(int x, int y) {mTextView.getLocationInWindow(mTempCoors);int oldOffset;if (isLeft) {oldOffset = mSelectionInfo.mStart;} else {oldOffset = mSelectionInfo.mEnd;}y -= mTempCoors[1];int offset = TextLayoutUtil.getHysteresisOffset(mTextView, x, y, oldOffset);if (offset != oldOffset) {resetSelectionInfo();if (isLeft) {if (offset > mBeforeDragEnd) {CursorHandle handle = getCursorHandle(false);changeDirection();handle.changeDirection();mBeforeDragStart = mBeforeDragEnd;selectText(mBeforeDragEnd, offset);handle.updateCursorHandle();} else {selectText(offset, -1);}updateCursorHandle();} else {if (offset < mBeforeDragStart) {CursorHandle handle = getCursorHandle(true);handle.changeDirection();changeDirection();mBeforeDragEnd = mBeforeDragStart;selectText(offset, mBeforeDragStart);handle.updateCursorHandle();} else {selectText(mBeforeDragStart, offset);}updateCursorHandle();}}}private void updateCursorHandle() {mTextView.getLocationInWindow(mTempCoors);Layout layout = mTextView.getLayout();if (isLeft) {mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) - mWidth + getExtraX(),layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mStart)) + getExtraY(), -1, -1);} else {mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mEnd) + getExtraX(),layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mEnd)) + getExtraY(), -1, -1);}}public void show(int x, int y) {mTextView.getLocationInWindow(mTempCoors);int offset = isLeft ? mWidth : 0;mPopupWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, x - offset + getExtraX(), y + getExtraY());}public int getExtraX() {return mTempCoors[0] - mPadding + mTextView.getPaddingLeft();}public int getExtraY() {return mTempCoors[1] + mTextView.getPaddingTop();}}private CursorHandle getCursorHandle(boolean isLeft) {if (mStartHandle.isLeft == isLeft) {return mStartHandle;} else {return mEndHandle;}}public static class Builder {private TextView mTextView;private int mCursorHandleColor = 0xFF1379D6;private int mSelectedColor = 0xFFAFE1F4;private float mCursorHandleSizeInDp = 24;public Builder(TextView textView) {mTextView = textView;}public Builder setCursorHandleColor(@ColorInt int cursorHandleColor) {mCursorHandleColor = cursorHandleColor;return this;}public Builder setCursorHandleSizeInDp(float cursorHandleSizeInDp) {mCursorHandleSizeInDp = cursorHandleSizeInDp;return this;}public Builder setSelectedColor(@ColorInt int selectedBgColor) {mSelectedColor = selectedBgColor;return this;}public SelectableTextHelper build() {return new SelectableTextHelper(this);}}
}

8.调用

private var mSelectableTextHelper: SelectableTextHelper? = null//实例化
//text为文案
mSelectableTextHelper = SelectableTextHelper.Builder(text).setSelectedColor(Color.parseColor("#afe1f4")).setCursorHandleSizeInDp(20f).setCursorHandleColor(Color.parseColor("#0d7aff")).build()

总结

感觉东西是有点多,但比较实用,而且直接复制去就可以用,自己写主要费大脑不是。

http://www.khdw.cn/news/39751.html

相关文章:

  • 昆山做网站的公昆山做网站的公司司chrome手机版
  • 专业网站建设哪里有网络营销有哪些功能
  • 网络推广营销培训seo长尾关键词优化
  • 鄂州手机网站设计百度开户渠道
  • 有了网站怎么做app吗百度推广天津总代理
  • 聊城网站建设招聘新闻今日要闻
  • 虎门商城网站建设国外网站谷歌seo推广
  • 网页版微信官方登录电商seo是什么
  • 怎么用dwcs6做网站设计四平网站seo
  • 旅游景区网站建设你对网络营销的理解
  • 装修网上接单平台有哪些啊?惠州网站seo排名优化
  • 网站构造下拉列表怎么做中国免费网站服务器下载
  • 网站集约化后如何建设线上推广100种方式
  • 山东莱钢建设有限公司网站常州百度搜索优化
  • wordpress主题幻灯片系统优化软件
  • 做网站怎么把导航每个页面都有百度下载免费官方安装
  • 做网站的哪里有求职seo服务
  • 沈阳微网站建设建立网站的几个步骤
  • 用ps怎么做网站背景企业网站优化价格
  • 网站制作多少费用网站推广工作
  • 12306网站建设花了多少钱seo营销怎么做
  • 游戏制作软件培训深圳网站seo公司
  • 建设官网网站nba新闻最新消息滚动
  • 如何完整地备份wordpress北京seo优化哪家公司好
  • 呼和浩特哪里做网站凌哥seo
  • 网站开发需要学shenme国内做网站比较好的公司
  • 做暧在线观看网站企业如何进行品牌推广
  • 写一个app需要多少钱合肥网站优化软件
  • 搭建一个网站需要多久推广平台网站热狗网
  • 锡盟建设工程造价工程管理网站网站销售怎么推广