Android — исправлен заголовок над scrollview с эффектом масштабирования

#java #android

#java #Android

Вопрос:

в настоящее время я переписываю наше приложение с ios на Android и не могу добиться надлежащего эффекта для работы. Итак, в iOS мы использовали эту библиотеку для достижения фиксированного заголовка над scrollview содержимого с эффектом параллакса. Я быстро изменил пример и экспортировал его в формате gif, чтобы было более понятно, чего мы пытаемся достичь:

iOS

Итак, прежде всего, я попробовал кое-что с, CollapsingToolbarLayout где я наткнулся на этот фрагмент. Таким образом, в основном фрагмент добавляет AppBarLayout.Behavior то, что обеспечивает эффект масштабирования. Капитальный ремонт не кажется гладким.

Затем я нашел PullZoomView, который кажется популярным в Android. Масштабирование и прокрутка выглядят великолепно. Единственная проблема заключается в том, что заголовок не исправлен и прокручивается listview следующим образом:

Android

Итак, я углубился в код и попытался изменить его для своего предложения, но это кажется взломанным и сложным.

Итак, из того, что я видел во всех библиотеках, кажется, что это переопределение поведения заголовка более распространено. Есть ли у кого-нибудь какие-либо советы, как я могу добиться желаемого поведения, прежде чем писать свое собственное решение? Может быть, есть какая-нибудь библиотека, которую я не нашел?

Ответ №1:

Напрямую не отвечает на ваш вопрос, но я создал библиотеку, в которой есть компонент, который расширяется при нажатии / касании. Я думаю, вы могли бы использовать код для создания собственного заголовка полосы прокрутки.

https://github.com/NadavTasher/ToolLibs/blob/master/lightool/src/main/java/nadav/tasher/lightool/graphics/views/ExpandingView.java

например, Сделайте фиксированный вид своим заголовком, а расширяющийся — своим scrollview

Ответ №2:

Я написал решение самостоятельно сразу после отправки этого вопроса. Мне действительно понравилась концепция в библиотеке от iOS, согласно которой у вас может быть отдельный UIViewController для заголовка и для части содержимого, поэтому в Android кажется, что фрагменты — это правильный путь. Я хочу поделиться своим кодом, если кто-нибудь хочет получить такой же эффект:

Иллюстрация

Добавьте в yur следующие зависимости build.gradle :

 implementation 'me.everything:overscroll-decor-android:1.0.4'
implementation 'com.github.ksoichiro:android-observablescrollview:1.6.0'
  

Мой класс (извините, это немного неаккуратно):

 public abstract class ParallaxHeaderActivity extends AppCompatActivity implements ObservableScrollViewCallbacks {

    private ObservableScrollView scrollView;
    private LinearLayout headerView;
    private FrameLayout contentView;

    private int headerHeight = 0;
    private int minimumHeaderHeight = 0;

    protected void setContentView(int layout, Fragment header, Fragment content){

        super.setContentView(layout);

        ViewGroup rootView = (ViewGroup) ((ViewGroup) this
                .findViewById(android.R.id.content)).getChildAt(0);

        headerHeight = (int)convertDpToPixel(260, this);
        minimumHeaderHeight = (int)convertDpToPixel(160, this);

        int contentViewId = View.generateViewId();

        contentView = new FrameLayout(this);
        contentView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        contentView.setPadding(0, headerHeight, 0, 0);
        contentView.setId(contentViewId);

        scrollView = new ObservableScrollView(this);
        scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        scrollView.setScrollViewCallbacks(this);
        scrollView.setFillViewport(true);
        scrollView.addView(contentView);
        scrollView.setScrollViewCallbacks(this);

        IOverScrollDecor decor = new VerticalOverScrollBounceEffectDecorator(new ScrollViewOverScrollDecorAdapter(scrollView));
        decor.setOverScrollUpdateListener(new IOverScrollUpdateListener() {
            @Override
            public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) {
                if (offset > 0) {
                    // 'view' is currently being over-scrolled from the top.
                    update((int)-offset);
                }

            }
        });

        rootView.addView(scrollView);

        addFragment(contentViewId, content);

        int headerViewId = View.generateViewId();

        headerView = new LinearLayout(this);
        headerView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, headerHeight));
        headerView.setId(headerViewId);

        rootView.addView(headerView);

        addFragment(headerViewId, header);

    }


    @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
        update(scrollY);
    }

    @Override
    public void onDownMotionEvent() {
    }

    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
    }

    private void addFragment(int id, Fragment fragment){

        final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(id, fragment);
        transaction.addToBackStack(null);
        transaction.commit();

    }

    private void update(final int scrollY) {
        headerView.getLayoutParams().height = Math.max(headerHeight - scrollY, minimumHeaderHeight);
        headerView.requestLayout();
    }

    public static float convertDpToPixel(float dp, Context context){
        return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    }

}
  

В вашей деятельности вы можете называть это как:

 setContentView(R.layout.activity_main, new HeaderFragment(), new ContentFragment());
  

fragment_content.xml:

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".ContentFragment">

        <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:text="@string/lipsum"/>

</FrameLayout>
  

fragment_header.xml:

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        android:src="@drawable/example"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:text="Test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:minHeight="?attr/actionBarSize"
        android:textColor="@android:color/white"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>