Account setup flow: Move button and headline handling into fragments

b/13508015

Change-Id: I9f7a09467fbee5a57985f36eaa47c2cc7b9d4086
This commit is contained in:
Tony Mantler 2014-03-17 16:45:47 -07:00
parent 7fbf3ac6d1
commit ae980cd685
27 changed files with 267 additions and 238 deletions

View File

@ -16,6 +16,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- TODO: This file is basically pointless -->
<ImageButton
style="@style/accountSetupNavButton"
android:contentDescription="@string/previous_action"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
<!-- Copyright (C) 2010 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.
@ -14,25 +14,26 @@
limitations under the License.
-->
<!-- Account Setup Layout - XL - landscape - see layout/ for small-screen version -->
<!-- Account Names - XL - portrait - see layout/ for small-screen version -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@drawable/account_setup_background" >
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/setup_padding_top"
android:paddingLeft="@dimen/setup_padding_left"
android:paddingRight="@dimen/setup_padding_right" >
android:paddingRight="@dimen/setup_padding_right"
>
<!-- Headline and hairline divider -->
<!-- Set headline for first fragment, change in code as we progress through screens -->
<TextView
android:id="@+id/headline"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -40,32 +41,23 @@
android:textAppearance="@style/accountSetupHeadline" />
<View
android:id="@+id/top_divider"
android:layout_below="@+id/headline"
android:layout_marginBottom="16dip"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/account_setup_divider_color" />
<!-- Buttons on the right -->
<FrameLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/top_divider"
android:layout_alignParentRight="true"
android:id="@+id/buttons">
<include layout="@layout/account_setup_buttons" />
</FrameLayout>
<!-- Primary fragment on the left -->
<!-- Primary Content -->
<FrameLayout
android:layout_below="@+id/top_divider"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dip"
android:paddingRight="64dip"
>
<include layout="@layout/account_setup_fragment_container" />
</FrameLayout>
</RelativeLayout>
android:id="@+id/setup_fragment_content"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- Buttons below that -->
<!-- TODO: buttons on either side -->
<include layout="@layout/account_setup_buttons" />
</LinearLayout>
</ScrollView>

View File

@ -47,11 +47,14 @@
android:background="@color/account_setup_divider_color" />
<!-- Primary fragment -->
<include layout="@layout/account_setup_fragment_container" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/setup_fragment_content"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- Buttons below that -->
<include layout="@layout/account_setup_buttons" />

View File

@ -14,24 +14,8 @@
limitations under the License.
-->
<LinearLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/account_credentials_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/setup_fragment_padding_top"
android:paddingLeft="@dimen/setup_fragment_padding_left"
android:paddingRight="@dimen/setup_fragment_padding_right" >
<FrameLayout
android:id="@+id/account_credentials_fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="@+id/button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/account_settings_buttons" />
</FrameLayout>
</LinearLayout>
android:layout_height="match_parent" />

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/setup_fragment_padding_top"
android:paddingLeft="@dimen/setup_fragment_padding_left"
android:paddingRight="@dimen/setup_fragment_padding_right" >
<FrameLayout
android:id="@+id/account_credentials_fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="@+id/button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/account_settings_buttons" />
</FrameLayout>
</LinearLayout>

View File

@ -14,13 +14,10 @@
limitations under the License.
-->
<!-- Fragment view -->
<FrameLayout
android:id="@+id/setup_fragment_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/setup_item_inset_left"
android:paddingRight="@dimen/setup_item_inset_right" >
<!-- Don't include the fragment itself here, or we won't be able to swap it out later -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@drawable/account_setup_background"
android:id="@+id/setup_fragment_container">
</FrameLayout>

View File

@ -63,7 +63,7 @@
android:orientation="vertical"
android:visibility="gone">
<Button
android:id="@+id/sign_in_with_google"
android:id="@+id/sign_in_with_oauth"
android:text="@string/sign_in_with_google"
android:layout_gravity="center"
android:layout_width="wrap_content"
@ -86,15 +86,6 @@
android:imeOptions="actionDone"/>
</LinearLayout>
<EditText
android:id="@+id/regular_password"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="@string/account_setup_incoming_password_label"
android:inputType="textPassword"
android:imeOptions="actionNext"
android:visibility="gone"/>
<include
android:id="@+id/client_certificate_selector"
layout="@layout/client_certificate_selector"

View File

@ -37,7 +37,10 @@
android:text="@string/account_setup_options_headline"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary" />
<include layout="@layout/account_setup_fragment_container"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/setup_fragment_content"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"

View File

@ -10,10 +10,7 @@ import com.android.email.R;
import com.android.email.activity.UiUtilities;
public class AccountCredentials extends Activity
implements AccountSetupCredentialsFragment.Callback, View.OnClickListener {
private View mDoneButton;
private View mCancelButton;
implements AccountSetupCredentialsFragment.Callback {
private static final String EXTRA_EMAIL = "email";
private static final String EXTRA_PROTOCOL = "protocol";
@ -37,16 +34,11 @@ public class AccountCredentials extends Activity
final AccountSetupCredentialsFragment f =
AccountSetupCredentialsFragment.newInstance(emailAddress, protocol,
null /* clientCert */, false /* passwordFailed */);
null /* clientCert */, false /* passwordFailed */, true /* standalone */);
getFragmentManager().beginTransaction()
.add(R.id.account_credentials_fragment_container, f, CREDENTIALS_FRAGMENT_TAG)
.commit();
mDoneButton = UiUtilities.getView(this, R.id.done);
mCancelButton = UiUtilities.getView(this, R.id.cancel);
mDoneButton.setOnClickListener(this);
mCancelButton.setOnClickListener(this);
// Assume canceled until we find out otherwise.
setResult(RESULT_CANCELED);
}
@ -60,19 +52,10 @@ public class AccountCredentials extends Activity
}
@Override
public void onClick(View view) {
if (view == mDoneButton) {
final AccountSetupCredentialsFragment fragment = (AccountSetupCredentialsFragment)
getFragmentManager().findFragmentByTag(CREDENTIALS_FRAGMENT_TAG);
final Bundle results = fragment.getCredentialResults();
onCredentialsComplete(results);
} else if (view == mCancelButton) {
finish();
}
}
@Override
public void setNextButtonEnabled(boolean enabled) {
mDoneButton.setEnabled(enabled);
public void onNextButton() {
final AccountSetupCredentialsFragment fragment = (AccountSetupCredentialsFragment)
getFragmentManager().findFragmentByTag(CREDENTIALS_FRAGMENT_TAG);
final Bundle results = fragment.getCredentialResults();
onCredentialsComplete(results);
}
}

View File

@ -178,13 +178,13 @@ public abstract class AccountServerBaseFragment extends AccountSetupFragment
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cancel:
getActivity().onBackPressed();
break;
case R.id.done:
collectUserInput();
break;
final int viewId = v.getId();
if (viewId == R.id.cancel) {
getActivity().onBackPressed();
} else if (viewId == R.id.done) {
collectUserInput();
} else {
super.onClick(v);
}
}
@ -196,11 +196,8 @@ public abstract class AccountServerBaseFragment extends AccountSetupFragment
// enable it directly, here
if (mProceedButton != null) {
mProceedButton.setEnabled(enable);
}
final Callback callback = (Callback) getActivity();
if (callback != null) {
callback.setNextButtonEnabled(enable);
} else {
setNextButtonEnabled(enable);
}
}

View File

@ -654,7 +654,7 @@ public class AccountSettings extends PreferenceActivity implements
}
@Override
public void setNextButtonEnabled(boolean enabled) {}
public void onNextButton() {}
/**
* Save process is done, dismiss the fragment.

View File

@ -46,8 +46,8 @@ public class AccountSetupBasicsFragment extends AccountSetupFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.account_setup_basics_fragment, container,
false);
final View view = inflateTemplatedView(inflater, container,
R.layout.account_setup_basics_fragment, R.string.account_setup_basics_headline);
mEmailView = UiUtilities.getView(view, R.id.account_email);
mManualSetupView = UiUtilities.getView(view, R.id.manual_setup);
@ -67,6 +67,8 @@ public class AccountSetupBasicsFragment extends AccountSetupFragment {
mEmailView.addTextChangedListener(textWatcher);
setPreviousButtonVisibility(View.INVISIBLE);
return view;
}
@ -84,8 +86,7 @@ public class AccountSetupBasicsFragment extends AccountSetupFragment {
&& addresses.length == 1
&& !TextUtils.isEmpty(addresses[0].getAddress());
final Callback callback = (Callback) getActivity();
callback.setNextButtonEnabled(emailValid);
setNextButtonEnabled(emailValid);
}
public void setEmail(final String email) {

View File

@ -57,6 +57,7 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
private static final String EXTRA_EMAIL = "email";
private static final String EXTRA_PROTOCOL = "protocol";
private static final String EXTRA_PASSWORD_FAILED = "password_failed";
private static final String EXTRA_STANDALONE = "standalone";
public static final String EXTRA_PASSWORD = "password";
public static final String EXTRA_CLIENT_CERT = "certificate";
@ -73,15 +74,18 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
private TextView mPasswordWarningLabel;
private TextView mEmailConfirmationLabel;
private TextView mEmailConfirmation;
private CertificateSelector mClientCertificateSelector;
private View mDeviceIdSection;
private TextView mDeviceId;
private String mEmailAddress;
private boolean mOfferOAuth;
private boolean mOfferCerts;
private String mProviderId;
private Context mAppContext;
private Bundle mResults;
private CertificateSelector mClientCertificateSelector;
private View mDeviceIdSection;
private TextView mDeviceId;
public interface Callback extends AccountSetupFragment.Callback {
void onCredentialsComplete(Bundle results);
@ -91,16 +95,21 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
* Create a new instance of this fragment with the appropriate email and protocol
* @param email login address for OAuth purposes
* @param protocol protocol of the service we're gathering credentials for
* @param clientCert alias of existing client cert
* @param passwordFailed true if the password attempt previously failed
* @param standalone true if this is not being inserted in the setup flow
* @return new fragment instance
*/
public static AccountSetupCredentialsFragment newInstance(final String email,
final String protocol, final String clientCert, final boolean passwordFailed) {
final String protocol, final String clientCert, final boolean passwordFailed,
final boolean standalone) {
final AccountSetupCredentialsFragment f = new AccountSetupCredentialsFragment();
final Bundle b = new Bundle(4);
final Bundle b = new Bundle(5);
b.putString(EXTRA_EMAIL, email);
b.putString(EXTRA_PROTOCOL, protocol);
b.putString(EXTRA_CLIENT_CERT, clientCert);
b.putBoolean(EXTRA_PASSWORD_FAILED, passwordFailed);
b.putBoolean(EXTRA_STANDALONE, standalone);
f.setArguments(b);
return f;
}
@ -108,13 +117,24 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.account_setup_credentials_fragment, container,
false);
final boolean standalone = getArguments().getBoolean(EXTRA_STANDALONE);
final View view;
if (standalone) {
view = inflater.inflate(R.layout.account_credentials_fragment, container, false);
mNextButton = UiUtilities.getView(view, R.id.done);
mNextButton.setOnClickListener(this);
mPreviousButton = UiUtilities.getView(view, R.id.cancel);
mPreviousButton.setOnClickListener(this);
} else {
// TODO: real headline string instead of sign_in_title
view = inflateTemplatedView(inflater, container,
R.layout.account_setup_credentials_fragment, R.string.sign_in_title);
}
mImapPasswordText = UiUtilities.getView(view, R.id.imap_password);
mRegularPasswordText = UiUtilities.getView(view, R.id.regular_password);
mOAuthGroup = UiUtilities.getView(view, R.id.oauth_group);
mOAuthButton = UiUtilities.getView(view, R.id.sign_in_with_google);
mOAuthButton = UiUtilities.getView(view, R.id.sign_in_with_oauth);
mOAuthButton.setOnClickListener(this);
mClientCertificateSelector = UiUtilities.getView(view, R.id.client_certificate_selector);
mDeviceIdSection = UiUtilities.getView(view, R.id.device_id_section);
@ -233,10 +253,7 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
}
public void validatePassword() {
final Callback callback = (Callback) getActivity();
if (callback != null) {
callback.setNextButtonEnabled(!TextUtils.isEmpty(getPassword()));
}
setNextButtonEnabled(!TextUtils.isEmpty(getPassword()));
// Warn (but don't prevent) if password has leading/trailing spaces
AccountSettingsUtils.checkPasswordSpaces(mAppContext, mImapPasswordText);
AccountSettingsUtils.checkPasswordSpaces(mAppContext, mRegularPasswordText);
@ -284,7 +301,8 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
@Override
public void onClick(final View view) {
if (view == mOAuthButton) {
final int viewId = view.getId();
if (viewId == R.id.sign_in_with_oauth) {
List<OAuthProvider> oauthProviders = AccountSettingsUtils.getAllOAuthProviders(
mAppContext);
// TODO currently the only oauth provider we support is google.
@ -297,6 +315,14 @@ public class AccountSetupCredentialsFragment extends AccountSetupFragment
i.putExtra(OAuthAuthenticationActivity.EXTRA_PROVIDER, mProviderId);
startActivityForResult(i, OAuthAuthenticationActivity.REQUEST_OAUTH);
}
} else if (viewId == R.id.done) {
final Callback callback = (Callback) getActivity();
callback.onNextButton();
} else if (viewId == R.id.cancel) {
final Callback callback = (Callback) getActivity();
callback.onBackPressed();
} else {
super.onClick(view);
}
}

View File

@ -36,26 +36,21 @@ import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.VendorPolicyLoader;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
public class AccountSetupFinal extends AccountSetupActivity
implements View.OnClickListener, AccountFinalizeFragment.Callback,
implements AccountFinalizeFragment.Callback,
AccountSetupNoteDialogFragment.Callback, AccountCreationFragment.Callback,
AccountCheckSettingsFragment.Callback, SecurityRequiredDialogFragment.Callback,
CheckSettingsErrorDialogFragment.Callback, CheckSettingsProgressDialogFragment.Callback,
@ -168,10 +163,6 @@ public class AccountSetupFinal extends AccountSetupActivity
private VendorPolicyLoader.Provider mProvider;
private boolean mPasswordFailed;
// UI elements
@VisibleForTesting
protected ImageButton mNextButton;
private static final int OWNER_NAME_LOADER_ID = 0;
private String mOwnerName;
@ -209,7 +200,7 @@ public class AccountSetupFinal extends AccountSetupActivity
INTENT_CREATE_ACCOUNT = getString(R.string.intent_create_account);
}
setContentView(R.layout.account_setup);
setContentView(R.layout.account_setup_activity);
if (savedInstanceState != null) {
mIsProcessing = savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PROCESSING, false);
@ -224,8 +215,6 @@ public class AccountSetupFinal extends AccountSetupActivity
savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED);
mSkipAutoDiscover = savedInstanceState.getBoolean(SAVESTATE_KEY_SKIP_AUTO_DISCOVER);
mPasswordFailed = savedInstanceState.getBoolean(SAVESTATE_KEY_PASSWORD_FAILED);
// I don't know why this view state doesn't get restored
updateHeadline();
} else {
// If we're not restoring from a previous state, we want to configure the initial screen
@ -263,15 +252,10 @@ public class AccountSetupFinal extends AccountSetupActivity
} else if (TextUtils.equals(ACTION_JUMP_TO_OPTIONS, action)) {
mState = STATE_OPTIONS;
}
updateHeadline();
updateContentFragment(false /* addToBackstack */);
mPasswordFailed = false;
}
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
mNextButton = UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
if (!mIsProcessing
&& mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
/**
@ -342,7 +326,6 @@ public class AccountSetupFinal extends AccountSetupActivity
}
mState = STATE_OPTIONS;
updateHeadline();
updateContentFragment(false /* addToBackstack */);
getFragmentManager().executePendingTransactions();
@ -445,39 +428,6 @@ public class AccountSetupFinal extends AccountSetupActivity
outState.putBoolean(SAVESTATE_KEY_PASSWORD_FAILED, mPasswordFailed);
}
/**
* Set the headline text according to mState.
*/
private void updateHeadline() {
TextView headlineView = UiUtilities.getView(this, R.id.headline);
switch (mState) {
case STATE_BASICS:
headlineView.setText(R.string.account_setup_basics_headline);
break;
case STATE_TYPE:
headlineView.setText(R.string.account_setup_account_type_headline);
break;
case STATE_CREDENTIALS:
// TODO: real string
headlineView.setText(R.string.sign_in_title);
break;
case STATE_MANUAL_INCOMING:
headlineView.setText(R.string.account_setup_incoming_headline);
break;
case STATE_MANUAL_OUTGOING:
headlineView.setText(R.string.account_setup_outgoing_headline);
break;
case STATE_OPTIONS:
headlineView.setText(R.string.account_setup_options_headline);
break;
case STATE_NAMES:
headlineView.setText(R.string.account_setup_names_headline);
break;
default:
throw new IllegalStateException("Incorrect state" + mState);
}
}
/**
* Swap in the new fragment according to mState. This pushes the current fragment onto the back
* stack, so only call it once per transition.
@ -496,7 +446,7 @@ public class AccountSetupFinal extends AccountSetupActivity
case STATE_CREDENTIALS:
f = AccountSetupCredentialsFragment.newInstance(mSetupData.getEmail(),
mSetupData.getIncomingProtocol(this), mSetupData.getClientCert(this),
mPasswordFailed);
mPasswordFailed, false /* standalone */);
backstackTag = CREDENTIALS_BACKSTACK_TAG;
break;
case STATE_MANUAL_INCOMING:
@ -538,7 +488,6 @@ public class AccountSetupFinal extends AccountSetupActivity
private void resetStateFromCurrentFragment() {
AccountSetupFragment f = getContentFragment();
mState = f.getState();
updateHeadline();
}
/**
@ -547,7 +496,10 @@ public class AccountSetupFinal extends AccountSetupActivity
*/
protected void proceed() {
mIsProcessing = false;
setNextButtonEnabled(true);
final AccountSetupFragment oldContentFragment = getContentFragment();
if (oldContentFragment != null) {
oldContentFragment.setNextButtonEnabled(true);
}
getFragmentManager().executePendingTransactions();
@ -590,13 +542,11 @@ public class AccountSetupFinal extends AccountSetupActivity
}
}
}
updateHeadline();
updateContentFragment(true /* addToBackstack */);
break;
case STATE_TYPE:
// We either got here through "Manual Setup" or because we didn't find the provider
mState = STATE_CREDENTIALS;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
break;
case STATE_CREDENTIALS:
@ -608,7 +558,6 @@ public class AccountSetupFinal extends AccountSetupActivity
} else {
if (mSkipAutoDiscover) {
mState = STATE_MANUAL_INCOMING;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
} else {
mState = STATE_AUTO_DISCOVER;
@ -628,19 +577,16 @@ public class AccountSetupFinal extends AccountSetupActivity
resetStateFromCurrentFragment();
} else {
mState = STATE_MANUAL_INCOMING;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
}
} else {
mState = STATE_OPTIONS;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
}
break;
case STATE_AUTO_DISCOVER:
// TODO: figure out if we can skip past manual setup
mState = STATE_MANUAL_INCOMING;
updateHeadline();
updateContentFragment(true);
break;
case STATE_MANUAL_INCOMING:
@ -656,7 +602,6 @@ public class AccountSetupFinal extends AccountSetupActivity
} else {
mState = STATE_OPTIONS;
}
updateHeadline();
updateContentFragment(true /* addToBackstack */);
break;
case STATE_MANUAL_OUTGOING:
@ -666,7 +611,6 @@ public class AccountSetupFinal extends AccountSetupActivity
break;
case STATE_CHECKING_OUTGOING:
mState = STATE_OPTIONS;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
break;
case STATE_OPTIONS:
@ -675,7 +619,6 @@ public class AccountSetupFinal extends AccountSetupActivity
break;
case STATE_CREATING:
mState = STATE_NAMES;
updateHeadline();
updateContentFragment(true /* addToBackstack */);
if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
getFragmentManager().executePendingTransactions();
@ -731,29 +674,14 @@ public class AccountSetupFinal extends AccountSetupActivity
super.finish();
}
/**
* Respond to clicks in the "Next" or "Previous" buttons
*/
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.next:
// Some states are handled without UI, block double-presses here
if (!mIsProcessing) {
proceed();
}
break;
case R.id.previous:
onBackPressed();
break;
public void onNextButton() {
// Some states are handled without UI, block double-presses here
if (!mIsProcessing) {
proceed();
}
}
@Override
public void setNextButtonEnabled(final boolean enabled) {
mNextButton.setEnabled(enabled);
}
/**
* @return true to proceed, false to remain on the current screen
*/
@ -1056,7 +984,7 @@ public class AccountSetupFinal extends AccountSetupActivity
*/
private void initiateAccountCreation() {
mIsProcessing = true;
setNextButtonEnabled(false);
getContentFragment().setNextButtonEnabled(false);
final Account account = mSetupData.getAccount();
if (account.mHostAuthRecv == null) {
@ -1212,7 +1140,7 @@ public class AccountSetupFinal extends AccountSetupActivity
*/
private void initiateAccountFinalize() {
mIsProcessing = true;
setNextButtonEnabled(false);
getContentFragment().setNextButtonEnabled(false);
AccountSetupNamesFragment fragment = (AccountSetupNamesFragment) getContentFragment();
// Update account object from UI

View File

@ -18,18 +18,30 @@ package com.android.email.activity.setup;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.google.common.annotations.VisibleForTesting;
/**
* Superclass for setup UI fragments.
* Currently holds a super-interface for the callbacks, as well as the state it was launched for so
* we can unwind things correctly when the user navigates the back stack.
*/
public class AccountSetupFragment extends Fragment {
public class AccountSetupFragment extends Fragment implements View.OnClickListener {
private static final String SAVESTATE_STATE = "AccountSetupFragment.state";
private int mState;
protected View mNextButton;
protected View mPreviousButton;
public interface Callback {
void setNextButtonEnabled(boolean enabled);
void onNextButton();
void onBackPressed();
}
@Override
@ -53,4 +65,66 @@ public class AccountSetupFragment extends Fragment {
public int getState() {
return mState;
}
/**
* This method wraps the given content layout with the chrome appropriate for the account setup
* flow. It also attaches itself as a click handler to the previous and next buttons.
*
* @param inflater LayoutInflater scoped to the appropriate context
* @param container ViewGroup to inflate the view into
* @param contentLayout Resource ID of the main content layout to insert into the template
* @param headline Resource ID of the headline string
* @return Fully inflated view hierarchy.
*/
protected View inflateTemplatedView(final LayoutInflater inflater, final ViewGroup container,
final int contentLayout, final int headline) {
final View template = inflater.inflate(R.layout.account_setup_template, container, false);
TextView headlineView = UiUtilities.getView(template, R.id.headline);
headlineView.setText(headline);
final ViewGroup contentContainer =
(ViewGroup) template.findViewById(R.id.setup_fragment_content);
inflater.inflate(contentLayout, contentContainer, true);
mNextButton = UiUtilities.getView(template, R.id.next);
mNextButton.setOnClickListener(this);
mPreviousButton = UiUtilities.getView(template, R.id.previous);
mPreviousButton.setOnClickListener(this);
return template;
}
@Override
public void onClick(View v) {
final int viewId = v.getId();
final Callback callback = (Callback) getActivity();
if (viewId == R.id.next) {
callback.onNextButton();
} else if (viewId == R.id.previous) {
callback.onBackPressed();
}
}
public void setNextButtonEnabled(boolean enabled) {
if (mNextButton != null) {
mNextButton.setEnabled(enabled);
}
}
/**
* Set visibility of the "previous" button
* @param visibility {@link View#INVISIBLE}, {@link View#VISIBLE}, {@link View#GONE}
*/
public void setPreviousButtonVisibility(int visibility) {
mPreviousButton.setVisibility(visibility);
}
/**
* Set the visibility of the "next" button
* @param visibility {@link View#INVISIBLE}, {@link View#VISIBLE}, {@link View#GONE}
*/
public void setNextButtonVisibility(int visibility) {
mNextButton.setVisibility(visibility);
}
}

View File

@ -119,11 +119,14 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final int layoutId = mSettingsMode
? R.layout.account_settings_incoming_fragment
: R.layout.account_setup_incoming_fragment;
final View view = inflater.inflate(layoutId, container, false);
final View view;
if (mSettingsMode) {
view = inflater.inflate(R.layout.account_settings_incoming_fragment, container, false);
} else {
view = inflateTemplatedView(inflater, container,
R.layout.account_setup_incoming_fragment,
R.string.account_setup_incoming_headline);
}
mUsernameView = UiUtilities.getView(view, R.id.account_username);
mServerLabelView = UiUtilities.getView(view, R.id.account_server_label);

View File

@ -40,6 +40,7 @@ import com.android.emailcommon.provider.Account;
public class AccountSetupNamesFragment extends AccountSetupFragment {
private EditText mDescription;
private EditText mName;
private View mAccountNameLabel;
private boolean mRequiresName = true;
public interface Callback extends AccountSetupFragment.Callback {
@ -58,18 +59,11 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.account_setup_names_fragment, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final View view = getView();
final View view = inflateTemplatedView(inflater, container,
R.layout.account_setup_names_fragment, R.string.account_setup_names_headline);
mDescription = UiUtilities.getView(view, R.id.account_description);
mName = UiUtilities.getView(view, R.id.account_name);
final View accountNameLabel = UiUtilities.getView(view, R.id.account_name_label);
mAccountNameLabel = UiUtilities.getView(view, R.id.account_name_label);
final TextWatcher validationTextWatcher = new TextWatcher() {
@Override
@ -88,6 +82,18 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
mName.addTextChangedListener(validationTextWatcher);
mName.setKeyListener(TextKeyListener.getInstance(false, TextKeyListener.Capitalize.WORDS));
setPreviousButtonVisibility(View.INVISIBLE);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Make sure the layout is inflated before twiddling with it
getView();
final SetupDataFragment setupData =
((SetupDataFragment.SetupDataContainer) getActivity()).getSetupData();
final int flowMode = setupData.getFlowMode();
@ -109,7 +115,7 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
if (!info.usesSmtp) {
mRequiresName = false;
mName.setVisibility(View.GONE);
accountNameLabel.setVisibility(View.GONE);
mAccountNameLabel.setVisibility(View.GONE);
} else {
if (account.getSenderName() != null) {
mName.setText(account.getSenderName());
@ -165,11 +171,7 @@ public class AccountSetupNamesFragment extends AccountSetupFragment {
mName.setError(null);
}
}
final Callback callback = (Callback) getActivity();
if (callback != null) {
// If we're not attached to the activity, this state probably doesn't need updating
callback.setNextButtonEnabled(enableNextButton);
}
setNextButtonEnabled(enableNextButton);
}
public String getDescription() {

View File

@ -55,8 +55,8 @@ public class AccountSetupOptionsFragment extends AccountSetupFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.account_setup_options_fragment, container,
false);
final View view = inflateTemplatedView(inflater, container,
R.layout.account_setup_options_fragment, R.string.account_setup_options_headline);
mCheckFrequencyView = UiUtilities.getView(view, R.id.account_check_frequency);
mSyncWindowView = UiUtilities.getView(view, R.id.account_sync_window);

View File

@ -101,11 +101,15 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final int layoutId = mSettingsMode
? R.layout.account_settings_outgoing_fragment
: R.layout.account_setup_outgoing_fragment;
final View view;
if (mSettingsMode) {
view = inflater.inflate(R.layout.account_settings_outgoing_fragment, container, false);
} else {
view = inflateTemplatedView(inflater, container,
R.layout.account_setup_outgoing_fragment,
R.string.account_setup_outgoing_headline);
}
final View view = inflater.inflate(layoutId, container, false);
final Context context = getActivity();
mUsernameView = UiUtilities.getView(view, R.id.account_username);

View File

@ -46,7 +46,8 @@ public class AccountSetupTypeFragment extends AccountSetupFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.account_setup_type_fragment, container, false);
final View view = inflateTemplatedView(inflater, container,
R.layout.account_setup_type_fragment, R.string.account_setup_account_type_headline);
final Context appContext = inflater.getContext().getApplicationContext();
@ -76,6 +77,8 @@ public class AccountSetupTypeFragment extends AccountSetupFragment
}
}
setNextButtonVisibility(View.INVISIBLE);
return view;
}