diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 373e32eebba7..a6ea864de12c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -20,8 +20,8 @@ --> + android:versionCode="10040003" + android:versionName="1.4.0 RC3"> + android:theme="@style/Theme.ownCloud.noActionBar.Login"> @@ -219,7 +219,9 @@ - + + diff --git a/res/drawable-anydpi-v21/arrow_right.xml b/res/drawable-anydpi-v21/arrow_right.xml new file mode 100644 index 000000000000..66272b455852 --- /dev/null +++ b/res/drawable-anydpi-v21/arrow_right.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/res/drawable-hdpi/arrow_right.png b/res/drawable-hdpi/arrow_right.png new file mode 100644 index 000000000000..7df35e34820a Binary files /dev/null and b/res/drawable-hdpi/arrow_right.png differ diff --git a/res/drawable-hdpi/ic_done_white.png b/res/drawable-hdpi/ic_done_white.png new file mode 100644 index 000000000000..c278b6c2b30b Binary files /dev/null and b/res/drawable-hdpi/ic_done_white.png differ diff --git a/res/drawable-hdpi/what_new_instant_upload.png b/res/drawable-hdpi/what_new_instant_upload.png new file mode 100644 index 000000000000..a8f0d3a2be48 Binary files /dev/null and b/res/drawable-hdpi/what_new_instant_upload.png differ diff --git a/res/drawable-hdpi/whats_new_accounts.png b/res/drawable-hdpi/whats_new_accounts.png new file mode 100644 index 000000000000..03b038821f87 Binary files /dev/null and b/res/drawable-hdpi/whats_new_accounts.png differ diff --git a/res/drawable-hdpi/whats_new_files.png b/res/drawable-hdpi/whats_new_files.png new file mode 100644 index 000000000000..6229974d6211 Binary files /dev/null and b/res/drawable-hdpi/whats_new_files.png differ diff --git a/res/drawable-mdpi/arrow_right.png b/res/drawable-mdpi/arrow_right.png new file mode 100644 index 000000000000..4e3764bb29e1 Binary files /dev/null and b/res/drawable-mdpi/arrow_right.png differ diff --git a/res/drawable-mdpi/ic_done_white.png b/res/drawable-mdpi/ic_done_white.png new file mode 100644 index 000000000000..3b2b65d26291 Binary files /dev/null and b/res/drawable-mdpi/ic_done_white.png differ diff --git a/res/drawable-xhdpi/arrow_right.png b/res/drawable-xhdpi/arrow_right.png new file mode 100644 index 000000000000..410181343507 Binary files /dev/null and b/res/drawable-xhdpi/arrow_right.png differ diff --git a/res/drawable-xhdpi/ic_done_white.png b/res/drawable-xhdpi/ic_done_white.png new file mode 100644 index 000000000000..3b2b65d26291 Binary files /dev/null and b/res/drawable-xhdpi/ic_done_white.png differ diff --git a/res/drawable-xxhdpi/arrow_right.png b/res/drawable-xxhdpi/arrow_right.png new file mode 100644 index 000000000000..344a813acb53 Binary files /dev/null and b/res/drawable-xxhdpi/arrow_right.png differ diff --git a/res/drawable-xxhdpi/ic_done_white.png b/res/drawable-xxhdpi/ic_done_white.png new file mode 100644 index 000000000000..0ebb55559b55 Binary files /dev/null and b/res/drawable-xxhdpi/ic_done_white.png differ diff --git a/res/drawable-xxxhdpi/arrow_right.png b/res/drawable-xxxhdpi/arrow_right.png new file mode 100644 index 000000000000..427adf0bd48a Binary files /dev/null and b/res/drawable-xxxhdpi/arrow_right.png differ diff --git a/res/drawable/indicator_dot_not_selected.xml b/res/drawable/indicator_dot_not_selected.xml new file mode 100644 index 000000000000..808504381017 --- /dev/null +++ b/res/drawable/indicator_dot_not_selected.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/indicator_dot_selected.xml b/res/drawable/indicator_dot_selected.xml new file mode 100644 index 000000000000..301ed3d2ba2b --- /dev/null +++ b/res/drawable/indicator_dot_selected.xml @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/res/drawable/round_button.xml b/res/drawable/round_button.xml new file mode 100644 index 000000000000..56b152d74280 --- /dev/null +++ b/res/drawable/round_button.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/drawable/whats_new_progress_transition.xml b/res/drawable/whats_new_progress_transition.xml new file mode 100644 index 000000000000..d13dc2c04872 --- /dev/null +++ b/res/drawable/whats_new_progress_transition.xml @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/whats_new_activity.xml b/res/layout/whats_new_activity.xml new file mode 100644 index 000000000000..54ff9bd427cb --- /dev/null +++ b/res/layout/whats_new_activity.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/whats_new_element.xml b/res/layout/whats_new_element.xml new file mode 100644 index 000000000000..d218b5194512 --- /dev/null +++ b/res/layout/whats_new_element.xml @@ -0,0 +1,62 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/values/dims.xml b/res/values/dims.xml index 068ea6df6ad2..3edc07b0aae0 100644 --- a/res/values/dims.xml +++ b/res/values/dims.xml @@ -38,6 +38,7 @@ 8dp 4dp 16dp + 32dp 8dp 4dp 2dp diff --git a/res/values/setup.xml b/res/values/setup.xml index 5947e62bed2f..87021066323f 100644 --- a/res/values/setup.xml +++ b/res/values/setup.xml @@ -1,5 +1,8 @@ + + false + Nextcloud nextcloud diff --git a/res/values/strings.xml b/res/values/strings.xml index 359597a328ec..a595977b7d8a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -347,7 +347,7 @@ An error occurred while waiting for the server; the operation couldn\'t be completed An error occurred while waiting for the server; the operation couldn\'t be completed The operation couldn\'t be completed; server is unavailable - + You do not have permission %s to rename this file @@ -545,4 +545,18 @@ SD card %1$d Unknown + + What\'s new in Nextcloud + + + A safe home for all your data + Access, share & protect your files at home and in your enterprise + + Multi account + Connect to all your clouds + + Instant upload + Keep your photos safe + + Skip diff --git a/res/values/styles.xml b/res/values/styles.xml index 664f6bfd9590..e7e598e6669a 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -113,6 +113,10 @@ @color/color_accent + + + + \ No newline at end of file diff --git a/src/com/owncloud/android/MainApp.java b/src/com/owncloud/android/MainApp.java index 56345e7c8dd1..d218a6f88b56 100644 --- a/src/com/owncloud/android/MainApp.java +++ b/src/com/owncloud/android/MainApp.java @@ -41,6 +41,7 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.services.observer.SyncedFolderObserverService; import com.owncloud.android.ui.activity.Preferences; +import com.owncloud.android.ui.activity.WhatsNewActivity; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -118,6 +119,7 @@ public class MainApp extends Application { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log_OC.d(activity.getClass().getSimpleName(), "onCreate(Bundle) starting" ); + WhatsNewActivity.runIfNeeded(activity); PassCodeManager.getPassCodeManager().onActivityCreated(activity); } @@ -174,6 +176,17 @@ public static String getAccountType() { return getAppContext().getResources().getString(R.string.account_type); } + // Non gradle build systems do not provide BuildConfig.VERSION_CODE + // so we must fallback to this method :( + public static int getVersionCode() { + try { + String thisPackageName = getAppContext().getPackageName(); + return getAppContext().getPackageManager().getPackageInfo(thisPackageName, 0).versionCode; + } catch (PackageManager.NameNotFoundException e) { + return 0; + } + } + // From AccountAuthenticator // public static final String AUTHORITY = "org.owncloud"; public static String getAuthority() { diff --git a/src/com/owncloud/android/features/FeatureList.java b/src/com/owncloud/android/features/FeatureList.java new file mode 100644 index 000000000000..7ce36ffaa3d2 --- /dev/null +++ b/src/com/owncloud/android/features/FeatureList.java @@ -0,0 +1,162 @@ +/** + * Nextcloud Android client application + * + * @author Bartosz Przybylski + * Copyright (C) 2015 Bartosz Przybylski + * Copyright (C) 2015 ownCloud Inc. + * Copyright (C) 2016 Nextcloud. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this program. If not, see . + */ + +package com.owncloud.android.features; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.owncloud.android.MainApp; +import com.owncloud.android.R; +import com.owncloud.android.lib.common.utils.Log_OC; + +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; + +/** + * @author Bartosz Przybylski + */ +public class FeatureList { + private static final boolean SHOW_ON_FIRST_RUN = true; + + private static final String VERSION_1_0_0 = "1.0.0"; + private static final String BETA_VERSION_0 = "0"; + + static final private FeatureItem featuresList[] = { + // Basic features showed on first install + new FeatureItem(R.drawable.whats_new_files, + R.string.welcome_feature_1_title, R.string.welcome_feature_1_text, + VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN), + new FeatureItem(R.drawable.whats_new_accounts, + R.string.welcome_feature_2_title, R.string.welcome_feature_2_text, + VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN), + new FeatureItem(R.drawable.what_new_instant_upload, + R.string.welcome_feature_3_title, R.string.welcome_feature_3_text, + VERSION_1_0_0, BETA_VERSION_0, SHOW_ON_FIRST_RUN), + // Features introduced in certain point in time + }; + + static public FeatureItem[] get() { + return featuresList; + } + + static public FeatureItem[] getFiltered(final int lastSeenVersionCode, final boolean isFirstRun, boolean isBeta) { + List features = new LinkedList<>(); + + for (FeatureItem item : get()) { + final int itemVersionCode = isBeta ? item.getBetaVersionNumber() : item.getVersionNumber(); + if (isFirstRun && item.shouldShowOnFirstRun()) { + features.add(item); + } else if (!isFirstRun && !item.shouldShowOnFirstRun() && + MainApp.getVersionCode() >= itemVersionCode && + lastSeenVersionCode < itemVersionCode) { + features.add(item); + } + } + return features.toArray(new FeatureItem[features.size()]); + } + + static public class FeatureItem implements Parcelable { + public static final int DO_NOT_SHOW = -1; + private int image; + private int titleText; + private int contentText; + private int versionNumber; + private int betaVersion; + private boolean showOnInitialRun; + + public FeatureItem(int image, int titleText, int contentText, String version, String betaVersion) { + this(image, titleText, contentText, version, betaVersion, false); + } + + public FeatureItem(int image, int titleText, int contentText, String version, String betaVersion, boolean showOnInitialRun) { + this.image = image; + this.titleText = titleText; + this.contentText = contentText; + this.versionNumber = versionCodeFromString(version); + this.betaVersion = Integer.parseInt(betaVersion); + this.showOnInitialRun = showOnInitialRun; + } + + public boolean shouldShowImage() { return image != DO_NOT_SHOW; } + public int getImage() { return image; } + + public boolean shouldShowTitleText() { return titleText != DO_NOT_SHOW; } + public int getTitleText() { return titleText; } + + public boolean shouldShowContentText() { return contentText != DO_NOT_SHOW; } + public int getContentText() { return contentText; } + + public int getVersionNumber() { return versionNumber; } + public int getBetaVersionNumber() { return betaVersion; } + public boolean shouldShowOnFirstRun() { return showOnInitialRun; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(image); + dest.writeInt(titleText); + dest.writeInt(contentText); + dest.writeInt(versionNumber); + dest.writeInt(betaVersion); + dest.writeByte((byte) (showOnInitialRun ? 1 : 0)); + } + + private FeatureItem(Parcel p) { + image = p.readInt(); + titleText = p.readInt(); + contentText = p.readInt(); + versionNumber = p.readInt(); + betaVersion = p.readInt(); + showOnInitialRun = p.readByte() == 1; + } + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + + @Override + public Object createFromParcel(Parcel source) { + return new FeatureItem(source); + } + + @Override + public Object[] newArray(int size) { + return new FeatureItem[size]; + } + }; + } + + private static int versionCodeFromString(String version) { + String v[] = version.split(Pattern.quote(".")); + if (v.length != 3) { + Log_OC.e("FeatureList", "Version string is incorrect " + version); + return 0; + } + return Integer.parseInt(v[0])*(int)(10e6) + + Integer.parseInt(v[1])*(int)(10e4) + + Integer.parseInt(v[2])*100; + } +} diff --git a/src/com/owncloud/android/ui/activity/WhatsNewActivity.java b/src/com/owncloud/android/ui/activity/WhatsNewActivity.java new file mode 100644 index 000000000000..16e7f630d9b0 --- /dev/null +++ b/src/com/owncloud/android/ui/activity/WhatsNewActivity.java @@ -0,0 +1,249 @@ +/** + * Nextcloud Android client application + * + * @author Bartosz Przybylski + * Copyright (C) 2015 Bartosz Przybylski + * Copyright (C) 2015 ownCloud Inc. + * Copyright (C) 2016 Nextcloud. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +import com.owncloud.android.MainApp; +import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountAuthenticatorActivity; +import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.features.FeatureList; +import com.owncloud.android.features.FeatureList.FeatureItem; +import com.owncloud.android.ui.whatsnew.ProgressIndicator; + +/** + * Activity displaying general feature after a fresh install and new features after an update. + */ +public class WhatsNewActivity extends FragmentActivity implements ViewPager.OnPageChangeListener { + + private static final String KEY_LAST_SEEN_VERSION_CODE = "lastSeenVersionCode"; + + private ImageButton mForwardFinishButton; + private Button mSkipButton; + private ProgressIndicator mProgress; + private ViewPager mPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.whats_new_activity); + + mProgress = (ProgressIndicator) findViewById(R.id.progressIndicator); + mPager = (ViewPager)findViewById(R.id.contentPanel); + final boolean isBeta = getResources().getBoolean(R.bool.is_beta); + FeaturesViewAdapter adapter = new FeaturesViewAdapter(getSupportFragmentManager(), + FeatureList.getFiltered(getLastSeenVersionCode(), isFirstRun(), isBeta)); + + mProgress.setNumberOfSteps(adapter.getCount()); + mPager.setAdapter(adapter); + mPager.addOnPageChangeListener(this); + + + mForwardFinishButton = (ImageButton) findViewById(R.id.forward); + mForwardFinishButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mProgress.hasNextStep()) { + mPager.setCurrentItem(mPager.getCurrentItem()+1, true); + mProgress.animateToStep(mPager.getCurrentItem()+1); + } else { + onFinish(); + finish(); + } + updateNextButtonIfNeeded(); + } + }); + + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mForwardFinishButton.setBackground(null); + } else { + mForwardFinishButton.setBackgroundDrawable(null); + } + + mSkipButton = (Button) findViewById(R.id.skip); + mSkipButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onFinish(); + finish(); + } + }); + + TextView tv = (TextView)findViewById(R.id.welcomeText); + tv.setText(isFirstRun() ? R.string.empty : R.string.whats_new_title); + + updateNextButtonIfNeeded(); + } + + @Override + public void onBackPressed() { + onFinish(); + super.onBackPressed(); + } + + + private void updateNextButtonIfNeeded() { + if (!mProgress.hasNextStep()) { + mForwardFinishButton.setImageResource(R.drawable.ic_done_white); + mSkipButton.setVisibility(View.INVISIBLE); + } else { + mForwardFinishButton.setImageResource(R.drawable.arrow_right); + mSkipButton.setVisibility(View.VISIBLE); + } + } + + private void onFinish() { + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = pref.edit(); + editor.putInt(KEY_LAST_SEEN_VERSION_CODE, MainApp.getVersionCode()); + editor.apply(); + } + + static private int getLastSeenVersionCode() { + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(MainApp.getAppContext()); + return pref.getInt(KEY_LAST_SEEN_VERSION_CODE, 0); + } + + static private boolean isFirstRun() { + return getLastSeenVersionCode() == 0 && AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext()) == null; + } + + static public void runIfNeeded(Context context) { + if (context instanceof WhatsNewActivity) { + return; + } + + if (shouldShow(context)) { + context.startActivity(new Intent(context, WhatsNewActivity.class)); + } + } + + static private boolean shouldShow(Context context) { + final boolean isBeta = context.getResources().getBoolean(R.bool.is_beta); + return (isFirstRun() && context instanceof AccountAuthenticatorActivity) || + ( + !(isFirstRun() && (context instanceof FileDisplayActivity)) && + !(context instanceof PassCodeActivity) && + (FeatureList.getFiltered(getLastSeenVersionCode(), isFirstRun(), isBeta).length > 0) + ); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + // unused but to be implemented due to abstract parent + } + + @Override + public void onPageSelected(int position) { + mProgress.animateToStep(position+1); + updateNextButtonIfNeeded(); + } + + @Override + public void onPageScrollStateChanged(int state) { + // unused but to be implemented due to abstract parent + } + + private final class FeaturesViewAdapter extends FragmentPagerAdapter { + + private FeatureItem[] mFeatures; + + public FeaturesViewAdapter(FragmentManager fm, FeatureItem[]features) { + super(fm); + mFeatures = features; + } + + @Override + public Fragment getItem(int position) { + return FeatureFragment.newInstance(mFeatures[position]); + } + + @Override + public int getCount() { + return mFeatures.length; + } + } + + public static class FeatureFragment extends Fragment { + private FeatureItem mItem; + + static public FeatureFragment newInstance(FeatureItem item) { + FeatureFragment f = new FeatureFragment(); + Bundle args = new Bundle(); + args.putParcelable("feature", item); + f.setArguments(args); + return f; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mItem = getArguments() != null ? (FeatureItem)getArguments().getParcelable("feature") : null; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.whats_new_element, container, false); + + ImageView iv = (ImageView)v.findViewById(R.id.whatsNewImage); + if (mItem.shouldShowImage()) { + iv.setImageResource(mItem.getImage()); + } + + TextView tv2 = (TextView)v.findViewById(R.id.whatsNewTitle); + if (mItem.shouldShowTitleText()) { + tv2.setText(mItem.getTitleText()); + } + + tv2 = (TextView)v.findViewById(R.id.whatsNewText); + if (mItem.shouldShowContentText()) { + tv2.setText(mItem.getContentText()); + } + + return v; + } + } + +} diff --git a/src/com/owncloud/android/ui/whatsnew/ProgressIndicator.java b/src/com/owncloud/android/ui/whatsnew/ProgressIndicator.java new file mode 100644 index 000000000000..1f51dca92eb1 --- /dev/null +++ b/src/com/owncloud/android/ui/whatsnew/ProgressIndicator.java @@ -0,0 +1,103 @@ +/** + * Nextcloud Android client application + * + * @author Bartosz Przybylski + * Copyright (C) 2015 Bartosz Przybylski + * Copyright (C) 2015 ownCloud Inc. + * Copyright (C) 2016 Nextcloud. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this program. If not, see . + */ + +package com.owncloud.android.ui.whatsnew; + +import android.content.Context; +import android.graphics.drawable.TransitionDrawable; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.owncloud.android.R; + +/** + * Progress indicator visualizing the actual progress with dots. + */ +public class ProgressIndicator extends FrameLayout { + + protected LinearLayout mDotsContainer; + + protected int mNumberOfSteps = -1; + protected int mCurrentStep = -1; + + public ProgressIndicator(Context context) { + super(context); + setup(); + } + + public ProgressIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + setup(); + } + + public ProgressIndicator(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setup(); + } + + public boolean hasNextStep() { + return mNumberOfSteps > mCurrentStep; + } + + public void setNumberOfSteps(int steps) { + mNumberOfSteps = steps; + mDotsContainer.removeAllViews(); + for (int i = 0; i < steps; ++i) { + ImageView iv = new ImageView(getContext()); + iv.setImageDrawable(getContext().getResources().getDrawable(R.drawable.whats_new_progress_transition)); + mDotsContainer.addView(iv); + } + animateToStep(1); + } + + public void animateToStep(int step) { + if (step < 1 || step > mNumberOfSteps) { + return; + } + + if (mCurrentStep != -1) { + ImageView prevDot = (ImageView) mDotsContainer.getChildAt(mCurrentStep-1); + TransitionDrawable transition = (TransitionDrawable)prevDot.getDrawable(); + transition.resetTransition(); + } + + mCurrentStep = step; + ImageView dot = (ImageView)mDotsContainer.getChildAt(step-1); + TransitionDrawable transition = (TransitionDrawable)dot.getDrawable(); + transition.startTransition(500); + } + + private void setup() { + mDotsContainer = new LinearLayout(getContext()); + mDotsContainer.setGravity(Gravity.CENTER); + FrameLayout.LayoutParams params = generateDefaultLayoutParams(); + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + mDotsContainer.setLayoutParams(params); + addView(mDotsContainer); + } + +}