@Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { if (event.getAction() != MotionEvent.ACTION_UP) return super.onTouchEvent(widget, buffer, event); int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); if (link.length != 0) { onLinkClick(link[0].getURL()); } return true; }
@Override public boolean onTouch(View v, MotionEvent event) { Layout layout = ((TextView) v).getLayout(); int x = (int) event.getX(); int y = (int) event.getY(); int offset = 0; if (layout != null) { int line = layout.getLineForVertical(y); offset = layout.getOffsetForHorizontal(line, x); } TextView tv = (TextView) v; SpannableString value = SpannableString.valueOf(tv.getText()); LinkMovementMethod.getInstance().onTouchEvent(tv, value, event); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: WeburlSpan[] urlSpans = value.getSpans(0, value.length(), WeburlSpan.class); boolean find = false; int findStart = 0; int findEnd = 0; for (WeburlSpan urlSpan : urlSpans) { int start = value.getSpanStart(urlSpan); int end = value.getSpanEnd(urlSpan); if (start <= offset && offset <= end) { find = true; findStart = start; findEnd = end; break; } } if (find) { BackgroundColorSpan bkcolor = new BackgroundColorSpan(0xff89660f); value.setSpan(bkcolor, findStart, findEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE); ((TextView) v).setText(value); } return find; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: BackgroundColorSpan[] backgroundColorSpans = value.getSpans(0, value.length(), BackgroundColorSpan.class); for (BackgroundColorSpan bkcolor : backgroundColorSpans) { value.removeSpan(bkcolor); ((TextView) v).setText(value); } break; } return false; }
public boolean onTouchEvent(TextView widget, final Spannable buffer, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) position = event.getY(); // used to see if the user scrolled or not if (!(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_DOWN)) { if (Math.abs((position - event.getY())) > 10) { handler.removeCallbacksAndMessages(null); Log.v(LogUtil.getTag(), "POSITION NOT CLICK IS " + event.getY()); } return super.onTouchEvent(widget, buffer, event); } Log.v(LogUtil.getTag(), "POSITION IS " + position); comm = (SpoilerRobotoTextView) widget; int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); final int off = layout.getOffsetForHorizontal(line, x); link = buffer.getSpans(off, off, URLSpan.class); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: clickHandled = false; if (link.length != 0) { handler.postDelayed(longClicked, android.view.ViewConfiguration.getLongPressTimeout()); } break; case MotionEvent.ACTION_UP: handler.removeCallbacksAndMessages(null); if (!clickHandled) { // regular click if (link.length != 0) { int i = 0; if (sequence != null) { i = ((Spannable) sequence).getSpanEnd(link[0]); } onLinkClick(link[0].getURL(), i); } } break; } return true; }
@Override public boolean onTouchEvent(MotionEvent event) { CharSequence text = getText(); int action = event.getAction(); if (!(text instanceof Spannable)) { return super.onTouchEvent(event); } Spannable buffer = (Spannable) text; if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { TextView widget = this; int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { if (mCurrentLink == link[0]) { link[0].onClick(widget); } mCurrentLink = null; buffer.removeSpan(mLinkFocusStyle); } else if (action == MotionEvent.ACTION_DOWN) { mCurrentLink = link[0]; buffer.setSpan( mLinkFocusStyle, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } return true; } } mCurrentLink = null; buffer.removeSpan(mLinkFocusStyle); return super.onTouchEvent(event); }
private Integer findOffsetForPosition(float x, float y) { if (childView == null || childView.getLayout() == null) { return null; } Layout layout = this.childView.getLayout(); int line = layout.getLineForVertical((int) y); return layout.getOffsetForHorizontal(line, x); }
@Override public int reactTagForTouch(float touchX, float touchY) { Spanned text = (Spanned) getText(); int target = getId(); int x = (int) touchX; int y = (int) touchY; Layout layout = getLayout(); if (layout == null) { // If the layout is null, the view hasn't been properly laid out yet. Therefore, we can't find // the exact text tag that has been touched, and the correct tag to return is the default one. return target; } int line = layout.getLineForVertical(y); int lineStartX = (int) layout.getLineLeft(line); int lineEndX = (int) layout.getLineRight(line); // TODO(5966918): Consider extending touchable area for text spans by some DP constant if (x >= lineStartX && x <= lineEndX) { int index = layout.getOffsetForHorizontal(line, x); // We choose the most inner span (shortest) containing character at the given index // if no such span can be found we will send the textview's react id as a touch handler // In case when there are more than one spans with same length we choose the last one // from the spans[] array, since it correspond to the most inner react element ReactTagSpan[] spans = text.getSpans(index, index, ReactTagSpan.class); if (spans != null) { int targetSpanTextLength = text.length(); for (int i = 0; i < spans.length; i++) { int spanStart = text.getSpanStart(spans[i]); int spanEnd = text.getSpanEnd(spans[i]); if (spanEnd > index && (spanEnd - spanStart) <= targetSpanTextLength) { target = spans[i].getReactTag(); targetSpanTextLength = (spanEnd - spanStart); } } } } return target; }
/** 覆寫觸控事件,分辨出是否為連結的點擊。 */ @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); // 取得事件類型 if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { // 是連結點擊 if (widget instanceof LinkTextView) { // 如果實體是LinkTextView ((LinkTextView) widget).linkHit = true; } if (action == MotionEvent.ACTION_UP) { // 放開時 // link[0].onClick(widget); // 開啟連結 String url = ((URLSpan) link[0]).getURL(); Utils.clickUrl(widget, url); } else if (action == MotionEvent.ACTION_DOWN) { // 按下時 Selection.setSelection( buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); // 選擇連結 } return true; } else { // 不是連結點擊 if (widget instanceof LinkTextView) { // 如果實體是LinkTextView ((LinkTextView) widget).linkHit = false; } Selection.removeSelection(buffer); Touch.onTouchEvent(widget, buffer, event); return false; } } return Touch.onTouchEvent(widget, buffer, event); }
private boolean down(TextView widget, Spannable buffer) { if (DBG) { Log.d(LOG_TAG, "--- down:"); } Layout layout = widget.getLayout(); int end = getEndPos(widget); int line = layout.getLineForOffset(end); if (line < layout.getLineCount() - 1) { int to; if (layout.getParagraphDirection(line) == layout.getParagraphDirection(line + 1)) { float h = layout.getPrimaryHorizontal(end); to = layout.getOffsetForHorizontal(line + 1, h); } else { to = layout.getLineStart(line + 1); } mManager.setSelectedEndPos(to); mManager.onCursorMoved(); return true; } return false; }
@Override public boolean onTouchEvent(MotionEvent event) { TextView widget = (TextView) this; Object text = widget.getText(); if (text instanceof Spanned) { Spannable buffer = (Spannable) text; int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection( buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } return true; } } } return false; }
@Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } commentView.invalidate(); return true; } else { // Changed this to propagate events PostView.this.onTouchEvent(event); return true; } } else { PostView.this.onTouchEvent(event); return true; } }
private TouchableSpan getPressedSpan( TextView textView, Spannable spannable, MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); x -= textView.getTotalPaddingLeft(); y -= textView.getTotalPaddingTop(); x += textView.getScrollX(); y += textView.getScrollY(); Layout layout = textView.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); TouchableSpan[] link = spannable.getSpans(off, off, TouchableSpan.class); TouchableSpan touchedSpan = null; if (link.length > 0) { touchedSpan = link[0]; } return touchedSpan; }
public boolean handleTouchEvent(MotionEvent event) { int action = event.getAction(); if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_DOWN) { return true; } else { int x = (int) event.getX(); int y = (int) event.getY(); x -= getTotalPaddingLeft(); y -= getTotalPaddingTop(); x += getScrollX(); y += getScrollY(); Layout layout = getLayout(); int line = layout.getLineForVertical(y); int offset = layout.getOffsetForHorizontal(line, x); float width = layout.getLineWidth(line); if (y > width) { offset = y; } if (!(getText() instanceof Spannable)) { return true; } else { Spannable span = (Spannable) getText(); ClickableSpan[] clickSpan = span.getSpans(offset, offset, ClickableSpan.class); if (clickSpan == null || clickSpan.length == 0) { am[] aam = span.getSpans(offset, offset, am.class); if (aam != null && aam.length != 0) return false; return true; } else { return false; } } } }
private static int getOffsetAtCoordinate(int line, float x, TextView tv, Layout layout) { x = convertToLocalHorizontalCoordinate(x, tv); return layout.getOffsetForHorizontal(line, x); }
@Override public boolean onTouch(View v, MotionEvent event) { float pos = event.getY(); if (event.getAction() == 0) mLastYPos = pos; if (event.getAction() > 1) { int scrollThreshold = DisplayUtils.dpToPx(getActivity(), 2); if (((mLastYPos - pos) > scrollThreshold) || ((pos - mLastYPos) > scrollThreshold)) mScrollDetected = true; } mLastYPos = pos; if (event.getAction() == MotionEvent.ACTION_UP) { ActionBar actionBar = getActionBar(); if (actionBar != null && actionBar.isShowing()) { setContentEditingModeVisible(true); return false; } } if (event.getAction() == MotionEvent.ACTION_UP && !mScrollDetected) { Layout layout = ((TextView) v).getLayout(); int x = (int) event.getX(); int y = (int) event.getY(); x += v.getScrollX(); y += v.getScrollY(); if (layout != null) { int line = layout.getLineForVertical(y); int charPosition = layout.getOffsetForHorizontal(line, x); Spannable spannable = mContentEditText.getText(); if (spannable == null) { return false; } // check if image span was tapped WPImageSpan[] imageSpans = spannable.getSpans(charPosition, charPosition, WPImageSpan.class); if (imageSpans.length != 0) { final WPImageSpan imageSpan = imageSpans[0]; MediaFile mediaFile = imageSpan.getMediaFile(); if (mediaFile == null) return false; if (!mediaFile.isVideo()) { LayoutInflater factory = LayoutInflater.from(getActivity()); final View alertView = factory.inflate(R.layout.alert_image_options, null); if (alertView == null) return false; final EditText imageWidthText = (EditText) alertView.findViewById(R.id.imageWidthText); final EditText titleText = (EditText) alertView.findViewById(R.id.title); final EditText caption = (EditText) alertView.findViewById(R.id.caption); final CheckBox featuredCheckBox = (CheckBox) alertView.findViewById(R.id.featuredImage); final CheckBox featuredInPostCheckBox = (CheckBox) alertView.findViewById(R.id.featuredInPost); // show featured image checkboxes if supported if (mFeaturedImageSupported) { featuredCheckBox.setVisibility(View.VISIBLE); featuredInPostCheckBox.setVisibility(View.VISIBLE); } featuredCheckBox.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { featuredInPostCheckBox.setVisibility(View.VISIBLE); } else { featuredInPostCheckBox.setVisibility(View.GONE); } } }); final SeekBar seekBar = (SeekBar) alertView.findViewById(R.id.imageWidth); final Spinner alignmentSpinner = (Spinner) alertView.findViewById(R.id.alignment_spinner); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( getActivity(), R.array.alignment_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); alignmentSpinner.setAdapter(adapter); imageWidthText.setText(String.valueOf(mediaFile.getWidth()) + "px"); seekBar.setProgress(mediaFile.getWidth()); titleText.setText(mediaFile.getTitle()); caption.setText(mediaFile.getCaption()); featuredCheckBox.setChecked(mediaFile.isFeatured()); if (mediaFile.isFeatured()) { featuredInPostCheckBox.setVisibility(View.VISIBLE); } else { featuredInPostCheckBox.setVisibility(View.GONE); } featuredInPostCheckBox.setChecked(mediaFile.isFeaturedInPost()); alignmentSpinner.setSelection(mediaFile.getHorizontalAlignment(), true); final int maxWidth = MediaUtils.getMinimumImageWidth( getActivity(), imageSpan.getImageSource(), mBlogSettingMaxImageWidth); seekBar.setMax(maxWidth / 10); if (mediaFile.getWidth() != 0) { seekBar.setProgress(mediaFile.getWidth() / 10); } seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (progress == 0) { progress = 1; } imageWidthText.setText(progress * 10 + "px"); } }); imageWidthText.setOnFocusChangeListener( new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { imageWidthText.setText(""); } } }); imageWidthText.setOnEditorActionListener( new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { int width = getEditTextIntegerClamped(imageWidthText, 10, maxWidth); seekBar.setProgress(width / 10); imageWidthText.setSelection((String.valueOf(width).length())); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow( imageWidthText.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN); return true; } }); showImageSettings( alertView, titleText, caption, imageWidthText, featuredCheckBox, featuredInPostCheckBox, maxWidth, alignmentSpinner, imageSpan); mScrollDetected = false; return true; } } else { mContentEditText.setMovementMethod(ArrowKeyMovementMethod.getInstance()); int selectionStart = mContentEditText.getSelectionStart(); if (selectionStart >= 0 && mContentEditText.getSelectionEnd() >= selectionStart) mContentEditText.setSelection(selectionStart, mContentEditText.getSelectionEnd()); } // get media gallery spans MediaGalleryImageSpan[] gallerySpans = spannable.getSpans(charPosition, charPosition, MediaGalleryImageSpan.class); if (gallerySpans.length > 0) { final MediaGalleryImageSpan gallerySpan = gallerySpans[0]; Intent intent = new Intent(ACTION_MEDIA_GALLERY_TOUCHED); intent.putExtra(EXTRA_MEDIA_GALLERY, gallerySpan.getMediaGallery()); getActivity().sendBroadcast(intent); } } } else if (event.getAction() == 1) { mScrollDetected = false; } return false; }
@Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_CANCEL) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { // 按下后松开,移除所有 BackgroundColorSpan。 BackgroundColorSpan[] backgroundColorSpans = buffer.getSpans(0, buffer.length(), BackgroundColorSpan.class); for (BackgroundColorSpan bkcolor : backgroundColorSpans) { buffer.removeSpan(bkcolor); } // Selection.removeSelection(buffer); link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { // 按下,给按下的 ClickableSpan 设置 BackgroundColorSpan。 /* Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); */ BackgroundColorSpan bkcolor = new BackgroundColorSpan(0xff89660f); buffer.setSpan( bkcolor, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), Spanned.SPAN_INCLUSIVE_INCLUSIVE); } else if (action == MotionEvent.ACTION_CANCEL) { // 按下不松开而是移动,则变成取消事件,移除所有 BackgroundColorSpan。 BackgroundColorSpan[] backgroundColorSpans = buffer.getSpans(0, buffer.length(), BackgroundColorSpan.class); for (BackgroundColorSpan bkcolor : backgroundColorSpans) { buffer.removeSpan(bkcolor); } } return true; } else { BackgroundColorSpan[] backgroundColorSpans = buffer.getSpans(0, buffer.length(), BackgroundColorSpan.class); for (BackgroundColorSpan bkcolor : backgroundColorSpans) { buffer.removeSpan(bkcolor); } // Selection.removeSelection(buffer); } } return super.onTouchEvent(widget, buffer, event); }