Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Add tutorial sliders for first time launch of app #466

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:hardwareAccelerated="false"
android:largeHeap="true"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the story behind this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sam1301 There was an issue outOfMemory error with loading the images. So i added largeheap to optimize using memory. :)

android:supportsRtl="false"
android:theme="@style/AppTheme.DayNight.NoActionBar"
tools:ignore="GoogleAppIndexingWarning">
Expand All @@ -50,16 +52,23 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>

<activity
android:name=".activities.TutorialActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.LoginActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
Expand Down
213 changes: 213 additions & 0 deletions app/src/main/java/com/zulip/android/activities/TutorialActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package com.zulip.android.activities;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.zulip.android.R;
import com.zulip.android.util.ActivityTransitionAnim;
import com.zulip.android.util.PrefManager;

/**
* This activity is for the first time users to get familiar with
* the zulip enivornment and the working of some special features
* of the app.
*/

public class TutorialActivity extends AppCompatActivity {

private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
private Button btnSkip, btnNext;
// viewpager change listener
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {

@Override
public void onPageSelected(int position) {
addBottomDots(position);

// changing the next button text 'NEXT' / 'GOT IT'
if (position == layouts.length - 1) {
// last page. make button text to GOT IT
btnNext.setText(getString(R.string.start));
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText(getString(R.string.next));
btnSkip.setVisibility(View.VISIBLE);
}
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {

}

@Override
public void onPageScrollStateChanged(int arg0) {

}
};
private PrefManager prefManager;

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

/* Checking for first time launch - before calling setContentView()
if isFirstTimeLaunch is false then ZulipActivity is called
*/
prefManager = new PrefManager(this);
if (!prefManager.isFirstTimeLaunch()) {
launchZulipActivity();
finish();
}

// Making notification bar transparent in SDK Version greater than 21
if (Build.VERSION.SDK_INT >= 21) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

setContentView(R.layout.activity_tutorial);

viewPager = (ViewPager) findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(R.id.layoutDots);
btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);


// layouts of all Tutorial sliders
layouts = new int[]{
R.layout.tutorial_slide1,
R.layout.tutorial_slide2,
R.layout.tutorial_slide3,
R.layout.tutorial_slide4};

// for adding bottom dots
addBottomDots(0);

// for making notification bar transparent
changeStatusBarColor();

myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);

btnSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchZulipActivity();
}
});

btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// checking for last page
// if last page Zulip screen will be launched
int current = getItem(+1);
if (current < layouts.length) {
// move to next screen
viewPager.setCurrentItem(current);
} else {
launchZulipActivity();
}
}
});
}

private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];

int[] colorsActive = getResources().getIntArray(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(R.array.array_dot_inactive);

dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(this);
dots[i].setText(Html.fromHtml("&#8226;"));
dots[i].setTextSize(35);
dots[i].setTextColor(colorsInactive[currentPage]);
dotsLayout.addView(dots[i]);
}

if (dots.length > 0)
dots[currentPage].setTextColor(colorsActive[currentPage]);
}

private int getItem(int i) {
return viewPager.getCurrentItem() + i;
}

private void launchZulipActivity() {
prefManager.setFirstTimeLaunch(false);
startActivity(new Intent(TutorialActivity.this, ZulipActivity.class));
ActivityTransitionAnim.transition(TutorialActivity.this);
finish();
}

/**
* Making notification bar transparent in SDK Versions > 21
*/
private void changeStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
}

/**
* View pager adapter
*/
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;

public MyViewPagerAdapter() {
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View view = layoutInflater.inflate(layouts[position], container, false);
container.addView(view);

return view;
}

@Override
public int getCount() {
return layouts.length;
}

@Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}


@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
import com.zulip.android.util.FileUtils;
import com.zulip.android.util.ListDialog;
import com.zulip.android.util.MutedTopics;
import com.zulip.android.util.PrefManager;
import com.zulip.android.util.RemoveViewsOnScroll;
import com.zulip.android.util.SwipeRemoveLinearLayout;
import com.zulip.android.util.UrlHelper;
Expand Down Expand Up @@ -2334,6 +2335,14 @@ public boolean onOptionsItemSelected(MenuItem item) {
FragmentManager.POP_BACK_STACK_INCLUSIVE);
clearSearch();
break;
case R.id.helpMe:
PrefManager prefManager = new PrefManager(getApplicationContext());
// making the first time launch TRUE
prefManager.setFirstTimeLaunch(true);
startActivity(new Intent(ZulipActivity.this, TutorialActivity.class));
finish();
break;

case R.id.search:
// show a pop up dialog only if gingerbread or under
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/com/zulip/android/util/PrefManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.zulip.android.util;

import android.content.Context;
import android.content.SharedPreferences;



public class PrefManager {

// Shared preferences file name
private static final String PREF_NAME = "zulip-slides";
private static final String IS_FIRST_TIME_LAUNCH = "IsFirstTimeLaunch";
SharedPreferences pref;
SharedPreferences.Editor editor;
Context _context;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-public, non-static field names start with m.

// shared pref mode
int PRIVATE_MODE = 0;

public PrefManager(Context context) {
this._context = context;
pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = pref.edit();
}

public boolean isFirstTimeLaunch() {
return pref.getBoolean(IS_FIRST_TIME_LAUNCH, true);
}

public void setFirstTimeLaunch(boolean isFirstTime) {
editor.putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about saving the version of app instead of a boolean; shared pref will remain same across upgrades

editor.commit();
}
}
Binary file added app/src/main/res/drawable/slide1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/slide2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/slide3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/slide4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions app/src/main/res/layout/activity_tutorial.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">


<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<LinearLayout
android:id="@+id/layoutDots"
android:layout_width="match_parent"
android:layout_height="30dp"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about saving dimensions in dimen.xml?

android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:orientation="horizontal">


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are some extra newlines in other xml files as well

</LinearLayout>

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_above="@id/layoutDots"
android:alpha=".5"
android:background="@android:color/white" />

<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can abstract out the style of buttons here into styles.xml

android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@null"
android:text="@string/next"
android:textColor="@android:color/white" />

<Button
android:id="@+id/btn_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="@null"
android:text="@string/skip"
android:textColor="@android:color/white" />

</RelativeLayout>
Loading