/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hapjs.widgets.view.swiper;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Choreographer;
import android.view.FocusFinder;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.os.ParcelableCompat;
import androidx.core.os.ParcelableCompatCreatorCallbacks;
import androidx.core.view.AccessibilityDelegateCompat;
import androidx.core.view.MotionEventCompat;
import androidx.core.view.VelocityTrackerCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
import androidx.core.widget.EdgeEffectCompat;
import androidx.customview.view.AbsSavedState;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerTitleStrip;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.hapjs.common.compat.BuildPlatform;
/**
* Layout manager that allows the user to flip left and right through pages of data. You supply an
* implementation of a {@link PagerAdapter} to generate the pages that the view shows.
*
* <p>
*
* <p>ViewPager is most often used in conjunction with {@link android.app.Fragment}, which is a
* convenient way to supply and manage the lifecycle of each page. There are standard adapters
* implemented for using fragments with the ViewPager, which cover the most common use cases. These
* are {@link FragmentPagerAdapter} and {@link FragmentStatePagerAdapter}; each of these classes
* have simple code showing how to build a full user interface with them.
*
* <p>
*
* <p>Views which are annotated with the {@link DecorView} annotation are treated as part of the
* view pagers 'decor'. Each decor view's position can be controlled via its {@code
* android:layout_gravity} attribute. For example:
*
* <p>
*
* <pre>
* <android.support.v4.view.ViewPager
* android:layout_width="match_parent"
* android:layout_height="match_parent">
*
* <android.support.v4.view.PagerTitleStrip
* android:layout_width="match_parent"
* android:layout_height="wrap_content"
* android:layout_gravity="top" />
*
* </android.support.v4.view.ViewPager>
* </pre>
*
* <p>
*
* <p>For more information about how to use ViewPager, read <a
* href="{@docRoot}training/implementing-navigation/lateral.html">Creating Swipe Views with
* Tabs</a>.
*
* <p>
*
* <p>You can find examples of using ViewPager in the API 4+ Support Demos and API 13+ Support Demos
* sample code.
*/
public class ViewPager extends ViewGroup {
/**
* Indicates that the pager is in an idle, settled state. The current page is fully in view and no
* animation is in progress.
*/
public static final int SCROLL_STATE_IDLE = 0;
/**
* Indicates that the pager is currently being dragged by the user.
*/
public static final int SCROLL_STATE_DRAGGING = 1;
/**
* Indicates that the pager is in the process of settling to a final position.
*/
public static final int SCROLL_STATE_SETTLING = 2;
static final int[] LAYOUT_ATTRS = new int[] {android.R.attr.layout_gravity};
private static final String TAG = "ViewPager";
private static final boolean DEBUG = false;
private static final boolean USE_CACHE = false;
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
private static final int MAX_SETTLE_DURATION = 600; // ms
private static final int MIN_DISTANCE_FOR_FLING = 25; // dips
private static final int DEFAULT_GUTTER_SIZE = 16; // dips
private static final int MIN_FLING_VELOCITY = 400; // dips
private static final Comparator<ItemInfo> COMPARATOR =
new Comparator<ItemInfo>() {
@Override
public int compare(ItemInfo lhs, ItemInfo rhs) {
return lhs.position - rhs.position;
}
};
private static final Interpolator sInterpolator =
new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
/**
* Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
*/
private static final int INVALID_POINTER = -1;
// If the pager is at least this close to its final position, complete the scroll
// on touch down and let the user interact with the content inside instead of
// "catching" the flinging pager.
private static final int CLOSE_ENOUGH = 2; // dp
private static final int DRAW_ORDER_DEFAULT = 0;
private static final int DRAW_ORDER_FORWARD = 1;
private static final int DRAW_ORDER_REVERSE = 2;
private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator();
private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
private final ItemInfo mTempItem = new ItemInfo();
private final Rect mTempRect = new Rect();
PagerAdapter mAdapter;
int mCurItem; // Index of currently displayed page.
/**
* Used to track what the expected number of items in the adapter should be. If the app changes
* this when we don't expect it, we'll throw a big obnoxious exception.
*/
private int mExpectedAdapterCount;
private VerticalViewPagerCompat compat;
private Choreographer.FrameCallback mDispatchCallback;
private int mRestoredCurItem = -1;
private Parcelable mRestoredAdapterState = null;
private ClassLoader mRestoredClassLoader = null;
private CustomScroller mScroller;
private boolean mIsScrollStarted;
private PagerObserver mObserver;
private int mPageMargin;
private Drawable mMarginDrawable;
private int mTopPageBounds;
private int mBottomPageBounds;
private int mL