private void createLinkFromSelection(String linkURL, String linkText) { try { if (linkURL != null && !linkURL.equals("http://") && !linkURL.equals("")) { if (mSelectionStart > mSelectionEnd) { int temp = mSelectionEnd; mSelectionEnd = mSelectionStart; mSelectionStart = temp; } Editable editable = mContentEditText.getText(); if (editable == null) { return; } if (mIsLocalDraft) { if (linkText == null) { if (mSelectionStart < mSelectionEnd) { editable.delete(mSelectionStart, mSelectionEnd); } editable.insert(mSelectionStart, linkURL); editable.setSpan( new URLSpan(linkURL), mSelectionStart, mSelectionStart + linkURL.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mContentEditText.setSelection(mSelectionStart + linkURL.length()); } else { if (mSelectionStart < mSelectionEnd) { editable.delete(mSelectionStart, mSelectionEnd); } editable.insert(mSelectionStart, linkText); editable.setSpan( new URLSpan(linkURL), mSelectionStart, mSelectionStart + linkText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); mContentEditText.setSelection(mSelectionStart + linkText.length()); } } else { if (linkText == null) { if (mSelectionStart < mSelectionEnd) { editable.delete(mSelectionStart, mSelectionEnd); } String urlHTML = "<a href=\"" + linkURL + "\">" + linkURL + "</a>"; editable.insert(mSelectionStart, urlHTML); mContentEditText.setSelection(mSelectionStart + urlHTML.length()); } else { if (mSelectionStart < mSelectionEnd) { editable.delete(mSelectionStart, mSelectionEnd); } String urlHTML = "<a href=\"" + linkURL + "\">" + linkText + "</a>"; editable.insert(mSelectionStart, urlHTML); mContentEditText.setSelection(mSelectionStart + urlHTML.length()); } } } } catch (RuntimeException e) { AppLog.e(T.POSTS, e); } }
@Override public void setContent(CharSequence text) { mContent = text; if (mContentEditText != null) { mContentEditText.setText(text); mContentEditText.setSelection(mSelectionStart, mSelectionEnd); } else { // TODO } }
@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; }
/** * Applies formatting to selected text, or marks the entry for a new text style at the current * cursor position * * @param toggleButton button from formatting bar * @param tag HTML tag name for text style */ private void onFormatButtonClick(ToggleButton toggleButton, String tag) { Spannable s = mContentEditText.getText(); if (s == null) return; int selectionStart = mContentEditText.getSelectionStart(); mStyleStart = selectionStart; int selectionEnd = mContentEditText.getSelectionEnd(); if (selectionStart > selectionEnd) { int temp = selectionEnd; selectionEnd = selectionStart; selectionStart = temp; } Class styleClass = null; if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG) || tag.equals(TAG_FORMAT_BAR_BUTTON_EM)) styleClass = StyleSpan.class; else if (tag.equals(TAG_FORMAT_BAR_BUTTON_UNDERLINE)) styleClass = WPUnderlineSpan.class; else if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRIKE)) styleClass = StrikethroughSpan.class; else if (tag.equals(TAG_FORMAT_BAR_BUTTON_QUOTE)) styleClass = QuoteSpan.class; if (styleClass == null) return; Object[] allSpans = s.getSpans(selectionStart, selectionEnd, styleClass); boolean textIsSelected = selectionEnd > selectionStart; if (mIsLocalDraft) { // Local drafts can use the rich text editor. Yay! boolean shouldAddSpan = true; for (Object span : allSpans) { if (span instanceof StyleSpan) { StyleSpan styleSpan = (StyleSpan) span; if ((styleSpan.getStyle() == Typeface.BOLD && !tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG)) || (styleSpan.getStyle() == Typeface.ITALIC && !tag.equals(TAG_FORMAT_BAR_BUTTON_EM))) { continue; } } if (!toggleButton.isChecked() && textIsSelected) { // If span exists and text is selected, remove the span s.removeSpan(span); shouldAddSpan = false; break; } else if (!toggleButton.isChecked()) { // Remove span at cursor point if button isn't checked Object[] spans = s.getSpans(mStyleStart - 1, mStyleStart, styleClass); for (Object removeSpan : spans) { selectionStart = s.getSpanStart(removeSpan); selectionEnd = s.getSpanEnd(removeSpan); s.removeSpan(removeSpan); } } } if (shouldAddSpan) { if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG)) { s.setSpan( new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (tag.equals(TAG_FORMAT_BAR_BUTTON_EM)) { s.setSpan( new StyleSpan(android.graphics.Typeface.ITALIC), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } else { try { s.setSpan( styleClass.newInstance(), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (java.lang.InstantiationException e) { AppLog.e(T.POSTS, e); } catch (IllegalAccessException e) { AppLog.e(T.POSTS, e); } } } } else { // Add HTML tags when editing an existing post String startTag = "<" + tag + ">"; String endTag = "</" + tag + ">"; Editable content = mContentEditText.getText(); if (textIsSelected) { content.insert(selectionStart, startTag); content.insert(selectionEnd + startTag.length(), endTag); toggleButton.setChecked(false); mContentEditText.setSelection(selectionEnd + startTag.length() + endTag.length()); } else if (toggleButton.isChecked()) { content.insert(selectionStart, startTag); mContentEditText.setSelection(selectionEnd + startTag.length()); } else if (!toggleButton.isChecked()) { content.insert(selectionEnd, endTag); mContentEditText.setSelection(selectionEnd + endTag.length()); } } }
@Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_edit_post_content, container, false); mFormatBar = (LinearLayout) rootView.findViewById(R.id.format_bar); mTitleEditText = (EditText) rootView.findViewById(R.id.post_title); mTitleEditText.setText(mTitle); mTitleEditText.setOnEditorActionListener( new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // Go to full screen editor when 'next' button is tapped on soft keyboard ActionBar actionBar = getActionBar(); if (actionId == EditorInfo.IME_ACTION_NEXT && actionBar != null && actionBar.isShowing()) { setContentEditingModeVisible(true); } return false; } }); mContentEditText = (WPEditText) rootView.findViewById(R.id.post_content); mContentEditText.setText(mContent); mPostContentLinearLayout = (LinearLayout) rootView.findViewById(R.id.post_content_wrapper); mPostSettingsLinearLayout = (LinearLayout) rootView.findViewById(R.id.post_settings_wrapper); Button postSettingsButton = (Button) rootView.findViewById(R.id.post_settings_button); postSettingsButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mEditorFragmentListener.onSettingsClicked(); } }); mBoldToggleButton = (ToggleButton) rootView.findViewById(R.id.bold); mEmToggleButton = (ToggleButton) rootView.findViewById(R.id.em); mBquoteToggleButton = (ToggleButton) rootView.findViewById(R.id.bquote); mUnderlineToggleButton = (ToggleButton) rootView.findViewById(R.id.underline); mStrikeToggleButton = (ToggleButton) rootView.findViewById(R.id.strike); mAddPictureButton = (Button) rootView.findViewById(R.id.addPictureButton); Button linkButton = (Button) rootView.findViewById(R.id.link); Button moreButton = (Button) rootView.findViewById(R.id.more); registerForContextMenu(mAddPictureButton); mContentEditText = (WPEditText) rootView.findViewById(R.id.post_content); mContentEditText.setOnSelectionChangedListener(this); mContentEditText.setOnTouchListener(this); mContentEditText.addTextChangedListener(this); mContentEditText.setOnEditTextImeBackListener( new WPEditText.EditTextImeBackListener() { @Override public void onImeBack(WPEditText ctrl, String text) { // Go back to regular editor if IME keyboard is dismissed // Bottom comparison is there to ensure that the keyboard is actually showing ActionBar actionBar = getActionBar(); if (mRootView.getBottom() < mFullViewBottom && actionBar != null && !actionBar.isShowing()) { setContentEditingModeVisible(false); } } }); mAddPictureButton.setOnClickListener(mFormatBarButtonClickListener); mBoldToggleButton.setOnClickListener(mFormatBarButtonClickListener); linkButton.setOnClickListener(mFormatBarButtonClickListener); mEmToggleButton.setOnClickListener(mFormatBarButtonClickListener); mUnderlineToggleButton.setOnClickListener(mFormatBarButtonClickListener); mStrikeToggleButton.setOnClickListener(mFormatBarButtonClickListener); mBquoteToggleButton.setOnClickListener(mFormatBarButtonClickListener); moreButton.setOnClickListener(mFormatBarButtonClickListener); mEditorFragmentListener.onEditorFragmentInitialized(); if (savedInstanceState != null) { Parcelable[] spans = savedInstanceState.getParcelableArray(KEY_IMAGE_SPANS); mContent = savedInstanceState.getString(KEY_CONTENT, ""); mContentEditText.setText(mContent); mContentEditText.setSelection( savedInstanceState.getInt(KEY_START, 0), savedInstanceState.getInt(KEY_END, 0)); if (spans != null && spans.length > 0) { for (Parcelable s : spans) { WPImageSpan editSpan = (WPImageSpan) s; addMediaFile( editSpan.getMediaFile(), editSpan.getMediaFile().getFilePath(), mImageLoader, editSpan.getStartPosition(), editSpan.getEndPosition()); } } } return rootView; }