简单视差特效的实现

基本思路:

   1. 自定义ListView,在对应的activity中创建headerView,并添加到listview中,由于只需要改变背景图片的大小,所以只需要将imageView的引用传递给自定义的ListView,让其控制。

    2. 在自定义listview总重新overScrollBy()方法。

    3. 重写onTouchEvent()方法,当UP的时候,通过属性动画,将imageView的高度还原为原始高度。

实现代码:

   

public class ParallaxListviw extends ListView {
    private ImageView mImageView;
    private int mOriginalHeight;// imageView的原始高度
    private int mDrawableHeight;//背景图片的高度
    private int mNewHeight;//imageView的动态高度

    public ParallaxListviw(Context context) {
        super(context);
    }

    public ParallaxListviw(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ParallaxListviw(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setImageView(ImageView imageView){
        this.mImageView = imageView;
        if (mImageView != null){//由于imageview是在oncreate方法中设置的,因此在布局画完之后测量对应高度,否则无法得到
            mImageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    mOriginalHeight = mImageView.getMeasuredHeight();
                    mDrawableHeight = mImageView.getDrawable().getIntrinsicHeight();
                    mImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            });

        }
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        if (deltaY < 0 && isTouchEvent){
            mNewHeight = mImageView.getHeight() + Math.abs(deltaY);
            if (mNewHeight <= mDrawableHeight){
                mImageView.getLayoutParams().height = mNewHeight;
                mImageView.requestLayout();
            }
        }

        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP){
            ValueAnimator valueAnimator = ValueAnimator.ofInt(mImageView.getHeight(), mOriginalHeight);
            valueAnimator.setDuration(500);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    mImageView.getLayoutParams().height = (int) valueAnimator.getAnimatedValue();
                    mImageView.requestLayout();
                }
            });
            valueAnimator.setInterpolator(new OvershootInterpolator(3));
            valueAnimator.start();
        }
        return super.onTouchEvent(ev);
    }
}
在activity中的设置:

public class MainActivity extends Activity {

    private ParallaxListviw mPlv;
    private ImageView mIv_header;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPlv = (ParallaxListviw)findViewById(R.id.plv);
        View header = View.inflate(this,R.layout.headerview,null);
        mIv_header = (ImageView) header.findViewById(R.id.iv_header);
        mPlv.setImageView(mIv_header);
        ArrayAdapter arrayAdapter = new ArrayAdapter(this,R.layout.item,new String[]{"毛衣","衬衫","羽绒服"});
        mPlv.addHeaderView(header);
        mPlv.setAdapter(arrayAdapter);
    }

}

    翻看大神的博客,发现,使用重写该方法实现下拉回弹,实际应用中bug一堆,只能做学习使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现Unity3D视差Shader的一般步骤如下: 1. 在ShaderLab中创建一个新的shader,并指定渲染队列。 2. 在CG程序中编写实现视差效果的代码。通常,这涉及到计算纹理坐标的偏移量,根据深度信息计算出位移量。最终,将位移量添加到纹理坐标中,使纹理随着深度变化而产生位移。 下面是一个简单视差Shader代码示例: Shader "Custom/Parallax" { Properties { _MainTex ("Texture", 2D) = "white" {} _BumpMap ("BumpMap", 2D) = "bump" {} _Parallax ("Parallax", Range(0, 1)) = 0.02 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque"} Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 texcoord : TEXCOORD0; }; struct v2f { float2 texcoord : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _BumpMap; float _Parallax; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; return o; } fixed4 frag (v2f i) : SV_Target { float2 uv = i.texcoord; float depth = tex2D(_BumpMap, uv).r; float2 offset = normalize(i.vertex.xy / i.vertex.w - i.texcoord) * depth * _Parallax; uv += offset; return tex2D(_MainTex, uv); } ENDCG } } FallBack "Diffuse" } 这个Shader使用了一张主纹理和一张法线贴图,同时增加了一个Parallax参数。在片段着色器中,使用法线贴图中的深度信息计算位移量,并将其添加到纹理坐标中,产生视差效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值