Created
April 28, 2014 15:20
-
-
Save slightfoot/11375255 to your computer and use it in GitHub Desktop.
Example of a Login DialogFragment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:minWidth="280dp" | |
> | |
<LinearLayout | |
android:id="@+id/panel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="vertical" | |
> | |
<EditText | |
android:id="@+id/username" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="8dp" | |
android:inputType="textVisiblePassword" | |
android:nextFocusDown="@+id/password" | |
android:imeOptions="actionNext" | |
android:singleLine="true" | |
android:hint="Username" | |
/> | |
<EditText | |
android:id="@+id/password" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="8dp" | |
android:inputType="textPassword" | |
android:imeOptions="actionDone" | |
android:singleLine="true" | |
android:hint="Password" | |
/> | |
<TextView | |
android:id="@+id/error" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="4dp" | |
android:layout_marginLeft="8dp" | |
android:layout_marginRight="8dp" | |
android:layout_marginTop="4dp" | |
android:gravity="center" | |
android:textColor="#FF0000" | |
/> | |
<include | |
layout="@layout/dialog_buttons" | |
/> | |
</LinearLayout> | |
<ProgressBar | |
android:id="@+id/progress" | |
style="?android:attr/progressBarStyleLarge" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center" | |
android:indeterminateOnly="true" | |
/> | |
</FrameLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
import android.app.Dialog; | |
import android.content.DialogInterface; | |
import android.os.AsyncTask; | |
import android.os.Bundle; | |
import android.support.v4.app.DialogFragment; | |
import android.support.v4.app.Fragment; | |
import android.support.v4.app.FragmentActivity; | |
import android.support.v4.app.FragmentManager; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.TextView; | |
public class MainActivity extends FragmentActivity | |
{ | |
@Override | |
protected void onCreate(Bundle savedInstanceState) | |
{ | |
super.onCreate(savedInstanceState); | |
if(savedInstanceState == null){ | |
new LoginDialogFrag() | |
.show(getSupportFragmentManager(), "login_dialog"); | |
} | |
} | |
public static class LoginDialogFrag extends DialogFragment implements | |
HeadlessAsyncTask.Callback<LoginModel, LoginModel>, | |
View.OnClickListener | |
{ | |
private static final String STATE_MODEL = "stateModel"; | |
private HeadlessFragment mHeadless; | |
private View mPanel; | |
private EditText mUsername; | |
private EditText mPassword; | |
private TextView mError; | |
private View mProgress; | |
private LoginAsyncTask mTask; | |
private LoginModel mModel; | |
@Override | |
public void onCreate(Bundle savedInstanceState) | |
{ | |
super.onCreate(savedInstanceState); | |
if(savedInstanceState != null){ | |
mModel = (LoginModel)savedInstanceState.getSerializable(STATE_MODEL); | |
} | |
} | |
@Override | |
public void onSaveInstanceState(Bundle outState) | |
{ | |
super.onSaveInstanceState(outState); | |
outState.putSerializable(STATE_MODEL, mModel); | |
} | |
@Override | |
public void onActivityCreated(Bundle savedInstanceState) | |
{ | |
super.onActivityCreated(savedInstanceState); | |
mHeadless = HeadlessFragment.get(getFragmentManager()); | |
mTask = (LoginAsyncTask)mHeadless.getBackgroundTask(); | |
if(mTask != null){ | |
mTask.setCallback(this); | |
} | |
updateViewState(); | |
} | |
@Override | |
public void onCancel(DialogInterface dialog) | |
{ | |
super.onCancel(dialog); | |
if(mTask != null){ | |
mTask.cancel(false); | |
} | |
} | |
@Override | |
public void onDetach() | |
{ | |
super.onDetach(); | |
if(mTask != null){ | |
mTask.setCallback(null); | |
} | |
} | |
@Override | |
public Dialog onCreateDialog(Bundle savedInstanceState) | |
{ | |
Dialog dialog = super.onCreateDialog(savedInstanceState); | |
dialog.setTitle("App Login"); | |
return dialog; | |
} | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) | |
{ | |
return inflater.inflate(R.layout.dialog_login, container, false); | |
} | |
@Override | |
public void onViewCreated(View view, Bundle savedInstanceState) | |
{ | |
super.onViewCreated(view, savedInstanceState); | |
mPanel = view.findViewById(R.id.panel); | |
mUsername = (EditText)view.findViewById(R.id.username); | |
mPassword = (EditText)view.findViewById(R.id.password); | |
mError = (TextView)view.findViewById(R.id.error); | |
mProgress = view.findViewById(R.id.progress); | |
setButton(DialogInterface.BUTTON_NEUTRAL, "Login", this); | |
} | |
private boolean setButton(int which, CharSequence text, View.OnClickListener listener) | |
{ | |
final int id; | |
switch(which){ | |
case DialogInterface.BUTTON_POSITIVE: id = android.R.id.button1; break; | |
case DialogInterface.BUTTON_NEUTRAL: id = android.R.id.button2; break; | |
case DialogInterface.BUTTON_NEGATIVE: id = android.R.id.button3; break; | |
default: throw new IllegalArgumentException("Bad button code"); | |
} | |
final Button button = (Button)getView().findViewById(id); | |
if(button != null){ | |
button.setText(text); | |
button.setOnClickListener(listener); | |
button.setVisibility(listener != null ? View.VISIBLE : View.GONE); | |
return true; | |
} | |
return false; | |
} | |
@Override | |
public void onClick(View v) | |
{ | |
mTask = new LoginAsyncTask(); | |
mHeadless.setBackgroundTask(mTask); | |
mTask.setCallback(this); | |
mModel = new LoginModel( | |
mUsername.getText().toString(), | |
mPassword.getText().toString()); | |
mTask.execute(mModel); | |
} | |
private void updateViewState() | |
{ | |
boolean waiting = (mModel != null) ? mModel.waiting : false; | |
mPanel.setVisibility(waiting ? View.INVISIBLE : View.VISIBLE); | |
mProgress.setVisibility(waiting ? View.VISIBLE : View.INVISIBLE); | |
mError.setText((mModel != null && mModel.error != null) ? | |
mModel.error.getMessage() : null); | |
} | |
@Override | |
public void onPreExecute() | |
{ | |
updateViewState(); | |
} | |
@Override | |
public void onProgressUpdate(LoginModel... values) | |
{ | |
// Do nothing | |
} | |
@Override | |
public void onPostExecute(LoginModel result) | |
{ | |
result.waiting = false; | |
mModel = result; | |
updateViewState(); | |
if(result.success){ | |
dismiss(); | |
} | |
} | |
@Override | |
public void onCancelled(LoginModel result) | |
{ | |
// do nothing | |
} | |
private static class LoginAsyncTask extends HeadlessAsyncTask<LoginModel, LoginModel, LoginModel> | |
{ | |
@Override | |
protected LoginModel doInBackground(LoginModel... params) | |
{ | |
LoginModel model = params[0]; | |
try{ | |
Thread.sleep(3000); | |
if(model.username.equals("admin") && model.password.equals("admin")){ | |
model.success = true; | |
} | |
else{ | |
throw new IllegalArgumentException("Bad username or password"); | |
} | |
} | |
catch(Exception e){ | |
model.success = false; | |
model.error = e; | |
} | |
return model; | |
} | |
} | |
} | |
private static class LoginModel implements Serializable | |
{ | |
private static final long serialVersionUID = 1L; | |
public String username; | |
public String password; | |
public Throwable error; | |
public boolean success; | |
public boolean waiting; | |
public LoginModel(String username, String password) | |
{ | |
this.username = username; | |
this.password = password; | |
this.waiting = true; | |
} | |
} | |
public static class HeadlessFragment extends Fragment | |
{ | |
private HeadlessAsyncTask<?, ?, ?> mBackgroundTask; | |
public static HeadlessFragment get(FragmentManager fm) | |
{ | |
HeadlessFragment headless = (HeadlessFragment)fm.findFragmentByTag("headless"); | |
if(headless == null){ | |
headless = new HeadlessFragment(); | |
fm.beginTransaction() | |
.add(headless, "headless") | |
.commit(); | |
} | |
return headless; | |
} | |
@Override | |
public void onCreate(Bundle savedInstanceState) | |
{ | |
super.onCreate(savedInstanceState); | |
setRetainInstance(true); | |
} | |
public void setBackgroundTask(HeadlessAsyncTask<?, ?, ?> backgroundTask) | |
{ | |
mBackgroundTask = backgroundTask; | |
} | |
public HeadlessAsyncTask<?, ?, ?> getBackgroundTask() | |
{ | |
return mBackgroundTask; | |
} | |
} | |
public static abstract class HeadlessAsyncTask<Param, Progress, Result> extends AsyncTask<Param, Progress, Result> | |
{ | |
private Callback<Progress, Result> mCallback; | |
public void setCallback(Callback<Progress, Result> callback) | |
{ | |
mCallback = callback; | |
} | |
@Override | |
protected void onPreExecute() | |
{ | |
if(mCallback != null){ | |
mCallback.onPreExecute(); | |
} | |
} | |
@Override | |
protected void onProgressUpdate(Progress... values) | |
{ | |
if(mCallback != null){ | |
mCallback.onProgressUpdate(values); | |
} | |
} | |
@Override | |
protected void onPostExecute(Result result) | |
{ | |
if(mCallback != null){ | |
mCallback.onPostExecute(result); | |
} | |
} | |
@Override | |
protected void onCancelled(Result result) | |
{ | |
if(mCallback != null){ | |
mCallback.onCancelled(result); | |
} | |
} | |
public static interface Callback<Progress, Result> | |
{ | |
public void onPreExecute (); | |
public void onProgressUpdate(Progress... values); | |
public void onPostExecute (Result result); | |
public void onCancelled (Result result); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment