Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkDetailActivity.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.enhancedbookmarks;
6
7 import android.animation.Animator;
8 import android.animation.AnimatorListenerAdapter;
9 import android.animation.ObjectAnimator;
10 import android.annotation.TargetApi;
11 import android.content.Context;
12 import android.graphics.Bitmap;
13 import android.os.Build;
14 import android.os.Bundle;
15 import android.text.Editable;
16 import android.text.TextWatcher;
17 import android.transition.Fade;
18 import android.transition.Transition;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.view.inputmethod.InputMethodManager;
22 import android.widget.Button;
23 import android.widget.EditText;
24 import android.widget.ImageButton;
25 import android.widget.ImageView;
26 import android.widget.LinearLayout;
27 import android.widget.RelativeLayout;
28 import android.widget.TextView;
29
30 import com.google.android.apps.chrome.R;
31
32 import org.chromium.chrome.browser.BookmarksBridge.BookmarkItem;
33 import org.chromium.chrome.browser.BookmarksBridge.BookmarkModelObserver;
34 import org.chromium.chrome.browser.UrlUtilities;
35 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksBridge.Fi ltersObserver;
36 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksBridge.Sa lientImageCallback;
37 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksModel;
38 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkDetailScrol lView.OnScrollListener;
39 import org.chromium.chrome.browser.widget.FadingShadow;
40 import org.chromium.chrome.browser.widget.FadingShadowView;
41 import org.chromium.chrome.browser.widget.FlowLayout;
42 import org.chromium.components.bookmarks.BookmarkId;
43 import org.chromium.components.bookmarks.BookmarkType;
44 import org.chromium.ui.base.DeviceFormFactor;
45
46 /**
47 * Dialog to show details of the selected bookmark. It has two modes: read-only mode and editing
48 * mode. Clicking on a textview will make the dialog animate to editing mode. On a handset this
49 * dialog will be full-screen; on tablet it will be a fixed-size dialog popping up in the middle of
50 * the screen.
51 */
52 public class EnhancedBookmarkDetailActivity extends EnhancedBookmarkActivityBase implements
53 View.OnClickListener, OnScrollListener, FiltersObserver {
54 public static final String INTENT_BOOKMARK_ID = "EnhancedBookmarkDetailActiv ity.BookmarkId";
55 private static final int ANIMATION_DURATION_MS = 300;
56
57 private EnhancedBookmarksModel mEnhancedBookmarksModel;
58 private BookmarkId mBookmarkId;
59
60 private EnhancedBookmarkDetailScrollView mScrollView;
61 private LinearLayout mContentLayout;
62 private ImageView mImageView;
63 private EditText mTitleEditText;
64 private EditText mUrlEditText;
65 private View mFolderBox;
66 private TextView mFolderTextView;
67 private TextView mAutoFoldersLabel;
68 private FlowLayout mAutoFoldersFlowLayout;
69 private EditText mDescriptionEditText;
70 private View mMaskView;
71 private RelativeLayout mActionBarLayout;
72 private ImageButton mCloseButton;
73 private ImageButton mDeleteButton;
74 private ImageButton mSaveButton;
75 private FadingShadowView mImageShadowMask;
76 private FadingShadowView mShadow;
77 private View mBottomSpacer;
78 private EditText[] mEditTexts;
79
80 private Animator mCurrentAnimator;
81 private int mDominantColor;
82 private boolean mIsEditingMode;
83
84 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse rver() {
85 @Override
86 public void bookmarkNodeRemoved(BookmarkItem parent, int oldIndex, Bookm arkItem node,
87 boolean isDoingExtensiveChanges) {
88 if (mBookmarkId.equals(node.getId())) {
89 dismiss();
90 }
91 }
92
93 @Override
94 public void bookmarkNodeMoved(BookmarkItem oldParent, int oldIndex, Book markItem newParent,
95 int newIndex) {
96 BookmarkId movedBookmark = mEnhancedBookmarksModel.getChildAt(newPar ent.getId(),
97 newIndex);
98 if (movedBookmark.equals(mBookmarkId)) {
99 setParentFolderName(newParent.getId());
100 }
101 }
102
103 @Override
104 public void bookmarkNodeChanged(BookmarkItem node) {
105 if (mBookmarkId.equals(node.getId())) updateViews(node);
106 }
107
108 @Override
109 public void bookmarkModelChanged() {
110 }
111 };
112
113 @Override
114 public void onCreate(Bundle savedInstanceState) {
115 super.onCreate(savedInstanceState);
116 EnhancedBookmarkUtils.setTaskDescriptionInDocumentMode(this,
117 getString(R.string.accessibility_enhanced_bookmark_detail_view)) ;
118 mEnhancedBookmarksModel = new EnhancedBookmarksModel();
119 mBookmarkId = BookmarkId.getBookmarkIdFromString(
120 getIntent().getStringExtra(INTENT_BOOKMARK_ID));
121 mEnhancedBookmarksModel.addModelObserver(mBookmarkModelObserver);
122 mEnhancedBookmarksModel.addFiltersObserver(this);
123 setContentView(R.layout.eb_detail);
124 mScrollView = (EnhancedBookmarkDetailScrollView) findViewById(
125 R.id.eb_detail_scroll_view);
126 mContentLayout = (LinearLayout) findViewById(R.id.eb_detail_content);
127 mImageView = (ImageView) findViewById(R.id.eb_detail_image_view);
128 mTitleEditText = (EditText) findViewById(R.id.eb_detail_title);
129 mUrlEditText = (EditText) findViewById(R.id.eb_detail_url);
130 mFolderBox = findViewById(R.id.eb_detail_folder_box);
131 mFolderTextView = (TextView) findViewById(R.id.eb_detail_folder_textview );
132 mAutoFoldersLabel = (TextView) findViewById(R.id.eb_detail_auto_folder_l abel);
133 mAutoFoldersFlowLayout = (FlowLayout) findViewById(R.id.eb_detail_flow_l ayout);
134 mDescriptionEditText = (EditText) findViewById(R.id.eb_detail_descriptio n);
135 mMaskView = findViewById(R.id.eb_detail_image_mask);
136 mActionBarLayout = (RelativeLayout) findViewById(R.id.eb_detail_action_b ar);
137 mSaveButton = (ImageButton) findViewById(R.id.eb_detail_actionbar_save_b utton);
138 mDeleteButton = (ImageButton) findViewById(R.id.eb_detail_actionbar_dele te_button);
139 mCloseButton = (ImageButton) findViewById(R.id.eb_detail_actionbar_close _button);
140 mImageShadowMask = (FadingShadowView) findViewById(R.id.eb_detail_top_sh adow);
141 mShadow = (FadingShadowView) findViewById(R.id.eb_detail_shadow);
142 mBottomSpacer = mScrollView.findViewById(R.id.bottom_spacer);
143 mEditTexts = new EditText[]{mTitleEditText, mUrlEditText, mDescriptionEd itText};
144
145 // Listen to click event of EditTexts while setting them not focusable i n order to
146 // postpone showing soft keyboard until animations are finished.
147 for (EditText editText : mEditTexts) editText.setOnClickListener(this);
148 clearErrorWhenNonEmpty(mEditTexts);
149 int shadowColor = getResources().getColor(
150 R.color.enhanced_bookmark_detail_dialog_shadow_color);
151 mShadow.init(shadowColor, FadingShadow.POSITION_TOP);
152 mImageShadowMask.init(shadowColor, FadingShadow.POSITION_TOP);
153 mImageShadowMask.setStrength(1.0f);
154
155 mSaveButton.setOnClickListener(this);
156 mDeleteButton.setOnClickListener(this);
157 mCloseButton.setOnClickListener(this);
158 mFolderBox.setOnClickListener(this);
159
160 mScrollView.setOnScrollListener(this);
161
162 updateViews();
163 updateAutoFolders();
164 setUpSharedElementAnimation();
165 }
166
167 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
168 private void setUpSharedElementAnimation() {
169 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
170 Transition t = new Fade();
171 // Exlude status bar and navigation bar, to work around an Android bug t hat white background
172 // activity will cause these two bars blink/flash during content transit ion.
173 t.excludeTarget(android.R.id.statusBarBackground, true);
174 t.excludeTarget(android.R.id.navigationBarBackground, true);
175 getWindow().setEnterTransition(t);
176 getWindow().setExitTransition(t);
177 }
178
179 /**
180 * Custom {@link android.app.Activity#finish()} that checks device version. If in Lollipop or
181 * future releases, it enables finish with backward shared element animation .
182 */
183 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
184 private void dismiss() {
185 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) finish();
186 else finishAfterTransition();
187 }
188
189 @Override
190 public void onBackPressed() {
191 onClick(mCloseButton);
192 }
193
194 private void updateViews() {
195 BookmarkItem bookmarkItem = mEnhancedBookmarksModel.getBookmarkById(mBoo kmarkId);
196 updateViews(bookmarkItem);
197 }
198
199 /**
200 * Updates each EditText to display the data in bookmarkItem. This function will be called every
201 * time user cancels editing.
202 */
203 private void updateViews(BookmarkItem bookmarkItem) {
204 mTitleEditText.setText(bookmarkItem.getTitle());
205 mUrlEditText.setText(bookmarkItem.getUrl());
206 setParentFolderName(bookmarkItem.getParentId());
207
208 if (bookmarkItem.getId().getType() == BookmarkType.PARTNER) {
209 mUrlEditText.setEnabled(false);
210 mDescriptionEditText.setVisibility(View.GONE);
211 } else {
212 mUrlEditText.setEnabled(true);
213 mDescriptionEditText.setText(
214 mEnhancedBookmarksModel.getBookmarkDescription(mBookmarkId)) ;
215 mDescriptionEditText.setVisibility(View.VISIBLE);
216 }
217
218 mDominantColor = EnhancedBookmarkUtils.generateBackgroundColor(bookmarkI tem);
219 mImageView.setBackgroundColor(mDominantColor);
220 mMaskView.setBackgroundColor(mDominantColor);
221 mEnhancedBookmarksModel.salientImageForUrl(bookmarkItem.getUrl(),
222 new SalientImageCallback() {
223 @Override
224 public void onSalientImageReady(Bitmap bitmap, String imageU rl) {
225 if (bitmap == null) return;
226 mImageView.setImageBitmap(bitmap);
227 mDominantColor = EnhancedBookmarkUtils.getDominantColorF orBitmap(bitmap);
228 mImageView.setBackgroundColor(mDominantColor);
229 mMaskView.setBackgroundColor(mDominantColor);
230 }
231 });
232 mMaskView.setAlpha(0.0f);
233 }
234
235 private void updateAutoFolders() {
236 mAutoFoldersFlowLayout.removeAllViews();
237 String[] filters = mEnhancedBookmarksModel.getFiltersForBookmark(mBookma rkId);
238 for (String filter : filters) {
239 Button autoFolder = new AutoFolderButton(this);
240 autoFolder.setText(filter);
241 mAutoFoldersFlowLayout.addView(autoFolder);
242 }
243 if (mAutoFoldersFlowLayout.getChildCount() > 0) {
244 mAutoFoldersLabel.setVisibility(View.VISIBLE);
245 mAutoFoldersFlowLayout.setVisibility(View.VISIBLE);
246 } else {
247 mAutoFoldersLabel.setVisibility(View.GONE);
248 mAutoFoldersFlowLayout.setVisibility(View.GONE);
249 }
250 }
251
252 private void setParentFolderName(BookmarkId parentId) {
253 mFolderTextView.setText(mEnhancedBookmarksModel.getBookmarkTitle(parentI d));
254 mFolderTextView.setEnabled(parentId.getType() != BookmarkType.PARTNER);
255 }
256
257 @Override
258 public void onClick(View v) {
259 // During animation, do not respond to any clicking events.
260 if (mCurrentAnimator != null) return;
261 if (v == mCloseButton) {
262 if (mIsEditingMode) leaveEditingMode(false);
263 else dismiss();
264 } else if (v == mSaveButton) {
265 if (mIsEditingMode) leaveEditingMode(true);
266 else dismiss();
267 } else if (v instanceof EditText) {
268 if (!mIsEditingMode) enterEditingMode((EditText) v);
269 } else if (v == mFolderBox) {
270 EnhancedBookmarkFolderSelectActivity.startFolderSelectActivity(this, mBookmarkId);
271 } else if (v == mDeleteButton) {
272 mEnhancedBookmarksModel.deleteBookmarks(mBookmarkId);
273 dismiss();
274 }
275 }
276
277 /**
278 * Entering editing mode will trigger scrolling-up animation, as an effort t o smoothly place the
279 * focused EditText to be the best editable position to user. After animatin g, corresponding
280 * EditText will be given a simulated touch event that shows up soft keyboar d and allow user to
281 * edit.
282 * <p>
283 * To ensure the view can always be scrolled up to enter editing mode, befor e animation: 1). If
284 * content is shorter than screen height, then we fill the content view by e mptyAreaHeight so as
285 * to align the content and scroll view. 2). Calculate the scrolling amount. 3). If the
286 * scrolling amount is larger than the current maximum scrollable amount, in crease height of
287 * mBottomSpacer to make the content long enough. 4).trigger scroll-up anima tion.
288 */
289 private void enterEditingMode(final EditText editText) {
290 if (mIsEditingMode) return;
291 mIsEditingMode = true;
292
293 if (DeviceFormFactor.isTablet(this)) {
294 // On tablet this the size of the dialog is controlled by framework. To avoid any
295 // jumpy behavior, we skip the crazy scrolling effect below.
296 animateScrolling(mScrollView.getScrollY(), editText);
297 } else {
298 int scrollAmount = mScrollView.getHeightCompensation() + editText.ge tTop()
299 - mTitleEditText.getTop();
300
301 // If there is not enough space to scroll, create padding at bottom.
302 if (scrollAmount > mScrollView.getMaximumScrollY()) {
303 // First try to align content view and scroll view.
304 int emptyAreaHeight = mScrollView.getHeight() - mContentLayout.g etHeight();
305 if (emptyAreaHeight < 0) emptyAreaHeight = 0;
306 // Then increase height of bottom spacer to create margin for sc roll.
307 setViewHeight(mBottomSpacer,
308 scrollAmount - mScrollView.getMaximumScrollY() + emptyAr eaHeight);
309 }
310
311 animateScrolling(scrollAmount, editText);
312 }
313 }
314
315 private void animateScrolling(int scrollAmount, final EditText editText) {
316 ObjectAnimator animator = ObjectAnimator.ofInt(mScrollView, "scrollY", s crollAmount);
317 animator.setDuration(scrollAmount == mScrollView.getScrollY() ? 0 : ANIM ATION_DURATION_MS);
318 animator.addListener(new AnimatorListenerAdapter() {
319 @Override
320 public void onAnimationEnd(Animator animation) {
321 for (EditText text : mEditTexts) text.setFocusableInTouchMode(tr ue);
322 editText.requestFocus();
323 InputMethodManager imm = (InputMethodManager) getSystemService(
324 Context.INPUT_METHOD_SERVICE);
325 imm.showSoftInput(editText, 0);
326 mCurrentAnimator = null;
327 }
328 });
329 mCurrentAnimator = animator;
330 animator.start();
331 }
332
333 /**
334 * Leaves editing mode and finishes the activity. If shouldSave is set false , all changes will
335 * be reverted.
336 */
337 private void leaveEditingMode(boolean shouldSave) {
338 assert mIsEditingMode;
339
340 String newTitle = mTitleEditText.getText().toString().trim();
341 String newUrl = mUrlEditText.getText().toString().trim();
342 if (shouldSave) {
343 boolean urlOrTitleInvalid = false;
344 // Fix user input urls, if necessary.
345 newUrl = UrlUtilities.fixupUrl(newUrl);
346 if (newUrl == null) newUrl = "";
347 mUrlEditText.setText(newUrl);
348 if (newUrl.isEmpty()) {
349 mUrlEditText.setError(getString(R.string.bookmark_missing_url));
350 urlOrTitleInvalid = true;
351 }
352 if (newTitle.isEmpty()) {
353 mTitleEditText.setError(getString(R.string.bookmark_missing_titl e));
354 urlOrTitleInvalid = true;
355 }
356 if (urlOrTitleInvalid) return;
357 }
358
359 mIsEditingMode = false;
360
361 if (shouldSave) {
362 BookmarkItem bookmarkItem = mEnhancedBookmarksModel.getBookmarkById( mBookmarkId);
363 String newDescription = mDescriptionEditText.getText().toString().tr im();
364 if (!bookmarkItem.getTitle().equals(newTitle)) {
365 mEnhancedBookmarksModel.setBookmarkTitle(mBookmarkId, newTitle);
366 }
367 if (!bookmarkItem.getUrl().equals(newUrl)
368 && bookmarkItem.getId().getType() != BookmarkType.PARTNER) {
369 mEnhancedBookmarksModel.setBookmarkUrl(mBookmarkId, newUrl);
370 }
371 if (bookmarkItem.getId().getType() != BookmarkType.PARTNER) {
372 mEnhancedBookmarksModel.setBookmarkDescription(mBookmarkId, newD escription);
373 }
374 } else {
375 // If user discards change, restore textviews to original values.
376 updateViews();
377 }
378
379 mContentLayout.requestFocus();
380 InputMethodManager imm = (InputMethodManager) getSystemService(
381 Context.INPUT_METHOD_SERVICE);
382 imm.hideSoftInputFromWindow(mTitleEditText.getWindowToken(), 0);
383 // Cancel error state of message
384 mUrlEditText.setError(null);
385 mTitleEditText.setError(null);
386 // Reset all EditTexts to be not focosable to postpone showing keyboard
387 for (EditText editText : mEditTexts) editText.setFocusable(false);
388 mCurrentAnimator = null;
389 if (mBottomSpacer.getHeight() != 0) setViewHeight(mBottomSpacer, 0);
390 dismiss();
391 }
392
393 @Override
394 public void onScrollChanged(int y, int oldY) {
395 int offset = mScrollView.getHeightCompensation();
396 if (y < offset) {
397 mMaskView.setAlpha(y / (float) offset);
398 mActionBarLayout.setBackgroundResource(0);
399 mShadow.setStrength(0.0f);
400 } else {
401 mMaskView.setAlpha(1.0f);
402 mActionBarLayout.setBackgroundColor(mDominantColor);
403 mShadow.setStrength(1.0f);
404 }
405
406 }
407
408 /**
409 * Adds a listener to EditTexts that clears the TextView's error once the us er types something.
410 */
411 private void clearErrorWhenNonEmpty(TextView... textViews) {
412 for (final TextView textView : textViews) {
413 textView.addTextChangedListener(new TextWatcher() {
414 @Override
415 public void beforeTextChanged(CharSequence s, int start, int cou nt, int after) {
416 }
417 @Override
418 public void onTextChanged(CharSequence s, int start, int before, int count) {
419 }
420 @Override
421 public void afterTextChanged(Editable s) {
422 if (s.length() != 0 && textView.getError() != null) textView .setError(null);
423 }
424 });
425 }
426 }
427
428 @Override
429 public void onDestroy() {
430 mEnhancedBookmarksModel.removeModelObserver(mBookmarkModelObserver);
431 mEnhancedBookmarksModel.destroy();
432 mEnhancedBookmarksModel = null;
433 super.onDestroy();
434 }
435
436 @Override
437 public void onFiltersChanged() {
438 updateAutoFolders();
439 }
440
441 private static void setViewHeight(View view, int height) {
442 ViewGroup.LayoutParams lp = view.getLayoutParams();
443 lp.height = height;
444 view.setLayoutParams(lp);
445 }
446
447 /**
448 * Rounded button for auto folders in bookmark detail page.
449 */
450 private static class AutoFolderButton extends Button {
451
452 private static final int TEXT_SIZE_SP = 14;
453
454 public AutoFolderButton(Context context) {
455 super(context);
456 setTextSize(TEXT_SIZE_SP);
457 // Force auto folder buttons smaller than android default size.
458 setMinHeight(0);
459 setMinimumHeight(0);
460 setMinWidth(0);
461 setMinimumWidth(0);
462 setBackgroundResource(R.drawable.btn_enhanced_bookmark_auto_folder);
463 }
464 }
465 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698