仿蜻蜓FM专辑页面滑动特效

用户要求一个特效,做了一个Demo,分享一下。

这里写图片描述

1.罗列代码

  • ListView headView布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <View
        android:id="@+id/placeholder_top"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@android:color/transparent" />
    <View
        android:id="@+id/placeholder_sticky"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
</LinearLayout>
  • 主布局文件
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <View
        android:id="@+id/top"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/ic_launcher" />
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
    <TextView
        android:id="@+id/sticky"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#00ffff"
        android:gravity="center"
        android:textColor="#ff0000"
        android:text="Sticky"
        android:textSize="20sp" />
</FrameLayout>
  • 主代码
package com.example.android.listviewscrolltrick;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.listviewscrolltrick.R;

public class MainActivity extends Activity {

    private TextView mStickyView;
    private View mPlaceHolderSticky;
    private ListView mListView;
    private View mTopView;

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mStickyView = (TextView) findViewById(R.id.sticky);
        mListView = (ListView) findViewById(R.id.listView);
        mTopView = findViewById(R.id.top);

        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View headView = inflater.inflate(R.layout.layout_headview, null);

        mPlaceHolderSticky = headView.findViewById(R.id.placeholder_sticky);
        mListView.addHeaderView(headView);

        mListView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @SuppressLint("NewApi")
                    @SuppressWarnings("deprecation")
                    @Override
                    public void onGlobalLayout() {
                        onScrollChanged();
                        ViewTreeObserver obs = mListView.getViewTreeObserver();
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            obs.removeOnGlobalLayoutListener(this);
                        } else {
                            obs.removeGlobalOnLayoutListener(this);
                        }
                    }
                });

        mListView.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                onScrollChanged();
            }
        });
        List<String> dataSource = new ArrayList<String>();
        for (int j = 0; j < 20; j++) {
            dataSource.add("item-----" + j);
        }
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, dataSource);
        mListView.setAdapter(arrayAdapter);
    }

    private void onScrollChanged() {
        View v = mListView.getChildAt(0);
        int top = (v == null) ? 0 : v.getTop();

        if (mListView.getFirstVisiblePosition() == 0) {
            mStickyView.setTranslationY(Math.max(mPlaceHolderSticky.getTop()
                    + top, 0));
            mTopView.setTranslationY(top);
        }

    }
}

2.大致原理讲解

  • ListView headView存在两块区域:R.id.placeholder_top /R.id.placeholder_sticky
    这两者是“地下工作者”,他们分别与mTopView/mStickView对应——高度相同,颜色透明

  • ListView加载完成后,调整mTopView/mStickView组件的位置

  • ListView滑动时,调整mTopView&&mStickyView的位置

3.结合源代码对原理进行深入讲解

  • 初始阶段位置的调整
    对ListView加载完成进行监听
    注意:要取消监听
mListView.getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
                    @SuppressLint("NewApi")
                    @SuppressWarnings("deprecation")
                    @Override
                    public void onGlobalLayout() {
                        onScrollChanged();
                        ViewTreeObserver obs = mListView.getViewTreeObserver();
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                            obs.removeOnGlobalLayoutListener(this);
                        } else {
                            obs.removeGlobalOnLayoutListener(this);
                        }
                    }
                });
  • 根据ListView中headView中的对应部分 ,设置mTopView/mStickView位置

    private void onScrollChanged() {
        View v = mListView.getChildAt(0);
        int top = (v == null) ? 0 : v.getTop();

        if (mListView.getFirstVisiblePosition() == 0) {
            mStickyView.setTranslationY(Math.max(mPlaceHolderSticky.getTop()
                    + top, 0));
            mTopView.setTranslationY(top);
        }

    }

由于mStickyView要一直显示在可见范围内,所以mStickyView.setTranslationY一定不能为负数.

  • ListView滑动

监听ListView滑动,调整mTopView/mStickView的位置(同上)

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                onScrollChanged();
            }
        });

3.Demo下载

http://download.csdn.net/detail/guchuanhang/9515429

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值