예제 #1
0
  /**
   * Update the Start/Stop text. The button is within a view group with a transition that is needed
   * to animate the button moving. The transition also animates the the text changing, but that
   * animation does not provide a good look and feel. Temporarily disable the view group transition
   * while the text is changing and restore it afterwards.
   *
   * @param parent - View Group holding the start/stop button
   * @param textView - The start/stop button
   * @param text - Start or Stop id
   */
  private void setStartStopText(final ViewGroup parent, TextView textView, int text) {
    final LayoutTransition layoutTransition = parent.getLayoutTransition();
    // Tap into the parent layout->draw flow just before the draw
    ViewTreeObserver viewTreeObserver = parent.getViewTreeObserver();
    if (viewTreeObserver != null) {
      viewTreeObserver.addOnPreDrawListener(
          new ViewTreeObserver.OnPreDrawListener() {
            /**
             * Re-establish the transition handler Remove this listener
             *
             * @return true so that onDraw() is called
             */
            @Override
            public boolean onPreDraw() {
              parent.setLayoutTransition(layoutTransition);
              ViewTreeObserver viewTreeObserver = parent.getViewTreeObserver();
              if (viewTreeObserver != null) {
                viewTreeObserver.removeOnPreDrawListener(this);
              }
              return true;
            }
          });
    }
    // Remove the transition while the text is updated
    parent.setLayoutTransition(null);

    String textStr = getActivity().getResources().getString(text);
    textView.setText(textStr);
    textView.setContentDescription(textStr);
  }
예제 #2
0
  private void initView() {

    textView = (TextView) findViewById(R.id.textview);
    ViewTreeObserver treeObserver = textView.getViewTreeObserver();
    treeObserver.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
          @Override
          public boolean onPreDraw() {
            if (!hasMeasure) {
              maxLines = textView.getLineCount();
              textView.setMaxLines(MAX);
              hasMeasure = true;
            }
            return true;
          }
        });

    textView.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            toggle();
          }
        });
  }
예제 #3
0
  private void fixLayout() {
    ViewTreeObserver obs = fragmentView.getViewTreeObserver();
    obs.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
          @Override
          public boolean onPreDraw() {
            if (fragmentView == null) {
              return true;
            }
            fragmentView.getViewTreeObserver().removeOnPreDrawListener(this);
            LinearLayout layout = (LinearLayout) fragmentView;
            WindowManager manager =
                (WindowManager)
                    ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
            int rotation = manager.getDefaultDisplay().getRotation();

            if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) {
              layout.setOrientation(LinearLayout.HORIZONTAL);
            } else {
              layout.setOrientation(LinearLayout.VERTICAL);
            }

            fragmentView.setPadding(
                fragmentView.getPaddingLeft(),
                0,
                fragmentView.getPaddingRight(),
                fragmentView.getPaddingBottom());
            return true;
          }
        });
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_collage_editor);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    interstitial = new InterstitialAd(this);
    interstitial.setAdUnitId(getString(R.string.interstitial_ad_unit_id));

    // Create ad request.
    AdRequest adRequest = new AdRequest.Builder().build();

    // Begin loading your interstitial.
    interstitial.loadAd(adRequest);

    Intent i = getIntent();
    imgid = i.getIntExtra("frameId", 0);
    typeId = i.getIntExtra("typeId", 0);

    imgBackground = (ImageView) findViewById(R.id.imgBackground);
    imgBackground.setBackgroundResource(imgid);

    ViewTreeObserver vto = imgBackground.getViewTreeObserver();
    //        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    //            @SuppressLint("NewApi")
    //            @SuppressWarnings("deprecation")
    //            @Override
    //            public void onGlobalLayout() {
    //                imgBackgroundWidth = imgBackground.getWidth();
    //                imgBackgroundHeight = imgBackground.getHeight();
    //                GenerateUI();
    //
    //                if (android.os.Build.VERSION.SDK_INT >=
    // android.os.Build.VERSION_CODES.JELLY_BEAN)
    //                    imgBackground.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    //                else
    //                    imgBackground.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    //
    //
    //            }
    //        });

    vto.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
          public boolean onPreDraw() {
            imgBackgroundWidth = imgBackground.getWidth();
            imgBackgroundHeight = imgBackground.getHeight();
            GenerateUI();

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
              imgBackground.getViewTreeObserver().removeOnPreDrawListener(this);
            else imgBackground.getViewTreeObserver().removeOnPreDrawListener(this);

            return true;
          }
        });

    collageEditorRelativeLayout = (RelativeLayout) findViewById(R.id.collageEditorRelativeLayout);
  }
예제 #5
0
  private void initFloatingWindow() {
    mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    mWindow = PolicyManager.makeNewWindow(mContext);
    mWindow.setWindowManager(mWindowManager, null, null);
    mWindow.requestFeature(Window.FEATURE_NO_TITLE);
    mDecor = mWindow.getDecorView();

    /// M: Get measured height of window and update. @{
    ViewTreeObserver vto = mDecor.getViewTreeObserver();
    vto.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
          public boolean onPreDraw() {
            mHeight = mDecor.getMeasuredHeight();
            updateFloatingWindowLayout();
            mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
            mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
            return true;
          }
        });
    /// @}

    mDecor.setOnTouchListener(mTouchListener);
    mWindow.setContentView(this);
    mWindow.setBackgroundDrawableResource(android.R.color.transparent);

    // While the media controller is up, the volume control keys should
    // affect the media stream type
    mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);

    setFocusable(true);
    setFocusableInTouchMode(true);
    setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
    requestFocus();
  }
예제 #6
0
 void getSize(SizeReadyCallback cb) {
   int currentWidth = getViewWidthOrParam();
   int currentHeight = getViewHeightOrParam();
   if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
     int paddingAdjustedWidth =
         currentWidth == WindowManager.LayoutParams.WRAP_CONTENT
             ? currentWidth
             : currentWidth - ViewCompat.getPaddingStart(view) - ViewCompat.getPaddingEnd(view);
     int paddingAdjustedHeight =
         currentHeight == LayoutParams.WRAP_CONTENT
             ? currentHeight
             : currentHeight - view.getPaddingTop() - view.getPaddingBottom();
     cb.onSizeReady(paddingAdjustedWidth, paddingAdjustedHeight);
   } else {
     // We want to notify callbacks in the order they were added and we only expect one or two
     // callbacks to
     // be added a time, so a List is a reasonable choice.
     if (!cbs.contains(cb)) {
       cbs.add(cb);
     }
     if (layoutListener == null) {
       final ViewTreeObserver observer = view.getViewTreeObserver();
       layoutListener = new SizeDeterminerLayoutListener(this);
       observer.addOnPreDrawListener(layoutListener);
     }
   }
 }
예제 #7
0
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    if (convertView == null) {
      LayoutInflater mInflater =
          (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
      convertView = mInflater.inflate(R.layout.specimen_list_item, null);
      viewHolder = new ViewHolder();
      viewHolder.specimenImageView = (ImageView) convertView.findViewById(R.id.specimen_image);
      viewHolder.specimenTitleView = (TextView) convertView.findViewById(R.id.specimen_title);
      viewHolder.specimenScientificName = (TextView) convertView.findViewById(R.id.scientific_name);
      viewHolder.specimenLocality = (TextView) convertView.findViewById(R.id.specimen_locality);
      viewHolder.specimenDescription =
          (TextView) convertView.findViewById(R.id.specimen_description);
      viewHolder.itemLocatedView = (ImageView) convertView.findViewById(R.id.item_located);
      convertView.setTag(viewHolder);
    } else {
      viewHolder = (ViewHolder) convertView.getTag();
    }

    final SpecimenListItem specimenListItem = objects.get(position);
    if (specimenListItem.getImagePath() == null) {
      viewHolder.specimenImageView.setImageResource(specimenListItem.getSpecimenImage());
    } else {
      final ViewTreeObserver vto = viewHolder.specimenImageView.getViewTreeObserver();
      if (vto.isAlive()) {
        vto.addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
              public boolean onPreDraw() {
                if (vto.isAlive()) {
                  vto.removeOnPreDrawListener(this);
                }
                thumbnailHeight = viewHolder.specimenImageView.getMeasuredHeight();
                thumbnailWidth = viewHolder.specimenImageView.getMeasuredWidth();
                if (cancelPotentialWork(
                    specimenListItem.getImagePath(), viewHolder.specimenImageView)) {
                  final LoadThumbnailTask loadThumbnailTask =
                      new LoadThumbnailTask(viewHolder.specimenImageView);
                  final AsyncDrawable asyncDrawable =
                      new AsyncDrawable(resources, bitmapPlaceHolder, loadThumbnailTask);
                  viewHolder.specimenImageView.setImageDrawable(asyncDrawable);
                  thumbnailWidth = viewHolder.specimenImageView.getMeasuredWidth();
                  loadThumbnailTask.execute(specimenListItem.getImagePath());
                }
                return true;
              }
            });
      }
    }
    viewHolder.specimenTitleView.setText(specimenListItem.getSpecimenTitle());
    viewHolder.specimenScientificName.setText(specimenListItem.getScientificName());
    viewHolder.specimenLocality.setText(specimenListItem.getSpecimenLocality());
    viewHolder.specimenDescription.setText(specimenListItem.getSpecimenDescription());
    viewHolder.itemLocatedView.setSelected(specimenListItem.isLocated());
    if (onClickListener != null) {
      viewHolder.specimenImageView.setOnClickListener(onClickListener);
    }

    return convertView;
  }
 public void registerOnPreDrawListener(View v) {
   // Listen for the first draw
   if (mViewTreeObserver == null) {
     mViewTreeObserver = v.getViewTreeObserver();
     mViewTreeObserver.addOnPreDrawListener(this);
   }
 }
 public void setupListener() {
   final ViewTreeObserver viewTreeObserver = mView.getViewTreeObserver();
   if (viewTreeObserver != null) {
     viewTreeObserver.addOnGlobalLayoutListener(this);
     viewTreeObserver.addOnGlobalFocusChangeListener(this);
     viewTreeObserver.addOnPreDrawListener(this);
     viewTreeObserver.addOnScrollChangedListener(this);
     viewTreeObserver.addOnTouchModeChangeListener(this);
   }
 }
예제 #10
0
  public void testDispatchOnPreDraw() {
    final LinearLayout layout = (LinearLayout) mActivity.findViewById(R.id.linearlayout);
    mViewTreeObserver = layout.getViewTreeObserver();

    MockOnPreDrawListener listener = new MockOnPreDrawListener();
    assertFalse(listener.hasCalledOnPreDraw());
    mViewTreeObserver.addOnPreDrawListener(listener);
    mViewTreeObserver.dispatchOnPreDraw();
    assertTrue(listener.hasCalledOnPreDraw());
  }
예제 #11
0
 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
   // TODO Auto-generated method stub
   super.onActivityCreated(savedInstanceState);
   view3 = (SurfaceView) this.getActivity().findViewById(R.id.view_3);
   ViewTreeObserver vto = view3.getViewTreeObserver();
   vto.addOnPreDrawListener(
       new ViewTreeObserver.OnPreDrawListener() {
         public boolean onPreDraw() {
           Data_RW.view_height = view3.getMeasuredHeight();
           Data_RW.view_width = view3.getMeasuredWidth();
           return true;
         }
       });
 }
예제 #12
0
 private void fixLayout() {
   if (listView != null) {
     ViewTreeObserver obs = listView.getViewTreeObserver();
     obs.addOnPreDrawListener(
         new ViewTreeObserver.OnPreDrawListener() {
           @Override
           public boolean onPreDraw() {
             fixLayoutInternal();
             if (listView != null) {
               listView.getViewTreeObserver().removeOnPreDrawListener(this);
             }
             return true;
           }
         });
   }
 }
  private static void sceneChangeRunTransition(
      final ViewGroup sceneRoot, final Transition transition) {
    if (transition != null) {
      final ViewTreeObserver observer = sceneRoot.getViewTreeObserver();
      final ViewTreeObserver.OnPreDrawListener listener =
          new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
              sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
              sPendingTransitions.remove(sceneRoot);
              // Add to running list, handle end to remove it
              final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
                  getRunningTransitions();
              ArrayList<Transition> currentTransitions = runningTransitions.get(sceneRoot);
              ArrayList<Transition> previousRunningTransitions = null;
              if (currentTransitions == null) {
                currentTransitions = new ArrayList<Transition>();
                runningTransitions.put(sceneRoot, currentTransitions);
              } else if (currentTransitions.size() > 0) {
                previousRunningTransitions = new ArrayList<Transition>(currentTransitions);
              }
              currentTransitions.add(transition);
              transition.addListener(
                  new Transition.TransitionListenerAdapter() {
                    @Override
                    public void onTransitionEnd(Transition transition) {
                      ArrayList<Transition> currentTransitions = runningTransitions.get(sceneRoot);
                      currentTransitions.remove(transition);
                    }
                  });
              transition.captureValues(sceneRoot, false);
              if (previousRunningTransitions != null) {
                for (Transition runningTransition : previousRunningTransitions) {
                  runningTransition.resume();
                }
              }
              transition.playTransition(sceneRoot);

              return true;
            }
          };
      observer.addOnPreDrawListener(listener);
    }
  }
  public AsymmetricGridView(final Context context, final AttributeSet attrs) {
    super(context, attrs);

    defaultPadding = Utils.dpToPx(context, 5);
    requestedHorizontalSpacing = defaultPadding;
    requestedVerticalSpacing = defaultPadding;
    padding = new Rect(defaultPadding, defaultPadding, defaultPadding, defaultPadding);

    final ViewTreeObserver vto = getViewTreeObserver();
    if (vto != null)
      vto.addOnPreDrawListener(
          new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
              getViewTreeObserver().removeOnPreDrawListener(this);
              determineColumns();
              if (gridAdapter != null) gridAdapter.notifyDataSetChanged();
              return false;
            }
          });
  }
  private void toggle(final boolean visible, final boolean animate, boolean force) {
    if (mVisible != visible || force) {
      mVisible = visible;
      int height = getHeight();
      if (height == 0 && !force) {
        ViewTreeObserver vto = getViewTreeObserver();
        if (vto.isAlive()) {
          vto.addOnPreDrawListener(
              new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                  ViewTreeObserver currentVto = getViewTreeObserver();
                  if (currentVto.isAlive()) {
                    currentVto.removeOnPreDrawListener(this);
                  }
                  toggle(visible, animate, true);
                  return true;
                }
              });
          return;
        }
      }
      int translationY = visible ? 0 : height + getMarginBottom();
      if (animate) {
        animate()
            .setInterpolator(mInterpolator) //
            .setDuration(TRANSLATE_DURATION_MILLIS) //
            .translationY(translationY);

      } else {
        setTranslationY(translationY);
      }

      // On pre-Honeycomb a translated view is still clickable, so we need
      // to disable clicks manually
      if (!hasHoneycombApi()) {
        setClickable(visible);
      }
    }
  }
 private void fixLayout() {
   ViewTreeObserver obs = fragmentView.getViewTreeObserver();
   obs.addOnPreDrawListener(
       new ViewTreeObserver.OnPreDrawListener() {
         @Override
         public boolean onPreDraw() {
           fragmentView.getViewTreeObserver().removeOnPreDrawListener(this);
           if (listAdapter != null) {
             listAdapter.notifyDataSetChanged();
           }
           if (listView != null) {
             listView.post(
                 new Runnable() {
                   @Override
                   public void run() {
                     listView.scrollTo(0);
                   }
                 });
           }
           return false;
         }
       });
 }
예제 #17
0
  /**
   * This method collapses the view that was clicked and animates all the views around it to close
   * around the collapsing view. There are several steps required to do this which are outlined
   * below.
   *
   * <p>1. Update the layout parameters of the view clicked so as to minimize its height to the
   * original collapsed (default) state. 2. After invoking a layout, the listview will shift all the
   * cells so as to display them most efficiently. Therefore, during the first predraw pass, the
   * listview must be offset by some amount such that given the custom bound change upon collapse,
   * all the cells that need to be on the screen after the layout are rendered by the listview. 3.
   * On the second predraw pass, all the items are first returned to their original location (before
   * the first layout). 4. The collapsing view's bounds are animated to what the final values should
   * be. 5. The bounds above the collapsing view are animated downwards while the bounds below the
   * collapsing view are animated upwards. 6. The extra text is faded out as its contents become
   * visible throughout the animation process.
   */
  private void prepareCollapseView(final CardView view, final View expandingLayout) {
    final Card card = (Card) getItemAtPosition(getPositionForView(view));

    /* Store the original top and bottom bounds of all the cells.*/
    final int oldTop = view.getTop();
    final int oldBottom = view.getBottom();

    final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();

    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (Build.VERSION.SDK_INT >= 16) {
        v.setHasTransientState(true);
      }
      oldCoordinates.put(v, new int[] {v.getTop(), v.getBottom()});
    }

    /* Update the layout so the extra content becomes invisible.*/
    view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, view.getCollapsedHeight()));

    /* Add an onPreDraw listener. */
    final ViewTreeObserver observer = getViewTreeObserver();
    observer.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {

          @Override
          public boolean onPreDraw() {

            if (!mShouldRemoveObserver) {
              /*Same as for expandingView, the parameters for setSelectionFromTop must
               * be determined such that the necessary cells of the ListView are rendered
               * and added to it.*/
              mShouldRemoveObserver = true;

              int newTop = view.getTop();
              int newBottom = view.getBottom();

              int newHeight = newBottom - newTop;
              int oldHeight = oldBottom - oldTop;
              int deltaHeight = oldHeight - newHeight;

              mTranslate = getTopAndBottomTranslations(oldTop, oldBottom, deltaHeight, false);

              int currentTop = view.getTop();
              int futureTop = oldTop + mTranslate[0];

              int firstChildStartTop = getChildAt(0).getTop();
              int firstVisiblePosition = getFirstVisiblePosition();
              int deltaTop = currentTop - futureTop;

              int i;
              int childCount = getChildCount();
              for (i = 0; i < childCount; i++) {
                View v = getChildAt(i);
                int height = v.getBottom() - Math.max(0, v.getTop());
                if (deltaTop - height > 0) {
                  firstVisiblePosition++;
                  deltaTop -= height;
                } else {
                  break;
                }
              }

              if (i > 0) {
                firstChildStartTop = 0;
              }

              setSelection(firstVisiblePosition);
              // setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);

              requestLayout();

              return false;
            }

            mShouldRemoveObserver = false;
            observer.removeOnPreDrawListener(this);

            int yTranslateTop = mTranslate[0];
            int yTranslateBottom = mTranslate[1];

            int index = indexOfChild(view);
            int numOfColumns = getNumColumns();
            int rowOfSelectedItem = (int) index / numOfColumns;

            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
              View v = getChildAt(i);
              int[] old = oldCoordinates.get(v);
              if (old != null) {
                /* If the cell was present in the ListView before the collapse and
                 * after the collapse then the bounds are reset to their old values.*/
                v.setTop(old[0]);
                v.setBottom(old[1]);
                if (Build.VERSION.SDK_INT >= 16) {
                  v.setHasTransientState(false);
                }
              } else {
                /* If the cell is present in the ListView after the collapse but
                 * not before the collapse then the bounds are calculated using
                 * the bottom and top translation of the collapsing cell.*/
                int rowOfv = (int) i / numOfColumns;
                int delta =
                    (i > index && rowOfv > rowOfSelectedItem) ? yTranslateBottom : -yTranslateTop;
                v.setTop(v.getTop() + delta);
                v.setBottom(v.getBottom() + delta);
              }
            }

            /* Animates all the cells present on the screen after the collapse. */
            ArrayList<Animator> animations = new ArrayList<Animator>();
            for (int i = 0; i < childCount; i++) {
              View v = getChildAt(i);
              if (v != view) {
                float diff = i > index ? -yTranslateBottom : yTranslateTop;
                animations.add(getAnimation(v, diff, diff));
              }
            }

            /*
            ValueAnimator animator = ValueAnimator.ofInt( yTranslateTop,-yTranslateBottom);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    int value = (Integer) valueAnimator.getAnimatedValue();

                    ViewGroup.LayoutParams layoutParams = expandingLayout.getLayoutParams();
                    layoutParams.height = value;
                    expandingLayout.setLayoutParams(layoutParams);
                }
            });
            animations.add(animator);*/

            /* Adds animation for collapsing the cell that was clicked. */
            animations.add(getAnimation(view, yTranslateTop, -yTranslateBottom));

            /* Adds an animation for fading out the extra content. */
            animations.add(ObjectAnimator.ofFloat(expandingLayout, ALPHA, 1, 0));

            /* Disabled the ListView for the duration of the animation.*/
            setEnabled(false);
            setClickable(false);

            /* Play all the animations created above together at the same time. */
            AnimatorSet s = new AnimatorSet();
            s.playTogether(animations);
            s.addListener(
                new AnimatorListenerAdapter() {
                  @Override
                  public void onAnimationEnd(Animator animation) {
                    expandingLayout.setVisibility(View.GONE);
                    view.setLayoutParams(
                        new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
                    view.setExpanded(false);
                    setEnabled(true);
                    setClickable(true);
                    /* Note that alpha must be set back to 1 in case this view is reused
                     * by a cell that was expanded, but not yet collapsed, so its state
                     * should persist in an expanded state with the extra content visible.*/
                    expandingLayout.setAlpha(1);

                    if (card.getOnCollapseAnimatorEndListener() != null)
                      card.getOnCollapseAnimatorEndListener().onCollapseEnd(card);
                  }
                });
            s.start();

            return true;
          }
        });
  }
예제 #18
0
  private void prepareExpandView(final CardView view, final View expandingLayout) {
    final Card card = (Card) getItemAtPosition(getPositionForView(view));

    /* Store the original top and bottom bounds of all the cells.*/
    final int oldTop = view.getTop();
    final int oldBottom = view.getBottom();

    final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();

    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
      View v = getChildAt(i);
      if (Build.VERSION.SDK_INT >= 16) {
        v.setHasTransientState(true);
      }
      oldCoordinates.put(v, new int[] {v.getTop(), v.getBottom()});
    }

    /* Update the layout so the extra content becomes visible.*/
    if (expandingLayout != null) expandingLayout.setVisibility(View.VISIBLE);

    /* Add an onPreDraw Listener to the listview. onPreDraw will get invoked after onLayout
     * and onMeasure have run but before anything has been drawn. This
     * means that the final post layout properties for all the items have already been
     * determined, but still have not been rendered onto the screen.*/
    final ViewTreeObserver observer = getViewTreeObserver();
    observer.addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {

          @Override
          public boolean onPreDraw() {
            /* Determine if this is the first or second pass.*/
            if (!mShouldRemoveObserver) {
              mShouldRemoveObserver = true;

              /* Calculate what the parameters should be for setSelectionFromTop.
               * The ListView must be offset in a way, such that after the animation
               * takes place, all the cells that remain visible are rendered completely
               * by the ListView.*/
              int newTop = view.getTop();
              int newBottom = view.getBottom();

              int newHeight = newBottom - newTop;
              int oldHeight = oldBottom - oldTop;
              int delta = newHeight - oldHeight;

              mTranslate = getTopAndBottomTranslations(oldTop, oldBottom, delta, true);

              int currentTop = view.getTop();
              int futureTop = oldTop - mTranslate[0];

              int firstChildStartTop = getChildAt(0).getTop();
              int firstVisiblePosition = getFirstVisiblePosition();
              int deltaTop = currentTop - futureTop;

              int i;
              int childCount = getChildCount();
              for (i = 0; i < childCount; i++) {
                View v = getChildAt(i);
                int height = v.getBottom() - Math.max(0, v.getTop());
                if (deltaTop - height > 0) {
                  firstVisiblePosition++;
                  deltaTop -= height;
                } else {
                  break;
                }
              }

              if (i > 0) {
                firstChildStartTop = 0;
              }

              setSelection(firstVisiblePosition);
              // setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);

              /* Request another layout to update the layout parameters of the cells.*/
              requestLayout();

              /* Return false such that the ListView does not redraw its contents on
               * this layout but only updates all the parameters associated with its
               * children.*/
              return false;
            }

            /* Remove the predraw listener so this method does not keep getting called. */
            mShouldRemoveObserver = false;
            observer.removeOnPreDrawListener(this);

            int yTranslateTop = mTranslate[0];
            int yTranslateBottom = mTranslate[1];

            ArrayList<Animator> animations = new ArrayList<Animator>();

            int index = indexOfChild(view);
            int numOfColumns = getNumColumns();
            int rowOfSelectedItem = (int) index / numOfColumns;

            /* Loop through all the views that were on the screen before the cell was
             *  expanded. Some cells will still be children of the ListView while
             *  others will not. The cells that remain children of the ListView
             *  simply have their bounds animated appropriately. The cells that are no
             *  longer children of the ListView also have their bounds animated, but
             *  must also be added to a list of views which will be drawn in dispatchDraw.*/
            for (View v : oldCoordinates.keySet()) {
              int[] old = oldCoordinates.get(v);
              v.setTop(old[0]);
              v.setBottom(old[1]);
              if (v.getParent() == null) {
                mViewsToDraw.add(v);
                int delta = old[0] < oldTop ? -yTranslateTop : yTranslateBottom;
                animations.add(getAnimation(v, delta, delta));
              } else {
                int i = indexOfChild(v);
                if (v != view) {
                  int rowOfv = (int) i / numOfColumns;
                  int delta =
                      (i > index && rowOfv > rowOfSelectedItem) ? yTranslateBottom : -yTranslateTop;
                  animations.add(getAnimation(v, delta, delta));
                }
                v.setHasTransientState(false);
              }
            }

            /* Adds animation for expanding the cell that was clicked. */
            animations.add(getAnimation(view, -yTranslateTop, yTranslateBottom));

            /* Adds an animation for fading in the extra content. */
            animations.add(ObjectAnimator.ofFloat(expandingLayout, ALPHA, 0, 1));

            /* Disabled the ListView for the duration of the animation.*/
            setEnabled(false);
            setClickable(false);

            /* Play all the animations created above together at the same time. */
            AnimatorSet s = new AnimatorSet();
            s.playTogether(animations);
            s.addListener(
                new AnimatorListenerAdapter() {
                  @Override
                  public void onAnimationEnd(Animator animation) {
                    view.setExpanded(true); // card.setExpanded(true);
                    setEnabled(true);
                    setClickable(true);
                    if (mViewsToDraw.size() > 0) {
                      for (View v : mViewsToDraw) {
                        if (Build.VERSION.SDK_INT >= 16) {
                          v.setHasTransientState(false);
                        }
                      }
                    }
                    mViewsToDraw.clear();

                    if (card.getOnExpandAnimatorEndListener() != null)
                      card.getOnExpandAnimatorEndListener().onExpandEnd(card);
                  }
                });
            s.start();
            return true;
          }
        });
  }
  /**
   * This method determines whether the hover cell has been shifted far enough to invoke a cell
   * swap. If so, then the respective cell swap candidate is determined and the data set is changed.
   * Upon posting a notification of the data set change, a layout is invoked to place the cells in
   * the right place. Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can offset
   * the cell being swapped to where it previously was and then animate it to its new position.
   */
  private void handleCellSwitch() {
    final int deltaY = mLastEventY - mDownY;
    int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;

    View belowView = getViewForId(mBelowItemId);
    View mobileView = getViewForId(mMobileItemId);
    View aboveView = getViewForId(mAboveItemId);

    boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
    boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());

    if (isBelow || isAbove) {

      final long switchItemId = isBelow ? mBelowItemId : mAboveItemId;
      View switchView = isBelow ? belowView : aboveView;
      final int originalItem = getPositionForView(mobileView);

      if (switchView == null) {
        updateNeighborViewsForId(mMobileItemId);
        return;
      }

      if (getPositionForView(switchView) < getHeaderViewsCount()) {
        return;
      }
      swapElements(originalItem, getPositionForView(switchView));

      BaseAdapter adapter;
      if (getAdapter() instanceof HeaderViewListAdapter) {
        adapter = (BaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter();
      } else {
        adapter = (BaseAdapter) getAdapter();
      }
      adapter.notifyDataSetChanged();

      mDownY = mLastEventY;
      mDownX = mLastEventX;

      final int switchViewStartTop = switchView.getTop();

      mobileView.setVisibility(View.VISIBLE);
      switchView.setVisibility(View.INVISIBLE);

      updateNeighborViewsForId(mMobileItemId);

      final ViewTreeObserver observer = getViewTreeObserver();
      observer.addOnPreDrawListener(
          new ViewTreeObserver.OnPreDrawListener() {
            public boolean onPreDraw() {
              observer.removeOnPreDrawListener(this);

              View switchView = getViewForId(switchItemId);

              mTotalOffset += deltaY;

              int switchViewNewTop = switchView.getTop();
              int delta = switchViewStartTop - switchViewNewTop;

              ViewHelper.setTranslationY(switchView, delta);

              ObjectAnimator animator = ObjectAnimator.ofFloat(switchView, "translationY", 0);
              animator.setDuration(MOVE_DURATION);
              animator.start();

              return true;
            }
          });
    }
  }
예제 #20
0
        private void animateRemoval(final ListView listview, View viewToRemove) {
          int firstVisiblePosition = listview.getFirstVisiblePosition();
          for (int i = 0; i < listview.getChildCount(); ++i) {
            View child = listview.getChildAt(i);
            if (child != viewToRemove) {
              int position = firstVisiblePosition + i;
              long itemId = listview.getAdapter().getItemId(position);
              mItemIdTopMap.put(itemId, child.getTop());
            }
          }
          // Delete the item from the adapter
          LocalAdapter.ChildViewHolder childViewHolder =
              (LocalAdapter.ChildViewHolder) viewToRemove.getTag();
          ((LocalAdapter) getExpandableListAdapter())
              .remove(childViewHolder.groupPosition, viewToRemove);
          new WriteToDatabaseTask(LocalLyricsFragment.this)
              .execute(LocalLyricsFragment.this, null, childViewHolder.lyrics);

          final ViewTreeObserver observer = listview.getViewTreeObserver();
          observer.addOnPreDrawListener(
              new ViewTreeObserver.OnPreDrawListener() {
                public boolean onPreDraw() {
                  observer.removeOnPreDrawListener(this);
                  boolean firstAnimation = true;
                  int firstVisiblePosition = listview.getFirstVisiblePosition();
                  for (int i = 0; i < listview.getChildCount(); ++i) {
                    final View child = listview.getChildAt(i);
                    int position = firstVisiblePosition + i;
                    long itemId = getListView().getAdapter().getItemId(position);
                    Integer formerTop = mItemIdTopMap.get(itemId);
                    int newTop = child.getTop();
                    if (formerTop != null) {
                      if (formerTop != newTop) {
                        int delta = formerTop - newTop;
                        child.setTranslationY(delta);
                        int MOVE_DURATION = 500;
                        child.animate().setDuration(MOVE_DURATION).translationY(0);
                        if (firstAnimation) {
                          child
                              .animate()
                              .setListener(
                                  new AnimatorActionListener(
                                      new Runnable() {
                                        public void run() {
                                          mBackgroundContainer.hideBackground();
                                          mSwiping = false;
                                          getListView().setEnabled(true);
                                        }
                                      },
                                      AnimatorActionListener.ActionType.END));
                          firstAnimation = false;
                        }
                      }
                    } else {
                      // Animate new views along with the others. The catch is that they did not
                      // exist in the start state, so we must calculate their starting position
                      // based on neighboring views.
                      int childHeight = child.getHeight() + listview.getDividerHeight();
                      formerTop = newTop + (i > 0 ? childHeight : -childHeight);
                      int delta = formerTop - newTop;
                      child.setTranslationY(delta);
                      int MOVE_DURATION = 500;
                      child.animate().setDuration(MOVE_DURATION).translationY(0);
                      if (firstAnimation) {
                        child
                            .animate()
                            .setListener(
                                new AnimatorActionListener(
                                    new Runnable() {
                                      public void run() {
                                        mBackgroundContainer.hideBackground();
                                        mSwiping = false;
                                        getListView().setEnabled(true);
                                      }
                                    },
                                    AnimatorActionListener.ActionType.END));
                        firstAnimation = false;
                      }
                    }
                  }
                  mBackgroundContainer.hideBackground();
                  mItemIdTopMap.clear();
                  return true;
                }
              });
        }