手记

拥有三个类轻轻松松实现3D画廊(二)

——————————————————————————————————————————————————

——————————————————————————————————————————————————
接下是FancyCoverFlowItemWrapper类

package cn.wom.fancycoverflow;

/**

  • 倒影特效
    /
    import android.
    ;
    import android.R;
    import android.annotation.SuppressLint;
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.graphics.*;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;

/**

  • This class has only internal use (package scope).
  • <p/>
  • It is responsible for applying additional effects to each coverflow item, that can only be applied at view level
  • (e.g. color saturation).
  • <p/>
  • This is a ViewGroup by intention to enable child views in layouts to stay interactive (like buttons) though
  • transformed.
  • <p/>
  • Since this class is only used within the FancyCoverFlowAdapter it doesn't need to check if there are multiple
  • children or not (there can only be one at all times).
    */
    @SuppressWarnings("ConstantConditions")
    class FancyCoverFlowItemWrapper extends ViewGroup {

    // =============================================================================
    // Private members
    // =============================================================================

    private float saturation;

    private boolean isReflectionEnabled = false;

    private float imageReflectionRatio;

    private int reflectionGap;

    private float originalScaledownFactor;

    /**

    • This is a matrix to apply color filters (like saturation) to the wrapped view.
      */
      private ColorMatrix colorMatrix;

    /**

    • This paint is used to draw the wrapped view including any filters.
      */
      private Paint paint;

    /**

    • This is a cache holding the wrapped view's visual representation.
      */
      private Bitmap wrappedViewBitmap;

    /**

    • This canvas is used to let the wrapped view draw it's content.
      */
      private Canvas wrappedViewDrawingCanvas;

    // =============================================================================
    // Constructor
    // =============================================================================

    public FancyCoverFlowItemWrapper(Context context) {
    super(context);
    this.init();
    }

    public FancyCoverFlowItemWrapper(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.init();
    }

    public FancyCoverFlowItemWrapper(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.init();
    }

    private void init() {
    this.paint = new Paint();
    this.colorMatrix = new ColorMatrix();
    // TODO: Define a default value for saturation inside an XML.
    this.setSaturation(1);
    }

    // =============================================================================
    // Getters / Setters
    // =============================================================================

    void setReflectionEnabled(boolean hasReflection) {
    if (hasReflection != this.isReflectionEnabled) {
    this.isReflectionEnabled = hasReflection;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // Turn off hardware acceleration if necessary (reflections won't support it).
            this.setLayerType(hasReflection ? View.LAYER_TYPE_SOFTWARE : View.LAYER_TYPE_HARDWARE, null);
        }
    
        this.remeasureChildren();
    }

    }

    void setReflectionRatio(float imageReflectionRatio) {
    if (imageReflectionRatio != this.imageReflectionRatio) {
    this.imageReflectionRatio = imageReflectionRatio;
    this.remeasureChildren();
    }
    }

    void setReflectionGap(int reflectionGap) {
    if (reflectionGap != this.reflectionGap) {
    this.reflectionGap = reflectionGap;
    this.remeasureChildren();
    }
    }

    public void setSaturation(float saturation) {
    if (saturation != this.saturation) {
    this.saturation = saturation;
    this.colorMatrix.setSaturation(saturation);
    this.paint.setColorFilter(new ColorMatrixColorFilter(this.colorMatrix));
    }
    }

    // =============================================================================
    // Supertype overrides
    // =============================================================================

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    this.remeasureChildren();

    // If we have reflection enabled, the original image is scaled down and a reflection is added beneath. Thus,
    // while maintaining the same height the width decreases and we need to adjust measured width.
    // WARNING: This is a hack because we do not obey the EXACTLY MeasureSpec mode that we will get mostly.
    if (this.isReflectionEnabled) {
        this.setMeasuredDimension((int) (this.getMeasuredWidth() * this.originalScaledownFactor), this.getMeasuredHeight());
    }

    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed) {
    int measuredWidth = this.getMeasuredWidth();
    int measuredHeight = this.getMeasuredHeight();

        if (this.wrappedViewBitmap == null  this.wrappedViewBitmap.getWidth() != measuredWidth  this.wrappedViewBitmap.getHeight() != measuredHeight) {
            this.wrappedViewBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
            this.wrappedViewDrawingCanvas = new Canvas(this.wrappedViewBitmap);
        }
    
        View child = getChildAt(0);
        int childWidth = child.getMeasuredWidth();
        int childHeight = child.getMeasuredHeight();
        int childLeft = (measuredWidth - childWidth) / 2;
        int childRight = measuredWidth - childLeft;
        child.layout(childLeft, 0, childRight, childHeight);
    }

    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    protected void dispatchDraw(Canvas canvas) {
    View childView = getChildAt(0);

    if (childView != null) {
        // If on honeycomb or newer, cache the view.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            if (childView.isDirty()) {
                childView.draw(this.wrappedViewDrawingCanvas);
    
                if (this.isReflectionEnabled) {
                    this.createReflectedImages();
                }
            }
        } else {
            childView.draw(this.wrappedViewDrawingCanvas);
        }
    }
    
    canvas.drawBitmap(this.wrappedViewBitmap, (this.getWidth() - childView.getWidth()) / 2, 0, paint);

    }

    // =============================================================================
    // Methods
    // =============================================================================

    private void remeasureChildren() {
    View child = this.getChildAt(0);

    if (child != null) {
        // When reflection is enabled calculate proportional scale down factor.
        final int originalChildHeight = this.getMeasuredHeight();
        this.originalScaledownFactor = this.isReflectionEnabled ? (originalChildHeight * (1 - this.imageReflectionRatio) - reflectionGap) / originalChildHeight : 1.0f;
        final int childHeight = (int) (this.originalScaledownFactor * originalChildHeight);
        final int childWidth = (int) (this.originalScaledownFactor * getMeasuredWidth());
    
        int heightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST);
        int widthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST);
        this.getChildAt(0).measure(widthSpec, heightSpec);
    }

    }

    /**

    • 用于创建Item的倒影
    • */
      private void createReflectedImages() {
      //获取Item的宽度
      final int width = this.wrappedViewBitmap.getWidth();
      //获取Item的高度
      final int height = this.wrappedViewBitmap.getHeight();

      final Matrix matrix = new Matrix();
      matrix.postScale(1, -1);

      //倒影未显示部分的高度
      final int scaledDownHeight = (int) (height * originalScaledownFactor);
      //倒影显示部分的高度
      final int invertedHeight = height - scaledDownHeight - reflectionGap;
      //必须是大于0的数,否则会抛出异常
      final int invertedBitmapSourceTop = scaledDownHeight - invertedHeight;
      //创建翻转的Bitmap对象
      final Bitmap invertedBitmap = Bitmap.createBitmap(this.wrappedViewBitmap, 0, invertedBitmapSourceTop, width, invertedHeight, matrix, true);

      this.wrappedViewDrawingCanvas.drawBitmap(invertedBitmap, 0, scaledDownHeight + reflectionGap, null);

      final Paint paint = new Paint();
      //处理用于线性渐变的对象
      final LinearGradient shader = new LinearGradient(0, height imageReflectionRatio + reflectionGap, 0, height, 0x70ffffff, 0x00ffffff, Shader.TileMode.CLAMP);
      //设置渐变
      paint.setShader(shader);
      //设置模式
      paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
      //绘制矩形,让渐变在矩形中发生
      this.wrappedViewDrawingCanvas.drawRect(0, height
      (1 - imageReflectionRatio), width, height, paint);
      }
      }
      ——————————————————————————————————————————————————
      ——————————————————————————————————————————————————
      最终实现的效果图为

如果想实现下面的效果图

就要在那个图片的资源的那个类里面做文章。

package cn.wom.fancycoverflow.example;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import cn.wom.fancycoverflow.FancyCoverFlow;
import cn.wom.fancycoverflow.FancyCoverFlowAdapter;
import cn.wom.fancycoverflow.R;

public class ViewGroupExample extends Activity {

// =============================================================================
// Supertype overrides
// =============================================================================

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.layout_inflate_example);

    FancyCoverFlow fancyCoverFlow = (FancyCoverFlow) findViewById(R.id.fancyCoverFlow);
    fancyCoverFlow.setAdapter(new ViewGroupExampleAdapter());
}

// =============================================================================
// Private classes
// =============================================================================

private static class ViewGroupExampleAdapter extends FancyCoverFlowAdapter {

    // =============================================================================
    // Private members
    // =============================================================================

    private int[] images = {R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5, R.drawable.image6,};

    // =============================================================================
    // Supertype overrides
    // =============================================================================

    @Override
    public int getCount() {
        return images.length;
    }

    @Override
    public Integer getItem(int i) {
        return images[i];
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getCoverFlowItem(int i, View reuseableView, ViewGroup viewGroup) {
        CustomViewGroup customViewGroup = null;

        if (reuseableView != null) {
            customViewGroup = (CustomViewGroup) reuseableView;
        } else {
            customViewGroup = new CustomViewGroup(viewGroup.getContext());
            customViewGroup.setLayoutParams(new FancyCoverFlow.LayoutParams(300, 600));
        }

        customViewGroup.getImageView().setImageResource(this.getItem(i));
        customViewGroup.getTextView().setText(String.format("Item %d", i));

        return customViewGroup;
    }
}

private static class CustomViewGroup extends LinearLayout {

    // =============================================================================
    // Child views
    // =============================================================================

    private TextView textView;

    private ImageView imageView;

    private Button button;

    // =============================================================================
    // Constructor
    // =============================================================================

    private CustomViewGroup(Context context) {
        super(context);

        this.setOrientation(VERTICAL);

        this.textView = new TextView(context);
        this.imageView = new ImageView(context);
        this.button = new Button(context);

        LinearLayout.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        this.textView.setLayoutParams(layoutParams);
        this.imageView.setLayoutParams(layoutParams);
        this.button.setLayoutParams(layoutParams);

        this.textView.setGravity(Gravity.CENTER);

        this.imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        this.imageView.setAdjustViewBounds(true);

        this.button.setText("Goto GitHub");
        this.button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("https://davidschreiber.github.com/FancyCoverFlow"));
                view.getContext().startActivity(i);
            }
        });

        this.addView(this.textView);
        this.addView(this.imageView);
        this.addView(this.button);
    }

    // =============================================================================
    // Getters
    // =============================================================================

    private TextView getTextView() {
        return textView;
    }

    private ImageView getImageView() {
        return imageView;
    }
}

}

0人推荐
随时随地看视频
慕课网APP