com.wit.and.dialog.ListDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.wit.and.dialog.ListDialog.java

Source

/*
 * =================================================================================
 * Copyright (C) 2013 Martin Albedinsky [Wolf-ITechnologies]
 * =================================================================================
 * Licensed under the Apache License, Version 2.0 or later (further "License" only);
 * ---------------------------------------------------------------------------------
 * You may use this file only in compliance with the License. More details and copy
 * of this License you may obtain at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You can redistribute, modify or publish any part of the code written in this
 * file but as it is described in the License, the software distributed under the 
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF
 * ANY KIND.
 * 
 * See the License for the specific language governing permissions and limitations
 * under the License.
 * =================================================================================
 */
package com.wit.and.dialog;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcel;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.wit.and.dialog.manage.DialogOptions;
import com.wit.and.style.styler.WidgetStyler;

/**
 * <h4>Class Overview</h4>
 * <p>
 * Dialog contains {@link ListView} in it's body view.
 * </p>
 * <p>
 * Can be used to show some listed items in the dialog (like options list or
 * online contacts in some messenger app).
 * </p>
 * <h3>Dialog styling:</h3>
 * <p>
 * This dialog implementation parses its style from main <b>dialogTheme</b>
 * where <b>listDialogStyle</b> is obtained to apply styles to specific
 * view elements for list dialog.
 * </p>
 *
 * @author Martin Albedinsky
 * @see Dialog
 */
public class ListDialog extends Dialog
        implements IListDialog, OnItemClickListener, OnItemLongClickListener, OnItemSelectedListener {

    /**
     * Constants =============================
     */

    /**
     * <p>
     * </p>
     */
    public static final int DEFAULT_RES = -0x01;

    /**
     * Indicates if logging for user output trough log-cat is enabled.
     */
    // private static final boolean USER_LOG = true;

    /**
     * Bundle identifiers.
     */

    /**
     */
    protected static final String BUNDLE_ADAPTER_ID = "com.wit.and.dialog.ListDialog.Bundle.Adapter.ID";

    protected static final String BUNDLE_LIST_VIEW_RES = "com.wit.and.dialog.ListDialog.Bundle.ListView.Res";

    protected static final String BUNDLE_EMPTY_VIEW_RES = "com.wit.and.dialog.ListDialog.Bundle.EmptyView.Res";

    /**
     * Log TAG.
     */
    private static final String TAG = ListDialog.class.getSimpleName();

    /**
     * Indicates if debug private output trough log-cat is enabled.
     */
    private static final boolean DEBUG = false;

    /**
     * Enums =================================
     */

    /**
     * Static members ========================
     */

    /**
     * Members ===============================
     */

    /**
     * Widget stylers.
     */

    /**
     */
    private final WidgetStyler.ListViewStyler LIST_STYLER = new WidgetStyler.ListViewStyler(0);

    private final WidgetStyler.TextViewStyler TEXT_STYLER = new WidgetStyler.TextViewStyler(0);

    /**
     * Base adapter to fill list view with items.
     */
    private BaseAdapter mAdapter;

    /**
     * List view for items.
     */
    private ListView mListView;

    /**
     * Text view to show text when the list view is empty.
     */
    private TextView mEmptyTextView;

    /**
     * Listeners -----------------------------
     */

    private OnListListener iListener = null;

    private OnListListener iParentListener = null;

    /**
     * Arrays --------------------------------
     */

    /**
     * Booleans ------------------------------
     */

    /**
     * Constructors ==========================
     */

    /**
     * Methods ===============================
     */

    /**
     * Public --------------------------------
     */

    /**
     * <p>
     * Creates new instance of list dialog fragment.
     * </p>
     *
     * @return New instance of list dialog fragment.
     */
    public static ListDialog newInstance() {
        // Return new instance of this dialog.
        return new ListDialog();
    }

    /**
     * <p>
     * Creates new instance of list dialog fragment.
     * </p>
     *
     * @param listOptions Specific dialog options for list dialog.
     * @return New instance of list dialog fragment.
     */
    public static ListDialog newInstance(ListOptions listOptions) {
        final ListDialog dialog = new ListDialog();
        dialog.setCancelable(listOptions.isCancelable());
        // Set up dialog arguments.
        dialog.setArguments(createArguments(listOptions));
        return dialog;
    }

    /**
     */
    @Override
    public void onActivityCreated(Bundle bundle) {
        super.onActivityCreated(bundle);

        Activity activity = this.getActivity();
        Fragment fragment = this.getFragmentManager().findFragmentByTag(this.getParentFragmentTag());

        // Check if some of the parents implements our listener.
        if (fragment != null && fragment instanceof OnListListener) {
            this.iParentListener = (OnListListener) fragment;
        } else if (activity != null && activity instanceof OnListListener) {
            this.iParentListener = (OnListListener) activity;
        }

        if (mAdapter == null) {
            // Obtain adapter.
            this.setAdapter(this.getParentAdapter(getOptions().getAdapterID()));
        }
    }

    /**
     */
    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
        if (DEBUG)
            Log.d(TAG, "onItemSelected(" + position + ")");

        if (this.iListener != null) {
            this.iListener.onListDialogItemSelected(this, adapterView, view, position, id);
        }
        if (this.iParentListener != null) {
            this.iParentListener.onListDialogItemSelected(this, adapterView, view, position, id);
        }
    }

    /**
     */
    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
        if (DEBUG)
            Log.d(TAG, "onNothingSelected()");

        if (this.iListener != null) {
            this.iListener.onListDialogNothingSelected(this, adapterView);
        }
        if (this.iParentListener != null) {
            this.iParentListener.onListDialogNothingSelected(this, adapterView);
        }
    }

    /**
     */
    @Override
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
        if (DEBUG)
            Log.d(TAG, "onItemLongClick(" + position + ")");

        boolean success = false;

        if (this.iListener != null) {
            success = this.iListener.onListDialogItemLongClick(this, adapterView, view, position, id);
        }
        if (this.iParentListener != null) {
            success = this.iParentListener.onListDialogItemLongClick(this, adapterView, view, position, id);
        }

        return success;
    }

    /**
     */
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        if (DEBUG)
            Log.d(TAG, "onItemClick(" + position + ")");

        if (iListener != null) {
            iListener.onListDialogItemClick(this, adapterView, view, position, id);
        }
        if (iParentListener != null) {
            iParentListener.onListDialogItemClick(this, adapterView, view, position, id);
        }
    }

    /**
     * Getters + Setters ---------------------
     */

    /**
     */
    @Override
    public ListOptions getOptions() {
        return (ListOptions) super.getOptions();
    }

    /**
      * <p>
      * Sets adapter for the list view of this list dialog.
      * </p>
      *
      * @param adapter List view adapter.
      */
    public void setAdapter(BaseAdapter adapter) {
        this.mAdapter = adapter;

        // Refresh list view.
        if (mListView != null) {
            mListView.setAdapter(adapter);
        }
    }

    /**
     * <p>
     * Returns current dialog list view adapter.
     * </p>
     */
    @Override
    public BaseAdapter getAdapter() {
        return mAdapter;
    }

    /**
     * <p>
     * Sets listener for this list dialog to listen for basic callback from the
     * list view.
     * </p>
     *
     * @param listener ListDialog listener.
     * @see com.wit.and.dialog.IListDialog.OnListListener
     */
    public void setOnListDialogListener(OnListListener listener) {
        this.iListener = listener;
    }

    /**
     * <p>
     * Returns dialog list view or <code>null</code> if there is no list view currently inflated.
     * </p>
     */
    @Override
    public ListView getListView() {
        return mListView;
    }

    /**
     * Protected -----------------------------
     */

    /**
     */
    @Override
    protected View onCreateBodyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final Context context = inflater.getContext();

        // There will be default empty view behind the list view in relative layout.
        RelativeLayout layout = new RelativeLayout(context);
        if (container instanceof LinearLayout) {
            // Apply valid linear layout params to fit with list view just left space in the dialog main view.
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT, 0);
            layoutParams.weight = 1;
            layout.setLayoutParams(layoutParams);
        } else {
            // Apply neutral layout params.
            layout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
        }
        layout.setGravity(Gravity.CENTER);
        // Do not allow to apply style to body view.
        // layout.setId(R.id.Dialog_Layout_Body);

        // Create empty view and insert it into body layout behind the list view.
        View emptyView = onCreateEmptyView(inflater, container, savedInstanceState);
        if (emptyView != null) {
            layout.addView(emptyView);
        }

        // Create list view and insert it into body layout.
        ListView listView = onCreateListView(inflater, layout, savedInstanceState);
        if (listView != null) {
            layout.addView(listView);
        }
        return layout;
    }

    /**
     * <p>
     * Invoked to create dialog list view.
     * </p>
     * <p>
     * Here is the best place to provide custom list view.
     * </p>
     *
     * @param inflater           Layout inflater.
     * @param container          Layout created in the {@link #onCreateBodyView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)}
     * @param savedInstanceState Saved dialog state.
     * @return Created dialog list view.
     */
    protected ListView onCreateListView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ListView listView;

        final ListOptions options = getOptions();
        if (options.getListViewRes() != DEFAULT_RES) {
            // Inflate custom list view.
            listView = (ListView) inflater.inflate(options.getListViewRes(), null, false);
        } else {
            // Create default list view.
            listView = new ListView(inflater.getContext(), null, android.R.attr.listViewStyle);
            listView.setId(R.id.And_Dialog_ListView);
            RelativeLayout.LayoutParams listViewParams = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            listViewParams.addRule(RelativeLayout.CENTER_IN_PARENT);
            listView.setLayoutParams(listViewParams);
        }
        return listView;
    }

    /**
     * <p>
     * Invoked to create dialog empty view for list view.
     * </p>
     * <p>
     * Here is the best place to provide custom empty view.
     * </p>
     *
     * @param inflater           Layout inflater.
     * @param container          Layout created in the {@link #onCreateBodyView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)}
     * @param savedInstanceState Saved dialog state.
     * @return Created empty view.
     */
    protected View onCreateEmptyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View emptyView;

        final ListOptions options = getOptions();
        if (options.getEmptyViewRes() != DEFAULT_RES) {
            // Inflate custom empty view.
            emptyView = inflater.inflate(options.getEmptyViewRes(), null, false);
        } else {
            // Create default empty text view.
            TextView textView = new TextView(inflater.getContext());
            textView.setId(android.R.id.empty);
            textView.setGravity(Gravity.CENTER);
            textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            textView.setVisibility(View.GONE);
            emptyView = textView;
        }

        return emptyView;
    }

    /**
     */
    @Override
    protected void onInitViews(View dialogView) {
        super.onInitViews(dialogView);

        // Initialize list view.
        this.mListView = (ListView) findViewByID(R.id.And_Dialog_ListView);
        mListView.setEmptyView(mEmptyTextView);

        // Check for default empty text view.
        View empty = findViewByID(android.R.id.empty);
        if (empty != null && empty instanceof TextView) {
            this.mEmptyTextView = (TextView) empty;
        }

        // Set adapter.
        if (mListView != null && mAdapter != null) {
            mListView.setAdapter(mAdapter);
        }

        // Set up list view.
        if (mListView != null) {
            mListView.setOnItemClickListener(this);
            mListView.setOnItemLongClickListener(this);
            mListView.setOnItemSelectedListener(this);
            mListView.setEmptyView(empty);
        }
    }

    /**
     */
    @Override
    protected void onBindDialog(View dialogView, Bundle bundle) {
        super.onBindDialog(dialogView, bundle);

        if (mEmptyTextView != null) {
            mEmptyTextView.setText(this.getOptions().getMessage());
        }
    }

    /**
     */
    @Override
    protected void onStyleDialog(View dialogView, TypedArray parsedArray) {
        final Context context = getActivity();

        final int listDialogStyle = parsedArray.getResourceId(R.styleable.And_Theme_Dialog_listDialogStyle,
                R.style.And_Dialog_ListDialog);
        final TypedArray dialogArray = context.obtainStyledAttributes(listDialogStyle,
                R.styleable.And_Theme_Dialog_ListDialog);
        if (dialogArray != null) {
            final int n = dialogArray.getIndexCount();
            for (int i = 0; i < n; i++) {
                int attr = dialogArray.getIndex(i);
                /**
                 * Obtain list dialog sub-dialog style.
                 */
                if (attr == R.styleable.And_Theme_Dialog_ListDialog_dialogStyle) {
                    final int dialogStyle = dialogArray.getResourceId(attr, R.style.And_Dialog_Dialog);
                    /**
                     * Let super to process list dialog sub-dialog style.
                     */
                    super.onStyleDialog(dialogView, dialogStyle);

                    // Set up empty text view style.
                    if (mEmptyTextView != null) {
                        final TypedArray bodyArray = context.obtainStyledAttributes(dialogStyle,
                                new int[] { R.attr.dialogBodyStyle });
                        if (bodyArray != null) {
                            final int bodyStyle = bodyArray.getResourceId(0, R.style.And_Dialog_Body);

                            // Apply body style to get some padding.
                            TEXT_STYLER.performStyling(bodyStyle, mEmptyTextView);

                            final TypedArray textArray = context.obtainStyledAttributes(bodyStyle,
                                    new int[] { android.R.attr.textViewStyle });
                            if (textArray != null) {
                                // Apply message text style.
                                TEXT_STYLER.performStyling(textArray.getResourceId(0, R.style.And_Dialog_TextView),
                                        mEmptyTextView);
                                textArray.recycle();
                            }
                            bodyArray.recycle();
                        }
                    }
                }
                /**
                 * Set up list dialog list view style.
                 */
                else if (attr == R.styleable.And_Theme_Dialog_ListDialog_android_listViewStyle) {
                    if (mListView != null) {
                        LIST_STYLER.performStyling(dialogArray.getResourceId(attr, R.style.And_Dialog_ListView),
                                mListView);
                    }
                }
            }
            dialogArray.recycle();
        }
    }

    /**
     * Private -------------------------------
     */

    /**
     * Checks if the parent activity/fragment implements adapter provider. If
     * yes returns the provided adapter.
     *
     * @param adapterID Id of adapter to obtain.
     * @return Adapter for list view or <code>null</code> if parent isnt' adapter provider.
     */
    private BaseAdapter getParentAdapter(int adapterID) {
        BaseAdapter adapter = null;
        Activity activity = this.getActivity();
        Fragment fragment = this.getFragmentManager().findFragmentByTag(this.getParentFragmentTag());

        if (fragment != null && fragment instanceof ListDialogAdapterProvider) {
            adapter = ((ListDialogAdapterProvider) fragment).onGetListDialogAdapter(getDialogID(), adapterID);
        } else if (activity != null && activity instanceof ListDialogAdapterProvider) {
            adapter = ((ListDialogAdapterProvider) activity).onGetListDialogAdapter(getDialogID(), adapterID);
        }

        return adapter;
    }

    /**
     * Abstract methods ----------------------
     */

    /**
     * Inner classes =========================
     */

    /**
     * <h4>Class Overview</h4>
     * <p>
     * Specific dialog options for {@link ListDialog}.
     * </p>
     *
     * @author Martin Albedinsky
     * @see ListDialog
     * @see com.wit.and.dialog.manage.DialogOptions
     */
    public static class ListOptions extends DialogOptions<ListOptions> {
        /**
         * Members ===============================
         */

        /**
         * Id of the adapter to pass to the list dialog.
         */
        int adapterID = -1;

        /**
         * Resource for list view layout.
         */
        int listViewRes = ListDialog.DEFAULT_RES;

        /**
         * Resource for empty view layout.
         */
        int emptyViewRes = ListDialog.DEFAULT_RES;

        /**
         * Constructors ==========================
         */

        /**
         * <p>
         * Same as {@link com.wit.and.dialog.manage.DialogOptions#DialogOptions()}.
         * </p>
         */
        public ListOptions() {
            super();
        }

        /**
         * <p>
         * Same as {@link com.wit.and.dialog.manage.DialogOptions#DialogOptions(android.content.res.Resources)}.
         * </p>
         *
         * @param resources
         */
        public ListOptions(Resources resources) {
            super(resources);
        }

        /**
         * <p>
         * Same as {@link com.wit.and.dialog.manage.DialogOptions#DialogOptions(android.os.Parcel)}.
         * </p>
         *
         * @param input
         */
        protected ListOptions(Parcel input) {
            super(input);
            this.adapterID = input.readInt();
            this.listViewRes = input.readInt();
            this.emptyViewRes = input.readInt();
        }

        /**
         * Methods ===============================
         */

        /**
         * Public --------------------------------
         */

        /**
         */
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(adapterID);
            dest.writeInt(listViewRes);
            dest.writeInt(emptyViewRes);
        }

        /**
         * Getters + Setters ---------------------
         */

        /**
         * <p>
         * Sets the id of adapter for list dialog.
         * </p>
         *
         * @param id Id of adapter.
         * @return This options.
         */
        public ListOptions adapterID(int id) {
            this.adapterID = id;
            return this;
        }

        public int getAdapterID() {
            return adapterID;
        }

        /**
         * <p>
         * Sets resource for layout which will represent
         * empty view for list dialog's list view.
         * </p>
         *
         * @param emptyLayoutRes Layout resource.
         * @return This options.
         */
        public ListOptions emptyView(int emptyLayoutRes) {
            this.emptyViewRes = emptyLayoutRes;
            return this;
        }

        /**
         * <p>
         * </p>
         *
         * @return
         */
        public int getEmptyViewRes() {
            return emptyViewRes;
        }

        /**
         * <p>
         * Sets resource for layout with custom list view.
         * </p>
         *
         * @param listViewLayoutRes Layout resource.
         * @return This options.
         */
        public ListOptions listView(int listViewLayoutRes) {
            this.listViewRes = listViewLayoutRes;
            return this;
        }

        /**
         * <p>
         * </p>
         *
         * @return
         */
        public int getListViewRes() {
            return listViewRes;
        }
    }

    /**
     * Interface =============================
     */
}