• 自定义图片,实现透明度动态变化


    The Use Case

    In Fragment, there are a couple of places where we use horizontal scrollers as a selection view. This means that the center icon is the “selected” icon, and items should transition in and out of this state fluidly. For this we decided that a nice reveal transition would be great.

    While this wasn’t entirely necessary, I felt that it was a effect that made the motion feel very fluid and added a touch of class to the app. I could have set up multiple image views and make parts of them individual, but this was the perfect place for a custom drawables.

    Customizing Drawables

    Drawables in Android are actually very similar to Views. They have similar methods for things like padding and bounds (layout), and have a draw method that can be overridden. In my case, I needed to be able to transition between two drawables, a selected drawable and an unselected drawable, based on a value.

    In our case, we simply create a subclass of Drawable that contains other Drawables (and an orientation).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    public class RevealDrawable extends Drawable {
      public RevealDrawable(Drawable unselected, Drawable selected, int orientation) {
        this(null, null);
    
        mUnselectedDrawable = unselected;
        mSelectedDrawable = selected;
        mOrientation = orientation;
      }
    }
    

    Next we need to be able to set the value identifying where the drawable is in the selection process. Fortunately Drawable has a facility for this type of thing built in, setLevel(int).

    A Drawable’s level is an integer between 0 and 10,000 which simply allows the Drawable to customize it’s view based on a value. In our case, we can simply define 5,000 as the selected state, 0 and entirely unselected to the left, and 10,000 as entirely unselected to the right.

    All we need to do now is to override the draw(Canvas canvas) method to draw the appropriate drawable by clipping the canvas based on the current level.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    
    @Override
    public void draw(Canvas canvas) {
    
      // If level == 10000 || level == 0, just draw the unselected image
      int level = getLevel();
      if (level == 10000 || level == 0) {
        mRevealState.mUnselectedDrawable.draw(canvas);
      }
    
      // If level == 5000 just draw the selected image
      else if (level == 5000) {
        mRevealState.mSelectedDrawable.draw(canvas);
      }
    
      // Else, draw the transitional version
      else {
        final Rect r = mTmpRect;
        final Rect bounds = getBounds();
    
        { // Draw the unselected portion
          float value = (level / 5000f) - 1f;
          int w = bounds.width();
          if ((mRevealState.mOrientation & HORIZONTAL) != 0) {
            w = (int) (w * Math.abs(value));
          }
          int h = bounds.height();
          if ((mRevealState.mOrientation & VERTICAL) != 0) {
            h = (int) (h * Math.abs(value));
          }
          int gravity = value < 0 ? Gravity.LEFT : Gravity.RIGHT;
          Gravity.apply(gravity, w, h, bounds, r);
    
          if (w > 0 && h > 0) {
            canvas.save();
            canvas.clipRect(r);
            mRevealState.mUnselectedDrawable.draw(canvas);
            canvas.restore();
          }
        }
    
        { // Draw the selected portion
          float value = (level / 5000f) - 1f;
          int w = bounds.width();
          if ((mRevealState.mOrientation & HORIZONTAL) != 0) {
            w -= (int) (w * Math.abs(value));
          }
          int h = bounds.height();
          if ((mRevealState.mOrientation & VERTICAL) != 0) {
            h -= (int) (h * Math.abs(value));
          }
          int gravity = value < 0 ? Gravity.RIGHT : Gravity.LEFT;
          Gravity.apply(gravity, w, h, bounds, r);
    
          if (w > 0 && h > 0) {
            canvas.save();
            canvas.clipRect(r);
            mRevealState.mSelectedDrawable.draw(canvas);
            canvas.restore();
          }
        }
      }
    }
    

    With that, we can simply set the level of the icon based on scroll position and away we go.

    1
    2
    3
    4
    5
    6
    
    float offset = getOffestForPosition(recyclerView, position);
    if (Math.abs(offset) <= 1f) {
      holder.image.setImageLevel((int) (offset * 5000) + 5000);
    } else {
      holder.image.setImageLevel(0);
    }
    

    If you’d like to see the source for this custom drawable, you can find the Gist on Github here

    源码: https://gist.github.com/rharter/34051da57f8a6a0991ff

    博客地址:http://ryanharter.com/blog/2015/04/03/custom-drawables/

  • 相关阅读:
    elasticsearch-搜索-定位搜索(十一)
    redis-缓存设计-自动延迟调度,最热商品缓存(二)
    20200925
    20175312 2018-2019-2 实验一《Java开发环境的熟悉》实验报告
    20175312 2018-2019-2 《Java程序设计》结对编程练习_四则运算(第一周:阶段性总结)
    20175312 2018-2019-2 《Java程序设计》第5周学习总结
    20175312陶光远 与 20175309刘雨恒 结对
    20175312 2018-2019-2 《Java程序设计》第4周学习总结
    20175312 2018-2019-2 《Java程序设计》第3周学习总结
    20175312 2018-2019-2 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/spring87/p/4456337.html
Copyright © 2020-2023  润新知