安卓 : Restoring recyclerview parallax

标签 android parallax android-recyclerview state-restoration

我尝试使用回收器 View 编写我自己的视差效果。它目前工作得很好......直到我不改变我的设备方向。

在状态恢复时,我取回了我用来计算标题 Y 翻译的“指标”变量,这没问题。 但是在恢复后我很难从不同的角度获得高度。

基本上这是我记录的内容:

D/parallax﹕ gridHeight: 0 - toolbar: 0 - poster: 0

我尝试使用 .measure() 然后使用 getMeasuredHeight() 但这是我得到的:

D/parallax﹕ gridHeight: 0 - toolbar: 128 - poster: 1108

也许我误用了 Measure。或者也许我应该在另一个时刻使用我的视差方法? (运行时的衣服?)如果你有任何线索......

这是我阅读一年后的第一个问题。希望我这样做的好方法。并感谢您的帮助 ;)

这是我的代码:

public class ParallaxActivity extends Activity {

    private int                     metrics = 0;
    private int                     resize = 0;
    private int                     gridHeight = -1;
    private int                     toolbarHeight = -1;
    private int                     posterHeight = -1;
    private boolean                 docked = false;

    private Toolbar                 toolbar;
    private ImageView               poster;
    private LinearLayout            header;
    private RecyclerView            grid;
    private RecyclerView.LayoutManager  manager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_parallax2);

    toolbar = (Toolbar)findViewById(R.id.toolbar_actionbar);
    toolbar.setNavigationIcon(R.drawable.ic_launcher);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

    poster = (ImageView)findViewById(R.id.poster);
    grid = (RecyclerView)findViewById(R.id.list);
    header = (LinearLayout)findViewById(R.id.header);

    manager = new GridLayoutManager(this, 2);
    grid.setLayoutManager(manager);
    DefaultItemAnimator animator = new DefaultItemAnimator();
    grid.setItemAnimator(animator);
    RecyclerGridAdapter ad = new RecyclerGridAdapter(this);
    grid.setAdapter(ad);
    ad.update();

    grid.setOnScrollListener(new RecyclerView.OnScrollListener()
    {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            metrics += dy / 3;
            parallax();
        }
    });
}

@Override
protected void onSaveInstanceState(Bundle b)
{
    super.onSaveInstanceState(b);
    b.putInt("metrics", metrics);
}

@Override
protected void onRestoreInstanceState(Bundle b)
{
    super.onRestoreInstanceState(b);
    metrics = b.getInt("metrics", 0);
}

@Override
public void onAttachedToWindow()
{
    if (metrics != 0)
        parallax();
}

private void parallax()
{
    if (gridHeight == -1)
    {
        gridHeight = grid.getHeight();
        toolbarHeight = toolbar.getHeight();
        posterHeight = poster.getHeight();
        Log.d("parallax", "gridHeight: " + gridHeight + " - toolbar: " + toolbarHeight + " - poster: " + posterHeight);
    }
    if (!docked && metrics > posterHeight - toolbarHeight)
    {
        docked = true;
        toolbar.setBackgroundColor(0xff000000);
    }
    if (docked && metrics < posterHeight - toolbarHeight)
    {
        docked = false;
        toolbar.setBackgroundColor(0x00000000);
    }

    if (metrics < 0)
        resize = 0;
    else if ( metrics > posterHeight - toolbarHeight)
        resize = posterHeight - toolbarHeight;
    else
        resize = metrics;

    header.setTranslationY(-resize);
    grid.setTranslationY(-resize);
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) grid.getLayoutParams();
    params.height = gridHeight + resize;
    grid.setLayoutParams(params);
}
}

和我的布局:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_actionbar"
    android:background="@null"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="5dp" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
    android:id="@+id/header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:elevation="0dp">

        <ImageView
            android:id="@+id/poster"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="centerCrop"
            android:adjustViewBounds="true"
            android:src="@drawable/jpeg"/>
        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="SerieKids"
            android:textSize="20dp"
            android:textColor="#ffffff"
            android:background="#000000"
            android:paddingStart="100dp"/>
</LinearLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"/>
</LinearLayout>
</RelativeLayout>

最后是我使用 measure() 的方式

if (gridHeight == -1)
{
    toolbar.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    poster.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    grid.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

    gridHeight = grid.getMeasuredHeight();
    toolbarHeight = toolbar.getMeasuredHeight();
    posterHeight = poster.getMeasuredHeight();
    Log.d("parallax", "gridHeight: " + gridHeight + " - toolbar: " + toolbarHeight + " - poster: " + posterHeight);
}

最佳答案

onGlobalLayoutListener 添加到您的 RecyclerView。这样您就可以确保您的 parallax 例程仅在您的 View 被完全绘制后才被调用。还要确保取消注册 globalLayout,否则每次绘制 View 时都会调用它(如果您使用它来控制旋转变化,那么我认为无需删除监听器。这样它会一直旋转时调用,因为布局将再次绘制)。

如何注册和取消注册布局监听器的示例:

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                       view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                       view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                   //your parallax routine here
                }
            });

关于安卓 : Restoring recyclerview parallax,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26807370/

相关文章:

java - Textview 值必须使用 if 语句更改 itemView 背景颜色

java - 向上或向下滚动时,recyclerview 无法正常工作

android - 如何让 Espresso 点击特定的 RecyclerView item?

javascript - 如果滚动超过 bg 图像大小,则视差停止背景图像 pos 更改

android - 如何在 Android 中转换日期

html - 视差滚动内容样式

javascript - 无法在标题图片上获得 skrollr 视差效果

android - 如何延迟从 RecyclerView 中删除项目

android - 设置 SearchView 清除按钮颜色

android - 如何在用户输入后过滤 Android MVVM 架构中的 LiveData?