br.liveo.searchliveo.SearchCardLiveo.java Source code

Java tutorial

Introduction

Here is the source code for br.liveo.searchliveo.SearchCardLiveo.java

Source

package br.liveo.searchliveo;

/*
 * Copyright 2015 Rudson Lima
 *
 * 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.
 */

import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.speech.RecognizerIntent;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Locale;

import br.liveo.searchliveo.interfaces.OnSearchListener;

public class SearchCardLiveo extends FrameLayout {

    private Activity mContext;

    private EditText mEdtSearch;

    private ImageView mImgArrowSearch;
    private ImageView mImgVoiceSearch;
    private ImageView mImgCloseSearch;

    private RecyclerView mRecyclerView;

    private CardView mCardSearch;

    private int mColorPrimaryDark;

    private boolean active = false;
    private boolean isVoice = true;

    private int mColorIcon = -1;
    private int mColorIconArrow = -1;
    private int mColorIconVoice = -1;
    private int mColorIconClose = -1;

    private int mStatusBarHideColor = -1;
    private int mStatusBarShowColor = -1;
    private OnSearchListener mSearchListener;

    private static String SEARCH_TEXT = "SEARCH_TEXT";
    public static int REQUEST_CODE_SPEECH_INPUT = 7777;
    private static String STATE_TO_SAVE = "STATE_TO_SAVE";
    private static String INSTANCE_STATE = "INSTANCE_STATE";

    /**
     * Start context and the listener Search Live library.
     * Use this method when you are using an Activity
     *
     * @param context - Context Activity
     */
    public SearchCardLiveo with(Context context) {

        if (this.mContext == null) {
            try {
                this.mContext = (Activity) context;
                this.mSearchListener = (OnSearchListener) context;
            } catch (ClassCastException e) {
                throw new ClassCastException(mContext.getString(R.string.warning_listener));
            }
        } else {
            build();
        }

        return this;
    }

    /**
     * Start context and the listener Search Live library.
     * Use this method when you are using an Fragment
     *
     * @param getActivity - Context Fragment
     * @param context - Listener
     */
    public SearchCardLiveo with(Activity getActivity, OnSearchListener context) {

        if (this.mContext == null) {
            try {
                this.mContext = getActivity;
                this.mSearchListener = context;
            } catch (ClassCastException e) {
                throw new ClassCastException(mContext.getString(R.string.warning_fragment_listener));
            }
        } else {
            build();
        }

        return this;
    }

    public void build() {

        if (this.mSearchListener == null) {
            throw new ClassCastException(mContext.getString(R.string.warning_listener));
        }

        try {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Resources.Theme theme = this.mContext.getTheme();
                TypedArray typedArray = theme.obtainStyledAttributes(new int[] { android.R.attr.colorPrimaryDark });
                setColorPrimaryDark(typedArray.getResourceId(0, 0));
            }
        } catch (Exception e) {
            e.getStackTrace();
        }
    }

    public SearchCardLiveo(Context context) {
        this(context, null);
    }

    public SearchCardLiveo(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SearchCardLiveo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (!isInEditMode()) {
            init(context);
            initAttribute(context, attrs, defStyleAttr);
        }
    }

    private void init(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.search_liveo_card, this, true);

        mEdtSearch = (EditText) view.findViewById(R.id.edt_search);

        mImgArrowSearch = (ImageView) view.findViewById(R.id.img_arrow_search);
        mImgVoiceSearch = (ImageView) view.findViewById(R.id.img_voice_search);

        mImgCloseSearch = (ImageView) view.findViewById(R.id.img_close_search);
        mImgCloseSearch.setVisibility(isVoice() ? View.GONE : View.VISIBLE);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_search_view);

        mCardSearch = (CardView) view.findViewById(R.id.card_search);
        mCardSearch.setVisibility(View.VISIBLE);

        mEdtSearch.setOnKeyListener(onKeyListener);

        mImgArrowSearch.setOnClickListener(onClickSearchArrow);
        mRecyclerView.setOnClickListener(onClickRecyclerView);
        mImgVoiceSearch.setOnClickListener(onClickVoiceSearch);
        mImgCloseSearch.setOnClickListener(onClickCloseSearch);

        mEdtSearch.setOnEditorActionListener(onEditorActionListener);
        mEdtSearch.addTextChangedListener(new OnTextWatcherEdtSearch());
    }

    private void initAttribute(Context context, AttributeSet attributeSet, int defStyleAttr) {
        TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.search_card_liveo, defStyleAttr,
                0);
        if (attr != null) {
            try {

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_hint)) {
                    hint(attr.getString(R.styleable.search_card_liveo_search_card_liveo_hint));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_text_color)) {
                    mEdtSearch.setTextColor(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_text_color, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_hint_color)) {
                    mEdtSearch.setHintTextColor(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_hint_color, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_color_icon)) {
                    setColorIcon(attr.getColor(R.styleable.search_card_liveo_search_card_liveo_color_icon, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_color_arrow)) {
                    setColorIconArrow(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_color_arrow, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_color_voice)) {
                    setColorIconVoice(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_color_voice, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_color_close)) {
                    setColorIconClose(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_color_close, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_background)) {
                    mCardSearch.setBackgroundColor(
                            attr.getColor(R.styleable.search_card_liveo_search_card_liveo_background, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_status_bar_show_color)) {
                    setStatusBarShowColor(attr
                            .getColor(R.styleable.search_card_liveo_search_card_liveo_status_bar_show_color, -1));
                }

                if (attr.hasValue(R.styleable.search_card_liveo_search_card_liveo_status_bar_hide_color)) {
                    setStatusBarHideColor(attr
                            .getColor(R.styleable.search_card_liveo_search_card_liveo_status_bar_hide_color, -1));
                }
            } finally {
                attr.recycle();
            }
        }
    }

    /**
     * Set a new background color. If you do not use this method and standard color is white SearchCardLiveo.
     * In his layout.xml you can use the "app:searchCardLiveoBackground="@color/..."" attribute
     *
     * @param resId color attribute - colors.xml file
     */
    public SearchCardLiveo backgroundResource(int resId) {
        mCardSearch.setBackgroundResource(resId);
        return this;
    }

    /**
     * Set a new background color. If you do not use this method and standard color is white SearchCardLiveo.
     * In his layout.xml you can use the "app:searchCardLiveoBackground="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo backgroundColor(int color) {
        mCardSearch.setBackgroundColor(ContextCompat.getColor(mContext, color));
        return this;
    }

    /**
     * Set a new text color.
     * In his layout.xml you can use the "app:searchCardLiveoTextColor="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo textColor(int color) {
        mEdtSearch.setTextColor(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new hint color.
     * In his layout.xml you can use the "app:searchCardLiveoHintColor="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo hintColor(int color) {
        mEdtSearch.setHintTextColor(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new text.
     * @param text "valeu"
     */
    public SearchCardLiveo text(String text) {
        mEdtSearch.setText(text);
        return this;
    };

    /**
     * Set a new hint.
     * In his layout.xml you can use the "app:searchCardLiveoHint="value"" attribute
     * @param text "valeu"
     */
    public SearchCardLiveo hint(String text) {
        mEdtSearch.setHint(text);
        return this;
    };

    /**
     * Set a new text.
     * @param text string attribute - string.xml file
     */
    public SearchCardLiveo text(int text) {
        mEdtSearch.setText(mContext.getString(text));
        return this;
    };

    /**
     * Set a new hint.
     * In his layout.xml you can use the "app:searchCardLiveoHint="@string/..."" attribute
     * @param text string attribute - string.xml file
     */
    public SearchCardLiveo hint(int text) {
        mEdtSearch.setHint(mContext.getString(text));
        return this;
    };

    /**
     * Set a new color for all icons (arrow, voice and close).
     * In his layout.xml you can use the "app:searchCardLiveoColorIcon="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo colorIcon(int color) {
        this.setColorIcon(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new color for back arrow
     * In his layout.xml you can use the "app:searchCardLiveoColorArrow="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo colorIconArrow(int color) {
        this.setColorIconArrow(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new color for voice
     * In his layout.xml you can use the "app:searchCardLiveoColorVoice="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo colorIconVoice(int color) {
        this.setColorIconVoice(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new color for close
     * In his layout.xml you can use the "app:searchCardLiveoColorClose="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo colorIconClose(int color) {
        this.setColorIconClose(ContextCompat.getColor(mContext, color));
        return this;
    };

    /**
     * Set a new color for statusBar when the SearchCardLiveo is closed
     * In his layout.xml you can use the "app:searchCardLiveoStatusBarHideColor="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo statusBarHideColor(int color) {
        setStatusBarHideColor(ContextCompat.getColor(mContext, color));
        return this;
    }

    /**
     * Set a new color for statusBar when the SearchCardLiveo for visible
     * In his layout.xml you can use the "app:searchCardLiveoStatusBarShowColor="@color/..."" attribute
     * @param color color attribute - colors.xml file
     */
    public SearchCardLiveo statusBarShowColor(int color) {
        setStatusBarShowColor(ContextCompat.getColor(mContext, color));
        return this;
    }

    /**
     * Hide voice icon
     */
    public SearchCardLiveo hideVoice() {
        setIsVoice(false);
        mImgVoiceSearch.setVisibility(View.GONE);
        return this;
    }

    /**
     * Show voice icon
     */
    public SearchCardLiveo showVoice() {
        setIsVoice(true);
        mImgVoiceSearch.setVisibility(View.VISIBLE);
        return this;
    }

    private void colorIcon() {
        if (getColorIcon() != -1 && getColorIconArrow() == -1) {
            mImgArrowSearch.setColorFilter(this.getColorIcon());
        }

        if (getColorIcon() != -1 && getColorIconVoice() == -1) {
            mImgVoiceSearch.setColorFilter(this.getColorIcon());
        }

        if (getColorIcon() != -1 && getColorIconClose() == -1) {
            mImgCloseSearch.setColorFilter(this.getColorIcon());
        }
    };

    private void colorIconArrow() {
        if (getColorIconArrow() != -1) {
            mImgArrowSearch.setColorFilter(this.getColorIconArrow());
        }
    };

    private void colorIconVoice() {
        if (this.getColorIconVoice() != -1) {
            mImgVoiceSearch.setColorFilter(this.getColorIconVoice());
        } else {
            mImgVoiceSearch.clearColorFilter();
        }
    };

    private void colorIconClose() {
        if (this.getColorIconClose() != -1) {
            mImgCloseSearch.setColorFilter(this.getColorIconClose());
        } else {
            mImgCloseSearch.clearColorFilter();
        }
    };

    private OnKeyListener onKeyListener = new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    hide();
                    return true;
                }
            }
            return false;
        }
    };

    private TextView.OnEditorActionListener onEditorActionListener = new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                hide();
                mContext.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                                .hideSoftInputFromWindow(mRecyclerView.getWindowToken(), 0);
                    }
                });
                return true;
            }
            return false;
        }
    };

    private OnClickListener onClickVoiceSearch = new OnClickListener() {
        @Override
        public void onClick(View v) {
            startVoice(mEdtSearch);
        }
    };

    private OnClickListener onClickCloseSearch = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mEdtSearch.getText().toString().length() != 0) {
                mEdtSearch.setText("");
                mContext.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                                .toggleSoftInput(InputMethodManager.SHOW_FORCED,
                                        InputMethodManager.HIDE_IMPLICIT_ONLY);
                    }
                });
            }
        }
    };

    private OnClickListener onClickSearchArrow = new OnClickListener() {
        @Override
        public void onClick(View v) {
            hide();
        }
    };

    private OnClickListener onClickRecyclerView = new OnClickListener() {
        @Override
        public void onClick(View v) {
            hide();
        }
    };

    /**
     * If SearchView is active(show), this method returns the value true
     */
    public boolean isActive() {
        return active;
    }

    private void setActive(boolean active) {
        this.active = active;
    }

    public boolean isVoice() {
        return isVoice;
    }

    public void setIsVoice(boolean isVoice) {
        this.isVoice = isVoice;
    }

    public int getStatusBarHideColor() {
        return mStatusBarHideColor;
    }

    public void setStatusBarHideColor(int mStatusBarHideColor) {
        this.mStatusBarHideColor = mStatusBarHideColor;
    }

    public int getStatusBarShowColor() {
        return mStatusBarShowColor;
    }

    public void setStatusBarShowColor(int mStatusBarShowColor) {
        this.mStatusBarShowColor = mStatusBarShowColor;
    }

    private int getColorIcon() {
        return mColorIcon;
    }

    private void setColorIcon(int colorIcon) {
        this.mColorIcon = colorIcon;
        this.colorIcon();
    }

    public int getColorIconArrow() {
        return mColorIconArrow;
    }

    public void setColorIconArrow(int color) {
        this.mColorIconArrow = color;
        this.colorIconArrow();
    }

    public int getColorIconVoice() {
        return mColorIconVoice;
    }

    public void setColorIconVoice(int color) {
        this.mColorIconVoice = color;
        this.colorIconVoice();
    }

    public int getColorIconClose() {
        return mColorIconClose;
    }

    public void setColorIconClose(int color) {
        this.mColorIconClose = color;
        this.colorIconClose();
    }

    private class OnTextWatcherEdtSearch implements TextWatcher {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            try {
                if (mEdtSearch.getText().toString().length() == 0) {
                    mImgCloseSearch.setVisibility(isVoice() ? View.GONE : View.VISIBLE);
                    mImgVoiceSearch.setVisibility(isVoice() ? View.VISIBLE : View.GONE);
                    mImgVoiceSearch.setImageResource(R.drawable.ic_keyboard_voice_color_24dp);
                    colorIconVoice();
                } else {
                    mImgVoiceSearch.setVisibility(View.GONE);
                    mImgCloseSearch.setVisibility(View.VISIBLE);
                    mImgCloseSearch.setImageResource(R.drawable.ic_close_color_24dp);
                    colorIconClose();
                }

                colorIcon();
                colorIconArrow();
                mSearchListener.changedSearch(mEdtSearch.getText().toString());
            } catch (Exception e) {
                e.getStackTrace();
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    }

    /**
     * Hide SearchCardLiveo
     */
    public void hide() {
        try {
            hideAnimation();
            setActive(false);
        } catch (Exception e) {
            e.getStackTrace();
        }
    }

    /**
     * Show SearchCardLiveo
     */
    public SearchCardLiveo show() {
        setActive(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            try {
                showAnimation();
            } catch (ClassCastException e) {
                throw new ClassCastException(mContext.getString(R.string.warning_with));
            }

        } else {

            Animation mFadeIn = AnimationUtils.loadAnimation(mContext.getApplicationContext(),
                    android.R.anim.fade_in);
            mCardSearch.setEnabled(true);
            mCardSearch.setVisibility(View.VISIBLE);
            mCardSearch.setAnimation(mFadeIn);

            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                            .toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
                }
            });
        }

        mEdtSearch.requestFocus();
        return this;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void showAnimation() {
        try {

            if (getStatusBarShowColor() != -1) {
                mContext.getWindow().setStatusBarColor(getStatusBarShowColor());
            } else {
                mContext.getWindow()
                        .setStatusBarColor(ContextCompat.getColor(mContext, R.color.search_liveo_primary_dark));
            }

            final Animator animator = ViewAnimationUtils.createCircularReveal(mCardSearch,
                    mCardSearch.getWidth() - (int) dpToPixel(24, this.mContext), (int) dpToPixel(23, this.mContext),
                    0, (float) Math.hypot(mCardSearch.getWidth(), mCardSearch.getHeight()));
            animator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    mContext.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                                    .toggleSoftInput(InputMethodManager.SHOW_FORCED,
                                            InputMethodManager.HIDE_IMPLICIT_ONLY);
                        }
                    });
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });

            animator.setDuration(300);
            animator.start();
        } catch (Exception e) {
            e.getStackTrace();
            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                            .toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
                }
            });
        }

        mCardSearch.setVisibility(View.VISIBLE);
    }

    private SearchCardLiveo hideAnimation() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            if (getStatusBarHideColor() != -1) {
                mContext.getWindow().setStatusBarColor(getStatusBarHideColor());
            } else {
                mContext.getWindow().setStatusBarColor(getColorPrimaryDark());
            }

            final Animator animatorHide = ViewAnimationUtils.createCircularReveal(mCardSearch,
                    mCardSearch.getWidth() - (int) dpToPixel(24, mContext), (int) dpToPixel(23, mContext),
                    (float) Math.hypot(mCardSearch.getWidth(), mCardSearch.getHeight()), 0);
            animatorHide.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                    mContext.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                                    .hideSoftInputFromWindow(mRecyclerView.getWindowToken(), 0);
                        }
                    });
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    mCardSearch.setVisibility(View.GONE);
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            animatorHide.setDuration(200);
            animatorHide.start();

        } else {

            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                            .hideSoftInputFromWindow(mRecyclerView.getWindowToken(), 0);
                }
            });

            Animation mFadeOut = AnimationUtils.loadAnimation(mContext.getApplicationContext(),
                    android.R.anim.fade_out);
            mCardSearch.setAnimation(mFadeOut);
            mCardSearch.setVisibility(View.INVISIBLE);
        }

        mEdtSearch.setText("");
        mCardSearch.setEnabled(false);
        return this;
    }

    private int getColorPrimaryDark() {
        return mColorPrimaryDark;
    }

    private void setColorPrimaryDark(int mColorPrimaryDark) {
        this.mColorPrimaryDark = ContextCompat.getColor(mContext, mColorPrimaryDark);
    }

    private float dpToPixel(float dp, Context context) {
        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        return dp * (metrics.densityDpi / 160f);
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
        bundle.putBoolean(STATE_TO_SAVE, this.isActive());

        if (!mEdtSearch.getText().toString().trim().equals("")) {
            bundle.putString(SEARCH_TEXT, mEdtSearch.getText().toString());
        }

        return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {

        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            this.setActive(bundle.getBoolean(STATE_TO_SAVE));

            String text = bundle.getString(SEARCH_TEXT, "");
            if (!text.trim().equals("")) {
                mEdtSearch.setText(text);
            }

            if (this.isActive()) {
                show();
            }

            state = bundle.getParcelable(INSTANCE_STATE);
        }

        super.onRestoreInstanceState(state);
    }

    private void startVoice(EditText editText) {
        ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(editText.getWindowToken(), 0);

        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT, mContext.getString(R.string.searchview_voice));
        try {
            mContext.startActivityForResult(intent, REQUEST_CODE_SPEECH_INPUT);
        } catch (ActivityNotFoundException a) {
            Toast.makeText(mContext.getApplicationContext(), R.string.not_supported, Toast.LENGTH_SHORT).show();
        }
    }

    public void resultVoice(int requestCode, int resultCode, Intent data) {
        if (requestCode == SearchCardLiveo.REQUEST_CODE_SPEECH_INPUT) {
            if (resultCode == Activity.RESULT_OK && null != data) {
                ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                mEdtSearch.setText(result.get(0));
            }
        }
    }
}