Skip to content

Instantly share code, notes, and snippets.

@slightfoot
Created April 28, 2014 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slightfoot/11375255 to your computer and use it in GitHub Desktop.
Save slightfoot/11375255 to your computer and use it in GitHub Desktop.
Example of a Login DialogFragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/buttonPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="?android:attr/dividerHorizontal"
android:dividerPadding="0dip"
android:minHeight="48dp"
android:orientation="vertical"
android:showDividers="beginning"
>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
android:orientation="horizontal"
tools:ignore="UselessParent"
>
<Button
android:id="@android:id/button2"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_weight="1"
android:maxLines="2"
android:minHeight="48dp"
android:textSize="14sp"
android:focusable="true"
android:visibility="gone"
/>
<Button
android:id="@android:id/button3"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:maxLines="2"
android:minHeight="48dp"
android:textSize="14sp"
android:focusable="true"
android:visibility="gone"
/>
<Button
android:id="@android:id/button1"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_weight="1"
android:maxLines="2"
android:minHeight="48dp"
android:textSize="14sp"
android:focusable="true"
android:visibility="gone"
/>
</LinearLayout>
</LinearLayout>
<?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>
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