<|start_filename|>library/src/main/java/com/hololo/tutorial/library/TutorialActivity.java<|end_filename|>
package com.hololo.tutorial.library;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

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

public class TutorialActivity extends AppCompatActivity implements View.OnClickListener {

    private List<Step> steps;
    private StepPagerAdapter adapter;

    private ViewPager pager;
    private Button next, prev;
    private LinearLayout indicatorLayout;
    private FrameLayout containerLayout;
    private RelativeLayout buttonContainer;

    private int currentItem;

    private String prevText, nextText, finishText, cancelText, givePermissionText;
    private int selectedIndicator = R.drawable.circle_black, indicator = R.drawable.circle_white;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        setTheme(R.style.TutorialStyle);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tutorial);

        init();
    }

    private void init() {
        steps = new ArrayList<>();
        initTexts();
        initViews();
        initAdapter();
    }

    private void initTexts() {
        prevText = "Back";
        cancelText = "Cancel";
        finishText = "Let's theme";
        nextText = "Next";
        givePermissionText = "Give";
    }

    private void initAdapter() {
        adapter = new StepPagerAdapter(getSupportFragmentManager(), steps);
        pager.setAdapter(adapter);
        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                currentItem = position;
                controlPosition(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void changeStatusBarColor(int backgroundColor) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(backgroundColor);
    }

    private void controlPosition(int position) {
        notifyIndicator();

        if (position == steps.size() - 1) {
            prev.setVisibility(View.VISIBLE);
            next.setText(finishText);
            prev.setText(prevText);
            prev.setEnabled(true);
        } else if (position == 0) {
            prev.setText(null);
            prev.setVisibility(View.GONE);
            next.setText(nextText);
            prev.setEnabled(false);
        } else {
            prev.setVisibility(View.VISIBLE);
            prev.setText(prevText);
            next.setText(nextText);
            prev.setEnabled(true);
        }

        if (controlPermission()) {
            prepareNormalView();
        } else {
            preparePermissionView();
        }

        containerLayout.setBackgroundColor(steps.get(position).getBackgroundColor());
        buttonContainer.setBackgroundColor(steps.get(position).getBackgroundColor());
    }

    @SuppressLint("ClickableViewAccessibility")
    private void prepareNormalView() {
        pager.setOnTouchListener(null);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void preparePermissionView() {
        next.setText(givePermissionText);

        pager.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
    }

    private void initViews() {
        currentItem = 0;

        pager = (ViewPager) findViewById(R.id.viewPager);
        next = (Button) findViewById(R.id.next);
        prev = (Button) findViewById(R.id.prev);
        indicatorLayout = (LinearLayout) findViewById(R.id.indicatorLayout);
        containerLayout = (FrameLayout) findViewById(R.id.containerLayout);
        buttonContainer = (RelativeLayout) findViewById(R.id.buttonContainer);

        next.setOnClickListener(this);
        prev.setOnClickListener(this);
    }

    public void addFragment(Step step) {
        steps.add(step);
        adapter.notifyDataSetChanged();
        notifyIndicator();
        controlPosition(currentItem);
    }

    public void addFragment(Step step, int position) {
        steps.add(position, step);
        adapter.notifyDataSetChanged();
        notifyIndicator();
        controlPosition(currentItem);
    }

    public void notifyIndicator() {
        if (indicatorLayout.getChildCount() > 0)
            indicatorLayout.removeAllViews();

        for (int i = 0; i < steps.size(); i++) {
            ImageView imageView = new ImageView(this);
            imageView.setPadding(8, 8, 8, 8);
            int drawable = indicator;
            if (i == currentItem)
                drawable = selectedIndicator;

            imageView.setImageResource(drawable);

            final int finalI = i;
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    changeFragment(finalI);
                }
            });

            indicatorLayout.addView(imageView);
        }

    }

    @Override
    public void onBackPressed() {
        if (currentItem == 0) {
            super.onBackPressed();
        } else {
            changeFragment(false);
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.next) {
            if (controlPermission())
                changeFragment(true);
            else
                requestPermissions(((PermissionStep) steps.get(pager.getCurrentItem())).getPermissions(), 1903);
        } else if (v.getId() == R.id.prev) {
            changeFragment(false);
        }
    }

    private void changeFragment(int position) {
        if (controlPermission())
            pager.setCurrentItem(position, true);
    }

    private boolean controlPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && steps.get(pager.getCurrentItem()) instanceof PermissionStep) {

            for (String permission : ((PermissionStep) steps.get(pager.getCurrentItem())).getPermissions()) {
                int permissionResult = checkSelfPermission(permission);

                if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        }
        return true;
    }

    private void changeFragment(boolean isNext) {
        int item = currentItem;
        if (isNext) {
            item++;
        } else {
            item--;
        }

        if (item < 0 || item == steps.size()) {
            finishTutorial();
        } else
            pager.setCurrentItem(item, true);
    }

    public void finishTutorial() {
        finish();
    }

    public void setPrevText(String text) {
        prevText = text;
    }

    public void setNextText(String text) {
        nextText = text;
    }

    public void setFinishText(String text) {
        finishText = text;
    }

    public void setCancelText(String text) {
        cancelText = text;
    }

    public void setGivePermissionText(String text) {
        givePermissionText = text;
    }

    public void setIndicatorSelected(int drawable) {
        selectedIndicator = drawable;
    }

    public void setIndicator(int drawable) {
        indicator = drawable;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            changeFragment(true);
        }
    }
}

<|start_filename|>app/src/main/java/com/hololo/tutorial/sample/MainActivity.java<|end_filename|>
package com.hololo.tutorial.sample;

import android.Manifest;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Toast;

import com.hololo.tutorial.library.PermissionStep;
import com.hololo.tutorial.library.Step;
import com.hololo.tutorial.library.TutorialActivity;

public class MainActivity extends TutorialActivity {

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

        addFragment(new PermissionStep.Builder().setPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}).setTitle(getString(R.string.permission_title)).setContent(getString(R.string.permission_detail)).setBackgroundColor(Color.parseColor("#FF0957")).setDrawable(R.drawable.ss_1).setSummary(getString(R.string.continue_and_learn)).build());
        addFragment(new Step.Builder().setTitle(getString(R.string.automatic_data)).setContent(getString(R.string.gm_finds_photos)).setBackgroundColor(Color.parseColor("#FF0957")).setDrawable(R.drawable.ss_1).setSummary(getString(R.string.continue_and_learn)).build());
        addFragment(new Step.Builder().setTitle(getString(R.string.choose_the_song)).setContent(getString(R.string.swap_to_the_tab)).setBackgroundColor(Color.parseColor("#00D4BA")).setDrawable(R.drawable.ss_2).setSummary(getString(R.string.continue_and_update)).build());
        addFragment(new Step.Builder().setTitle(getString(R.string.edit_data)).setContent(getString(R.string.update_easily)).setBackgroundColor(Color.parseColor("#1098FE")).setDrawable(R.drawable.ss_3).setSummary(getString(R.string.continue_and_result)).build());
        addFragment(new Step.Builder().setTitle(getString(R.string.result_awesome)).setContent(getString(R.string.after_updating)).setBackgroundColor(Color.parseColor("#CA70F3")).setDrawable(R.drawable.ss_4).setSummary(getString(R.string.thank_you)).build());

    }

    @Override
    public void finishTutorial() {
        Toast.makeText(this, "Tutorial finished", Toast.LENGTH_SHORT).show();
        finish();
    }

    //@Override
    public void currentFragmentPosition(int position) {
        Toast.makeText(this,"Position : " + position,Toast.LENGTH_SHORT).show();
    }
}


<|start_filename|>library/src/main/java/com/hololo/tutorial/library/StepView.java<|end_filename|>
package com.hololo.tutorial.library;

import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class StepView extends Fragment {

    Step step;

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

        step = getArguments().getParcelable("step");
    }
}
