/*
* Copyright 2013 Inmite s.r.o. (www.inmite.eu).
*
* 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.
*/
package eu.inmite.android.lib.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
// TODO: Auto-generated Javadoc
/**
* Base dialog fragment for all your dialogs, stylable and same design on Android 2.2+.
*
* @author David Vávra (david@inmite.eu)
*/
public abstract class BaseDialogFragment extends DialogFragment {
/* (non-Javadoc)
* @see android.support.v4.app.DialogFragment#onCreateDialog(android.os.Bundle)
*/
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity(), R.style.SDL_Dialog);
// custom dialog background
final TypedArray a = getActivity().getTheme().obtainStyledAttributes(null, R.styleable.DialogStyle, R.attr.sdlDialogStyle, 0);
Drawable dialogBackground = a.getDrawable(R.styleable.DialogStyle_dialogBackground);
a.recycle();
dialog.getWindow().setBackgroundDrawable(dialogBackground);
Bundle args = getArguments();
if (args != null) {
dialog.setCanceledOnTouchOutside(args.getBoolean(BaseDialogBuilder.ARG_CANCELABLE_ON_TOUCH_OUTSIDE));
}
return dialog;
}
/* (non-Javadoc)
* @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Builder builder = new Builder(this, getActivity(), inflater, container);
return build(builder).create();
}
/**
* Builds the.
*
* @param initialBuilder the initial builder
* @return the builder
*/
protected abstract Builder build(Builder initialBuilder);
/* (non-Javadoc)
* @see android.support.v4.app.DialogFragment#onDestroyView()
*/
@Override
public void onDestroyView() {
// bug in the compatibility library
if (getDialog() != null && getRetainInstance()) {
getDialog().setDismissMessage(null);
}
super.onDestroyView();
}
/**
* Gets the positive button.
*
* @return the positive button if specified and the view is created, null otherwise
*/
protected Button getPositiveButton() {
if (getView() != null) {
return (Button) getView().findViewById(R.id.sdl__positive_button);
} else {
return null;
}
}
/**
* Gets the negative button.
*
* @return the negative button if specified and the view is created, null otherwise
*/
protected Button getNegativeButton() {
if (getView() != null) {
return (Button) getView().findViewById(R.id.sdl__negative_button);
} else {
return null;
}
}
/**
* Gets the neutral button.
*
* @return the neutral button if specified and the view is created, null otherwise
*/
protected Button getNeutralButton() {
if (getView() != null) {
return (Button) getView().findViewById(R.id.sdl__neutral_button);
} else {
return null;
}
}
/**
* Custom dialog builder.
*/
protected static class Builder {
/** The m dialog fragment. */
private final DialogFragment mDialogFragment;
/** The m context. */
private final Context mContext;
/** The m container. */
private final ViewGroup mContainer;
/** The m inflater. */
private final LayoutInflater mInflater;
/** The m title. */
private CharSequence mTitle = null;
/** The icon. */
private int icon = 0;
/** The m positive button text. */
private CharSequence mPositiveButtonText;
/** The m positive button listener. */
private View.OnClickListener mPositiveButtonListener;
/** The m negative button text. */
private CharSequence mNegativeButtonText;
/** The m negative button listener. */
private View.OnClickListener mNegativeButtonListener;
/** The m neutral button text. */
private CharSequence mNeutralButtonText;
/** The m neutral button listener. */
private View.OnClickListener mNeutralButtonListener;
/** The m message. */
private CharSequence mMessage;
/** The m view. */
private View mView;
/** The m view spacing specified. */
private boolean mViewSpacingSpecified;
/** The m view spacing left. */
private int mViewSpacingLeft;
/** The m view spacing top. */
private int mViewSpacingTop;
/** The m view spacing right. */
private int mViewSpacingRight;
/** The m view spacing bottom. */
private int mViewSpacingBottom;
/** The m list adapter. */
private ListAdapter mListAdapter;
/** The m list checked item idx. */
private int mListCheckedItemIdx;
/** The m on item click listener. */
private AdapterView.OnItemClickListener mOnItemClickListener;
/** Styling: *. */
private int mTitleTextColor;
/** The m title separator color. */
private int mTitleSeparatorColor;
/** The m message text color. */
private int mMessageTextColor;
/** The m button text color. */
private ColorStateList mButtonTextColor;
/** The m button separator color. */
private int mButtonSeparatorColor;
/** The m button background color normal. */
private int mButtonBackgroundColorNormal;
/** The m button background color pressed. */
private int mButtonBackgroundColorPressed;
/** The m button background color focused. */
private int mButtonBackgroundColorFocused;
/**
* Instantiates a new builder.
*
* @param dialogFragment the dialog fragment
* @param context the context
* @param inflater the inflater
* @param container the container
*/
public Builder(DialogFragment dialogFragment, Context context, LayoutInflater inflater, ViewGroup container) {
this.mDialogFragment = dialogFragment;
this.mContext = context;
this.mContainer = container;
this.mInflater = inflater;
}
/**
* Gets the layout inflater.
*
* @return the layout inflater
*/
public LayoutInflater getLayoutInflater() {
return mInflater;
}
/**
* Sets the title.
*
* @param titleId the title id
* @return the builder
*/
public Builder setTitle(int titleId) {
this.mTitle = mContext.getText(titleId);
return this;
}
/**
* Sets the title.
*
* @param titleId the title id
* @param icon the icon
* @return the builder
*/
public Builder setTitle(int titleId,int icon) {
this.mTitle = mContext.getText(titleId);
this.icon=icon;
return this;
}
/**
* Sets the title.
*
* @param title the title
* @return the builder
*/
public Builder setTitle(CharSequence title) {
this.mTitle = title;
return this;
}
/**
* Sets the title.
*
* @param title the title
* @param icon the icon
* @return the builder
*/
public Builder setTitle(CharSequence title,int icon) {
this.mTitle = title;
this.icon=icon;
return this;
}
/**
* Sets the positive button.
*
* @param textId the text id
* @param listener the listener
* @return the builder
*/
public Builder setPositiveButton(int textId, final View.OnClickListener listener) {
mPositiveButtonText = mContext.getText(textId);
mPositiveButtonListener = listener;
return this;
}
/**
* Sets the positive button.
*
* @param text the text
* @param listener the listener
* @return the builder
*/
public Builder setPositiveButton(CharSequence text, final View.OnClickListener listener) {
mPositiveButtonText = text;
mPositiveButtonListener = listener;
return this;
}
/**
* Sets the negative button.
*
* @param textId the text id
* @param listener the listener
* @return the builder
*/
public Builder setNegativeButton(int textId, final View.OnClickListener listener) {
mNegativeButtonText = mContext.getText(textId);
mNegativeButtonListener = listener;
return this;
}
/**
* Sets the negative button.
*
* @param text the text
* @param listener the listener
* @return the builder
*/
public Builder setNegativeButton(CharSequence text, final View.OnClickListener listener) {
mNegativeButtonText = text;
mNegativeButtonListener = listener;
return this;
}
/**
* Sets the neutral button.
*
* @param textId the text id
* @param listener the listener
* @return the builder
*/
public Builder setNeutralButton(int textId, final View.OnClickListener listener) {
mNeutralButtonText = mContext.getText(textId);
mNeutralButtonListener = listener;
return this;
}
/**
* Sets the neutral button.
*
* @param text the text
* @param listener the listener
* @return the builder
*/
public Builder setNeutralButton(CharSequence text, final View.OnClickListener listener) {
mNeutralButtonText = text;
mNeutralButtonListener = listener;
return this;
}
/**
* Sets the message.
*
* @param messageId the message id
* @return the builder
*/
public Builder setMessage(int messageId) {
mMessage = mContext.getText(messageId);
return this;
}
/**
* Sets the message.
*
* @param message the message
* @return the builder
*/
public Builder setMessage(CharSequence message) {
mMessage = message;
return this;
}
/**
* Set list.
*
* @param listAdapter the list adapter
* @param checkedItemIdx Item check by default, -1 if no item should be checked
* @param listener the listener
* @return the builder
*/
public Builder setItems(ListAdapter listAdapter, int checkedItemIdx, final AdapterView.OnItemClickListener listener) {
mListAdapter = listAdapter;
mOnItemClickListener = listener;
mListCheckedItemIdx = checkedItemIdx;
return this;
}
/**
* Sets the view.
*
* @param view the view
* @return the builder
*/
public Builder setView(View view) {
mView = view;
mViewSpacingSpecified = false;
return this;
}
/**
* Sets the view.
*
* @param view the view
* @param viewSpacingLeft the view spacing left
* @param viewSpacingTop the view spacing top
* @param viewSpacingRight the view spacing right
* @param viewSpacingBottom the view spacing bottom
* @return the builder
*/
public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop,
int viewSpacingRight, int viewSpacingBottom) {
mView = view;
mViewSpacingSpecified = true;
mViewSpacingLeft = viewSpacingLeft;
mViewSpacingTop = viewSpacingTop;
mViewSpacingRight = viewSpacingRight;
mViewSpacingBottom = viewSpacingBottom;
return this;
}
/**
* Creates the.
*
* @return the view
*/
public View create() {
final Resources res = mContext.getResources();
final int defaultTitleTextColor = res.getColor(R.color.sdl_title_text_dark);
final int defaultTitleSeparatorColor = res.getColor(R.color.sdl_title_separator_dark);
final int defaultMessageTextColor = res.getColor(R.color.sdl_message_text_dark);
final ColorStateList defaultButtonTextColor = res.getColorStateList(R.color.sdl_button_text_dark);
final int defaultButtonSeparatorColor = res.getColor(R.color.sdl_button_separator_dark);
final int defaultButtonBackgroundColorNormal = res.getColor(R.color.sdl_button_normal_dark);
final int defaultButtonBackgroundColorPressed = res.getColor(R.color.sdl_button_pressed_dark);
final int defaultButtonBackgroundColorFocused = res.getColor(R.color.sdl_button_focused_dark);
final TypedArray a = mContext.getTheme().obtainStyledAttributes(null, R.styleable.DialogStyle, R.attr.sdlDialogStyle, 0);
mTitleTextColor = a.getColor(R.styleable.DialogStyle_titleTextColor, defaultTitleTextColor);
mTitleSeparatorColor = a.getColor(R.styleable.DialogStyle_titleSeparatorColor, defaultTitleSeparatorColor);
mMessageTextColor = a.getColor(R.styleable.DialogStyle_messageTextColor, defaultMessageTextColor);
mButtonTextColor = a.getColorStateList(R.styleable.DialogStyle_buttonTextColor);
if (mButtonTextColor == null) {
mButtonTextColor = defaultButtonTextColor;
}
mButtonSeparatorColor = a.getColor(R.styleable.DialogStyle_buttonSeparatorColor, defaultButtonSeparatorColor);
mButtonBackgroundColorNormal = a.getColor(R.styleable.DialogStyle_buttonBackgroundColorNormal, defaultButtonBackgroundColorNormal);
mButtonBackgroundColorPressed = a.getColor(R.styleable.DialogStyle_buttonBackgroundColorPressed, defaultButtonBackgroundColorPressed);
mButtonBackgroundColorFocused = a.getColor(R.styleable.DialogStyle_buttonBackgroundColorFocused, defaultButtonBackgroundColorFocused);
a.recycle();
View v = getDialogLayoutAndInitTitle();
LinearLayout content = (LinearLayout) v.findViewById(R.id.sdl__content);
if (mMessage != null) {
View viewMessage = mInflater.inflate(R.layout.dialog_part_message, content, false);
TextView tvMessage = (TextView) viewMessage.findViewById(R.id.sdl__message);
tvMessage.setTextColor(mMessageTextColor);
tvMessage.setText(mMessage);
content.addView(viewMessage);
}
if (mView != null) {
FrameLayout customPanel = (FrameLayout) mInflater.inflate(R.layout.dialog_part_custom, content, false);
FrameLayout custom = (FrameLayout) customPanel.findViewById(R.id.sdl__custom);
custom.addView(mView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if (mViewSpacingSpecified) {
custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom);
}
content.addView(customPanel);
}
if (mListAdapter != null) {
ListView list = (ListView) mInflater.inflate(R.layout.dialog_part_list, content, false);
list.setAdapter(mListAdapter);
list.setOnItemClickListener(mOnItemClickListener);
if (mListCheckedItemIdx != -1) {
list.setSelection(mListCheckedItemIdx);
}
content.addView(list);
}
addButtons(content);
return v;
}
/**
* Gets the dialog layout and init title.
*
* @return the dialog layout and init title
*/
private View getDialogLayoutAndInitTitle() {
View v = mInflater.inflate(R.layout.dialog_part_title, mContainer, false);
TextView tvTitle = (TextView) v.findViewById(R.id.sdl__title);
View viewTitleDivider = v.findViewById(R.id.sdl__titleDivider);
if (mTitle != null) {
tvTitle.setText(mTitle);
tvTitle.setTextColor(mTitleTextColor);
if(icon!=0)
{
tvTitle.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
tvTitle.setCompoundDrawablePadding(10);
tvTitle.setGravity(Gravity.CENTER_VERTICAL);
}
viewTitleDivider.setBackgroundDrawable(new ColorDrawable(mTitleSeparatorColor));
} else {
tvTitle.setVisibility(View.GONE);
viewTitleDivider.setVisibility(View.GONE);
}
return v;
}
/**
* Adds the buttons.
*
* @param llListDialog the ll list dialog
*/
private void addButtons(LinearLayout llListDialog) {
if (mNegativeButtonText != null || mNeutralButtonText != null || mPositiveButtonText != null) {
View viewButtonPanel = mInflater.inflate(R.layout.dialog_part_button_panel, llListDialog, false);
LinearLayout llButtonPanel = (LinearLayout) viewButtonPanel.findViewById(R.id.dialog_button_panel);
viewButtonPanel.findViewById(R.id.dialog_horizontal_separator).setBackgroundDrawable(new ColorDrawable(mButtonSeparatorColor));
boolean addDivider = false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
addDivider = addPositiveButton(llButtonPanel, addDivider);
} else {
addDivider = addNegativeButton(llButtonPanel, addDivider);
}
addDivider = addNeutralButton(llButtonPanel, addDivider);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
addNegativeButton(llButtonPanel, addDivider);
} else {
addPositiveButton(llButtonPanel, addDivider);
}
llListDialog.addView(viewButtonPanel);
}
}
/**
* Adds the negative button.
*
* @param parent the parent
* @param addDivider the add divider
* @return true, if successful
*/
private boolean addNegativeButton(ViewGroup parent, boolean addDivider) {
if (mNegativeButtonText != null) {
if (addDivider) {
addDivider(parent);
}
Button btn = (Button) mInflater.inflate(R.layout.dialog_part_button, parent, false);
btn.setId(R.id.sdl__negative_button);
btn.setText(mNegativeButtonText);
btn.setTextColor(mButtonTextColor);
btn.setBackgroundDrawable(getButtonBackground());
btn.setOnClickListener(mNegativeButtonListener);
parent.addView(btn);
return true;
}
return addDivider;
}
/**
* Adds the positive button.
*
* @param parent the parent
* @param addDivider the add divider
* @return true, if successful
*/
private boolean addPositiveButton(ViewGroup parent, boolean addDivider) {
if (mPositiveButtonText != null) {
if (addDivider) {
addDivider(parent);
}
Button btn = (Button) mInflater.inflate(R.layout.dialog_part_button, parent, false);
btn.setId(R.id.sdl__positive_button);
btn.setText(mPositiveButtonText);
btn.setTextColor(mButtonTextColor);
btn.setBackgroundDrawable(getButtonBackground());
btn.setOnClickListener(mPositiveButtonListener);
parent.addView(btn);
return true;
}
return addDivider;
}
/**
* Adds the neutral button.
*
* @param parent the parent
* @param addDivider the add divider
* @return true, if successful
*/
private boolean addNeutralButton(ViewGroup parent, boolean addDivider) {
if (mNeutralButtonText != null) {
if (addDivider) {
addDivider(parent);
}
Button btn = (Button) mInflater.inflate(R.layout.dialog_part_button, parent, false);
btn.setId(R.id.sdl__neutral_button);
btn.setText(mNeutralButtonText);
btn.setTextColor(mButtonTextColor);
btn.setBackgroundDrawable(getButtonBackground());
btn.setOnClickListener(mNeutralButtonListener);
parent.addView(btn);
return true;
}
return addDivider;
}
/**
* Adds the divider.
*
* @param parent the parent
*/
private void addDivider(ViewGroup parent) {
View view = mInflater.inflate(R.layout.dialog_part_button_separator, parent, false);
view.findViewById(R.id.dialog_button_separator).setBackgroundDrawable(new ColorDrawable(mButtonSeparatorColor));
parent.addView(view);
}
/**
* Gets the button background.
*
* @return the button background
*/
private StateListDrawable getButtonBackground() {
int[] pressedState = {android.R.attr.state_pressed};
int[] focusedState = {android.R.attr.state_focused};
int[] defaultState = {android.R.attr.state_enabled};
ColorDrawable colorDefault = new ColorDrawable(mButtonBackgroundColorNormal);
ColorDrawable colorPressed = new ColorDrawable(mButtonBackgroundColorPressed);
ColorDrawable colorFocused = new ColorDrawable(mButtonBackgroundColorFocused);
StateListDrawable background = new StateListDrawable();
background.addState(pressedState, colorPressed);
background.addState(focusedState, colorFocused);
background.addState(defaultState, colorDefault);
return background;
}
}
}