com.heinrichreimersoftware.materialintro.slide.SimpleSlide.java Source code

Java tutorial

Introduction

Here is the source code for com.heinrichreimersoftware.materialintro.slide.SimpleSlide.java

Source

/*
 * MIT License
 *
 * Copyright (c) 2017 Jan Heinrich Reimer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.heinrichreimersoftware.materialintro.slide;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.heinrichreimersoftware.materialintro.R;
import com.heinrichreimersoftware.materialintro.view.parallax.ParallaxSlideFragment;

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

public class SimpleSlide implements Slide, RestorableSlide, ButtonCtaSlide {

    private static final int DEFAULT_PERMISSIONS_REQUEST_CODE = 34; //Random number
    private SimpleSlideFragment fragment;

    private final long id;
    private final CharSequence title;
    @StringRes
    private final int titleRes;
    private final CharSequence description;
    @StringRes
    private final int descriptionRes;
    @DrawableRes
    private final int imageRes;
    @LayoutRes
    private final int layoutRes;

    @ColorRes
    private final int backgroundRes;
    @ColorRes
    private final int backgroundDarkRes;
    private final boolean canGoForward;
    private final boolean canGoBackward;
    private String[] permissions;
    private int permissionsRequestCode;
    private CharSequence buttonCtaLabel = null;
    @StringRes
    private int buttonCtaLabelRes = 0;
    private View.OnClickListener buttonCtaClickListener = null;

    protected SimpleSlide(Builder builder) {
        fragment = SimpleSlideFragment.newInstance(builder.id, builder.title, builder.titleRes, builder.description,
                builder.descriptionRes, builder.imageRes, builder.backgroundRes, builder.layoutRes,
                builder.permissionsRequestCode);
        id = builder.id;
        title = builder.title;
        titleRes = builder.titleRes;
        description = builder.description;
        descriptionRes = builder.descriptionRes;
        imageRes = builder.imageRes;
        layoutRes = builder.layoutRes;
        backgroundRes = builder.backgroundRes;
        backgroundDarkRes = builder.backgroundDarkRes;
        canGoForward = builder.canGoForward;
        canGoBackward = builder.canGoBackward;
        permissions = builder.permissions;
        permissionsRequestCode = builder.permissionsRequestCode;
        buttonCtaLabel = builder.buttonCtaLabel;
        buttonCtaLabelRes = builder.buttonCtaLabelRes;
        buttonCtaClickListener = builder.buttonCtaClickListener;
        updatePermissions();
    }

    @Override
    public Fragment getFragment() {
        return fragment;
    }

    @Override
    public void setFragment(Fragment fragment) {
        if (fragment instanceof SimpleSlideFragment)
            this.fragment = (SimpleSlideFragment) fragment;
    }

    @Override
    public int getBackground() {
        return backgroundRes;
    }

    @Override
    public int getBackgroundDark() {
        return backgroundDarkRes;
    }

    @Override
    public boolean canGoForward() {
        updatePermissions();
        return canGoForward && permissions == null;

    }

    @Override
    public boolean canGoBackward() {
        return canGoBackward;
    }

    @Override
    public View.OnClickListener getButtonCtaClickListener() {
        updatePermissions();
        if (permissions == null) {
            return buttonCtaClickListener;
        }
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (fragment.getActivity() != null)
                    ActivityCompat.requestPermissions(fragment.getActivity(), permissions, permissionsRequestCode);
            }
        };
    }

    @Override
    public CharSequence getButtonCtaLabel() {
        updatePermissions();
        if (permissions == null) {
            return buttonCtaLabel;
        }
        Context context = fragment.getContext();
        if (context != null)
            return context.getResources().getQuantityText(R.plurals.mi_label_grant_permission, permissions.length);
        return null;
    }

    @Override
    public int getButtonCtaLabelRes() {
        updatePermissions();
        if (permissions == null) {
            return buttonCtaLabelRes;
        }
        return 0;
    }

    private synchronized void updatePermissions() {
        if (permissions != null) {
            final List<String> permissionsNotGranted = new ArrayList<>();
            for (String permission : permissions) {
                if (fragment.getContext() == null || ContextCompat.checkSelfPermission(fragment.getContext(),
                        permission) != PackageManager.PERMISSION_GRANTED) {
                    permissionsNotGranted.add(permission);
                }
            }

            if (permissionsNotGranted.size() > 0) {
                permissions = permissionsNotGranted.toArray(new String[permissionsNotGranted.size()]);
            } else {
                permissions = null;
            }
        } else {
            permissions = null;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        SimpleSlide that = (SimpleSlide) o;

        if (id != that.id)
            return false;
        if (titleRes != that.titleRes)
            return false;
        if (descriptionRes != that.descriptionRes)
            return false;
        if (imageRes != that.imageRes)
            return false;
        if (layoutRes != that.layoutRes)
            return false;
        if (backgroundRes != that.backgroundRes)
            return false;
        if (backgroundDarkRes != that.backgroundDarkRes)
            return false;
        if (canGoForward != that.canGoForward)
            return false;
        if (canGoBackward != that.canGoBackward)
            return false;
        if (permissionsRequestCode != that.permissionsRequestCode)
            return false;
        if (buttonCtaLabelRes != that.buttonCtaLabelRes)
            return false;
        if (fragment != null ? !fragment.equals(that.fragment) : that.fragment != null)
            return false;
        if (title != null ? !title.equals(that.title) : that.title != null)
            return false;
        if (description != null ? !description.equals(that.description) : that.description != null)
            return false;
        if (!Arrays.equals(permissions, that.permissions))
            return false;
        if (buttonCtaLabel != null ? !buttonCtaLabel.equals(that.buttonCtaLabel) : that.buttonCtaLabel != null)
            return false;
        return buttonCtaClickListener != null ? buttonCtaClickListener.equals(that.buttonCtaClickListener)
                : that.buttonCtaClickListener == null;

    }

    @Override
    public int hashCode() {
        int result = fragment != null ? fragment.hashCode() : 0;
        result = 31 * result + ((Long) id).hashCode();
        result = 31 * result + (title != null ? title.hashCode() : 0);
        result = 31 * result + titleRes;
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + descriptionRes;
        result = 31 * result + imageRes;
        result = 31 * result + layoutRes;
        result = 31 * result + backgroundRes;
        result = 31 * result + backgroundDarkRes;
        result = 31 * result + (canGoForward ? 1 : 0);
        result = 31 * result + (canGoBackward ? 1 : 0);
        result = 31 * result + Arrays.hashCode(permissions);
        result = 31 * result + permissionsRequestCode;
        result = 31 * result + (buttonCtaLabel != null ? buttonCtaLabel.hashCode() : 0);
        result = 31 * result + buttonCtaLabelRes;
        result = 31 * result + (buttonCtaClickListener != null ? buttonCtaClickListener.hashCode() : 0);
        return result;
    }

    public static class Builder {
        @ColorRes
        private int backgroundRes = 0;
        private long id = 0;
        @ColorRes
        private int backgroundDarkRes = 0;
        private CharSequence title = null;
        @StringRes
        private int titleRes = 0;
        private CharSequence description = null;
        @StringRes
        private int descriptionRes = 0;
        @DrawableRes
        private int imageRes = 0;
        @LayoutRes
        private int layoutRes = R.layout.mi_fragment_simple_slide;
        private boolean canGoForward = true;
        private boolean canGoBackward = true;
        private String[] permissions = null;
        private CharSequence buttonCtaLabel = null;
        @StringRes
        private int buttonCtaLabelRes = 0;
        private View.OnClickListener buttonCtaClickListener = null;

        private int permissionsRequestCode = DEFAULT_PERMISSIONS_REQUEST_CODE;

        public Builder background(@ColorRes int backgroundRes) {
            this.backgroundRes = backgroundRes;
            return this;
        }

        public Builder backgroundDark(@ColorRes int backgroundDarkRes) {
            this.backgroundDarkRes = backgroundDarkRes;
            return this;
        }

        public Builder title(CharSequence title) {
            this.title = title;
            this.titleRes = 0;
            return this;
        }

        public Builder titleHtml(String titleHtml) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                this.title = Html.fromHtml(titleHtml, Html.FROM_HTML_MODE_LEGACY);
            } else {
                //noinspection deprecation
                this.title = Html.fromHtml(titleHtml);
            }
            this.titleRes = 0;
            return this;
        }

        public Builder id(long id) {
            this.id = id;
            return this;
        }

        public Builder title(@StringRes int titleRes) {
            this.titleRes = titleRes;
            this.title = null;
            return this;
        }

        public Builder description(CharSequence description) {
            this.description = description;
            this.descriptionRes = 0;
            return this;
        }

        public Builder descriptionHtml(String descriptionHtml) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                this.description = Html.fromHtml(descriptionHtml, Html.FROM_HTML_MODE_LEGACY);
            } else {
                //noinspection deprecation
                this.description = Html.fromHtml(descriptionHtml);
            }
            this.descriptionRes = 0;
            return this;
        }

        public Builder description(@StringRes int descriptionRes) {
            this.descriptionRes = descriptionRes;
            this.description = null;
            return this;
        }

        public Builder image(@DrawableRes int imageRes) {
            this.imageRes = imageRes;
            return this;
        }

        public Builder layout(@LayoutRes int layoutRes) {
            this.layoutRes = layoutRes;
            return this;
        }

        public Builder scrollable(boolean scrollable) {
            this.layoutRes = scrollable ? R.layout.mi_fragment_simple_slide_scrollable
                    : R.layout.mi_fragment_simple_slide;
            return this;
        }

        public Builder canGoForward(boolean canGoForward) {
            this.canGoForward = canGoForward;
            return this;
        }

        public Builder canGoBackward(boolean canGoBackward) {
            this.canGoBackward = canGoBackward;
            return this;
        }

        public Builder permissions(String[] permissions) {
            this.permissions = permissions;
            return this;
        }

        public Builder permission(String permission) {
            this.permissions = new String[] { permission };
            return this;
        }

        public Builder permissionsRequestCode(int permissionsRequestCode) {
            this.permissionsRequestCode = permissionsRequestCode;
            return this;
        }

        public Builder buttonCtaLabel(CharSequence buttonCtaLabel) {
            this.buttonCtaLabel = buttonCtaLabel;
            this.buttonCtaLabelRes = 0;
            return this;
        }

        public Builder buttonCtaLabelHtml(String buttonCtaLabelHtml) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                this.buttonCtaLabel = Html.fromHtml(buttonCtaLabelHtml, Html.FROM_HTML_MODE_LEGACY);
            } else {
                //noinspection deprecation
                this.buttonCtaLabel = Html.fromHtml(buttonCtaLabelHtml);
            }
            this.buttonCtaLabelRes = 0;
            return this;
        }

        public Builder buttonCtaLabel(@StringRes int buttonCtaLabelRes) {
            this.buttonCtaLabelRes = buttonCtaLabelRes;
            this.buttonCtaLabel = null;
            return this;
        }

        public Builder buttonCtaClickListener(View.OnClickListener buttonCtaClickListener) {
            this.buttonCtaClickListener = buttonCtaClickListener;
            return this;
        }

        public SimpleSlide build() {
            if (backgroundRes == 0)
                throw new IllegalArgumentException("You must set a background.");
            return new SimpleSlide(this);
        }
    }

    public static class SimpleSlideFragment extends ParallaxSlideFragment {
        private static final String ARGUMENT_ID = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_ID";
        private static final String ARGUMENT_TITLE = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_TITLE";
        private static final String ARGUMENT_TITLE_RES = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_TITLE_RES";
        private static final String ARGUMENT_DESCRIPTION = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_DESCRIPTION";
        private static final String ARGUMENT_DESCRIPTION_RES = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_DESCRIPTION_RES";
        private static final String ARGUMENT_IMAGE_RES = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_IMAGE_RES";
        private static final String ARGUMENT_BACKGROUND_RES = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_BACKGROUND_RES";
        private static final String ARGUMENT_LAYOUT_RES = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_LAYOUT_RES";

        private static final String ARGUMENT_PERMISSIONS_REQUEST_CODE = "com.heinrichreimersoftware.materialintro.SimpleFragment.ARGUMENT_PERMISSIONS_REQUEST_CODE";

        private TextView titleView = null;
        private TextView descriptionView = null;
        private ImageView imageView = null;

        public SimpleSlideFragment() {
        }

        public static SimpleSlideFragment newInstance(long id, CharSequence title, @StringRes int titleRes,
                CharSequence description, @StringRes int descriptionRes, @DrawableRes int imageRes,
                @ColorRes int backgroundRes, @LayoutRes int layout, int permissionsRequestCode) {
            Bundle arguments = new Bundle();
            arguments.putLong(ARGUMENT_ID, id);
            arguments.putCharSequence(ARGUMENT_TITLE, title);
            arguments.putInt(ARGUMENT_TITLE_RES, titleRes);
            arguments.putCharSequence(ARGUMENT_DESCRIPTION, description);
            arguments.putInt(ARGUMENT_DESCRIPTION_RES, descriptionRes);
            arguments.putInt(ARGUMENT_IMAGE_RES, imageRes);
            arguments.putInt(ARGUMENT_BACKGROUND_RES, backgroundRes);
            arguments.putInt(ARGUMENT_LAYOUT_RES, layout);
            arguments.putInt(ARGUMENT_PERMISSIONS_REQUEST_CODE, permissionsRequestCode);

            SimpleSlideFragment fragment = new SimpleSlideFragment();
            fragment.setArguments(arguments);

            return fragment;
        }

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
            updateNavigation();
        }

        @Override
        public void onResume() {
            super.onResume();
            //Lock scroll for the case that users revoke accepted permission settings while in the intro
            updateNavigation();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Bundle arguments = getArguments();

            View fragment = inflater.inflate(
                    arguments.getInt(ARGUMENT_LAYOUT_RES, R.layout.mi_fragment_simple_slide), container, false);

            titleView = (TextView) fragment.findViewById(R.id.mi_title);
            descriptionView = (TextView) fragment.findViewById(R.id.mi_description);
            imageView = (ImageView) fragment.findViewById(R.id.mi_image);

            long id = arguments.getLong(ARGUMENT_ID);
            CharSequence title = arguments.getCharSequence(ARGUMENT_TITLE);
            int titleRes = arguments.getInt(ARGUMENT_TITLE_RES);
            CharSequence description = arguments.getCharSequence(ARGUMENT_DESCRIPTION);
            int descriptionRes = arguments.getInt(ARGUMENT_DESCRIPTION_RES);
            int imageRes = arguments.getInt(ARGUMENT_IMAGE_RES);
            int backgroundRes = arguments.getInt(ARGUMENT_BACKGROUND_RES);

            //Title
            if (titleView != null) {
                if (title != null) {
                    titleView.setText(title);
                    titleView.setVisibility(View.VISIBLE);
                } else if (titleRes != 0) {
                    titleView.setText(titleRes);
                    titleView.setVisibility(View.VISIBLE);
                } else {
                    titleView.setVisibility(View.GONE);
                }
            }

            //Description
            if (descriptionView != null) {
                if (description != null) {
                    descriptionView.setText(description);
                    descriptionView.setVisibility(View.VISIBLE);
                } else if (descriptionRes != 0) {
                    descriptionView.setText(descriptionRes);
                    descriptionView.setVisibility(View.VISIBLE);
                } else {
                    descriptionView.setVisibility(View.GONE);
                }
            }

            //Image
            if (imageView != null) {
                if (imageRes != 0) {
                    imageView.setImageResource(imageRes);
                    imageView.setVisibility(View.VISIBLE);
                } else {
                    imageView.setVisibility(View.GONE);
                }
            }

            @ColorInt
            int textColorPrimary;
            @ColorInt
            int textColorSecondary;

            if (backgroundRes != 0
                    && ColorUtils.calculateLuminance(ContextCompat.getColor(getContext(), backgroundRes)) < 0.6) {
                //Use light text color
                textColorPrimary = ContextCompat.getColor(getContext(), R.color.mi_text_color_primary_dark);
                textColorSecondary = ContextCompat.getColor(getContext(), R.color.mi_text_color_secondary_dark);
            } else {
                //Use dark text color
                textColorPrimary = ContextCompat.getColor(getContext(), R.color.mi_text_color_primary_light);
                textColorSecondary = ContextCompat.getColor(getContext(), R.color.mi_text_color_secondary_light);
            }

            if (titleView != null) {
                titleView.setTextColor(textColorPrimary);
            }
            if (descriptionView != null) {
                descriptionView.setTextColor(textColorSecondary);
            }

            if (getActivity() instanceof SimpleSlideActivity) {
                ((SimpleSlideActivity) getActivity()).onSlideViewCreated(this, fragment, id);
            }

            return fragment;
        }

        @Override
        public void onDestroyView() {
            if (getActivity() instanceof SimpleSlideActivity) {
                long id = getArguments().getLong(ARGUMENT_ID);
                ((SimpleSlideActivity) getActivity()).onSlideDestroyView(this, getView(), id);
            }
            titleView = null;
            descriptionView = null;
            imageView = null;
            super.onDestroyView();
        }

        public TextView getTitleView() {
            return titleView;
        }

        public TextView getDescriptionView() {
            return descriptionView;
        }

        public ImageView getImageView() {
            return imageView;
        }

        public long getSlideId() {
            return getArguments().getLong(ARGUMENT_ID);
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                @NonNull int[] grantResults) {
            int permissionsRequestCode = getArguments() == null ? DEFAULT_PERMISSIONS_REQUEST_CODE
                    : getArguments().getInt(ARGUMENT_PERMISSIONS_REQUEST_CODE, DEFAULT_PERMISSIONS_REQUEST_CODE);
            if (requestCode == permissionsRequestCode) {
                updateNavigation();
            }
        }
    }
}