2017-06-06 18:53:32 jifashihan 阅读数 580
  • 苹果iOS应用UI控件开发

    本视频是传智播客iOS学院精心录制的免费精华版UI基础视频,该视频特点在于较大程度保证了知识点的完整性,视频的起点都是针对有一定OC基础的同学

    14109 人正在学习 去看看 传智

UI需要android和IOS统一,搜索框为IOS风格,在网上找了一个
【Android自定义控件】仿IOS风格的搜索框

在此基础上,对焦点进行了处理,默认不获得焦点,点击以后得到焦点,并弹出软键盘

/**
 * 仿IOS搜索框,默认字体居中,点击搜索框,字体移到左侧

 */

public class SearchEditText extends AppCompatEditText implements View.OnFocusChangeListener, View.OnKeyListener, TextWatcher, View.OnClickListener
{
    private static final String TAG = "SearchEditText";
    /**
     * 图标是否默认在左边
     */
    private boolean isIconLeft = false;
    /**
     * 是否点击软键盘搜索
     */
    private boolean pressSearch = false;
    /**
     * 软键盘搜索键监听
     */
    private OnSearchClickListener listener;

    private Drawable[] drawables; // 控件的图片资源
    private Drawable drawableLeft, drawableDel; // 搜索图标和删除按钮图标
    private int eventX, eventY; // 记录点击坐标
    private Rect rect; // 控件区域
    private Context context;

    public void setOnSearchClickListener(OnSearchClickListener listener)
    {
        this.listener = listener;
    }

    public interface OnSearchClickListener
    {
        void onSearchClick(View view);

        void onTextChanged(String text);

        void beforeTextChanged(String text);

        void afterTextChanged(String text);

        void viewClick();
    }

    public SearchEditText(Context context)
    {
        this(context, null);
        this.context = context;
        init();
    }


    public SearchEditText(Context context, AttributeSet attrs)
    {
        this(context, attrs, android.R.attr.editTextStyle);
        this.context = context;
        init();
    }


    public SearchEditText(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }


    private void init()
    {
        //默认不获取焦点
        setFocusable(false);
        setOnFocusChangeListener(this);
        setOnKeyListener(this);
        addTextChangedListener(this);
        setOnClickListener(this);

        //关闭粘贴复制功能
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            setCustomInsertionActionModeCallback(new ActionMode.Callback()
            {
                @Override
                public boolean onCreateActionMode(ActionMode mode, Menu menu)
                {
                    return false;
                }

                @Override
                public boolean onPrepareActionMode(ActionMode mode, Menu menu)
                {
                    return false;
                }

                @Override
                public boolean onActionItemClicked(ActionMode mode, MenuItem item)
                {
                    return false;
                }

                @Override
                public void onDestroyActionMode(ActionMode mode)
                {

                }
            });
        }
        setLongClickable(false);

    /*    SoftKeyBoardListener.setListener(context, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener()
        {
            @Override
            public void keyBoardShow(int height)
            {
            }

            @Override
            public void keyBoardHide(int height)
            {   //键盘关闭,搜索框失去焦点,显示正常的列表,隐藏搜索列表,设置上拉下拉可用
                setFocusable(false);
                clearFocus();


            }
        });
                */

    }

    @Override
    public void onClick(View v)
    {
        if (pressSearch)
        {
            return;
        }
        if (!isFocused())
        {
            //点击控件获取焦点,弹出键盘
            setFocusableInTouchMode(true);
            requestFocus();
            isIconLeft = true;
            invalidate();
            setHint("请输入关键字");

        }
        setSelectAllOnFocus(false);
        InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

        imm.showSoftInput(this, 0);

        /*InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);*/
        if (listener != null)
        {
            listener.viewClick();
        }

    }


    @Override
    protected void onDraw(Canvas canvas)
    {
        if (isIconLeft)
        { // 如果是默认样式,直接绘制
            if (length() < 1)
            {
                drawableDel = null;
            }
            this.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, drawableDel, null);
            super.onDraw(canvas);
        }
        else
        { // 如果不是默认样式,需要将图标绘制在中间
            if (drawables == null)
                drawables = getCompoundDrawables();
            if (drawableLeft == null)
                drawableLeft = drawables[0];
            float textWidth = getPaint().measureText(getHint().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = drawableLeft.getIntrinsicWidth();
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
            super.onDraw(canvas);
        }
    }


    @Override
    public void onFocusChange(View v, boolean hasFocus)
    {
        // 被点击时,恢复默认样式
        if (!pressSearch && TextUtils.isEmpty(getText().toString()))
        {
            isIconLeft = hasFocus;
        }
    }

    //点击取消等操作,复原搜索框
    public void setDefault()
    {
        setFocusable(false);
        clearFocus();
        setText("");
        setHint("搜索");
        isIconLeft = false;
        pressSearch = false;
        invalidate();
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event)
    {
        pressSearch=false;
        //加入&& event.getAction() == KeyEvent.ACTION_DOWN防止执行两次
        if (listener != null && event.getAction() == KeyEvent.ACTION_DOWN)
        {
            pressSearch = (keyCode == KeyEvent.KEYCODE_ENTER);
            if (pressSearch)
            {
                /*隐藏软键盘*/
                InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm.isActive())
                {
                    imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
                }
                listener.onSearchClick(v);
                pressSearch = false;
                setFocusable(false);
                clearFocus();
            }
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
// 清空edit内容
        if (drawableDel != null && event.getAction() == MotionEvent.ACTION_UP)
        {
            eventX = (int) event.getRawX();
            eventY = (int) event.getRawY();
            Log.i(TAG, "eventX = " + eventX + "; eventY = " + eventY);
            if (rect == null)
                rect = new Rect();
            getGlobalVisibleRect(rect);
            rect.left = rect.right - drawableDel.getIntrinsicWidth();
            if (rect.contains(eventX, eventY))
            {
                //点击删除按钮,清空文字,关闭软键盘,设置焦点不可用
                setText("");
                setFocusable(false);
                /*隐藏软键盘*/
                InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm.isActive())
                {
                    imm.hideSoftInputFromWindow(this.getApplicationWindowToken(), 0);
                }
                // listener.onSearchClick(this);
            }
        }
// 删除按钮被按下时改变图标样式
        if (drawableDel != null && event.getAction() == MotionEvent.ACTION_DOWN)
        {
            eventX = (int) event.getRawX();
            eventY = (int) event.getRawY();
            Log.i(TAG, "eventX = " + eventX + "; eventY = " + eventY);
            if (rect == null)
                rect = new Rect();
            getGlobalVisibleRect(rect);
            rect.left = rect.right - drawableDel.getIntrinsicWidth();
            if (rect.contains(eventX, eventY))
                drawableDel = this.getResources().getDrawable(R.drawable.delete_new);
        }
        else
        {
            drawableDel = this.getResources().getDrawable(R.drawable.delete_new);
        }
        return super.onTouchEvent(event);
    }


    @Override
    public void afterTextChanged(Editable arg0)
    {
        if (this.length() < 1)
        {
            drawableDel = null;
        }
        else
        {
            drawableDel = this.getResources().getDrawable(R.drawable.delete_new);
        }
        if (listener != null)
        {
            listener.afterTextChanged(arg0 + "");
        }
    }


    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
    {
        if (listener != null)
        {
            listener.beforeTextChanged(arg0 + "");
        }
    }

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
    {
        if (listener != null)
        {
            listener.onTextChanged(arg0 + "");
        }

    }
}
2018-01-13 22:03:34 Sure_Min 阅读数 385
  • 苹果iOS应用UI控件开发

    本视频是传智播客iOS学院精心录制的免费精华版UI基础视频,该视频特点在于较大程度保证了知识点的完整性,视频的起点都是针对有一定OC基础的同学

    14109 人正在学习 去看看 传智

说起来毕业也一年半了,一直想把积累的一些东西搬到博客上来但找不到什么时间(其实是因为懒,>_<),现在有点时间就做一些吧,万事开头难,嘿嘿。

 

今天带来一个自定义控件叫IosDialog,就是ios上那种风格的有一个确定键一个返回键的文本提示对话框。控件是很早以前写的,之所以写这个控件是因为UI在做效果图的时候总是参照ios的风格来做,而ios那边有现成的控件,android这边我觉得每次都copy一大段的代码太麻烦了,于是就封装了这个控件。废话说了一堆,下面正片开始。

 

先自定义一个对话框风格,在styles文件下添加如下代码:

<!-- 自定义对话框风格 -->
<style name="CustomDialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
</style>

然后要定义一些对话框的背景资源文件,比如白色圆角背景,按钮的selector什么的,代码如下:

dialog_top_up.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />

</shape>

dialog_bottom_left_up.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners android:bottomLeftRadius="10dp" />

</shape>

dialog_bottom_left_down.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />

    <corners android:bottomLeftRadius="10dp" />

</shape>

dialog_bottom_left_selector.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/dialog_bottom_left_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/dialog_bottom_left_down" android:state_pressed="true"></item>

</selector>

dialog_bottom_right_up.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners android:bottomRightRadius="10dp" />

</shape>

dialog_bottom_right_down.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />

    <corners android:bottomRightRadius="10dp" />

</shape>

dialog_bottom_right_selector.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/dialog_bottom_right_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/dialog_bottom_right_down" android:state_pressed="true"></item>

</selector>

以上一共7个xml文件都添加到drawable目录下就可以了,没什么好讲的。


然后在layout目录下新建一个对话框的布局文件dialog_ios.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/dialog_top_up"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginTop="20dp"
            android:text="我是标题"
            android:textColor="#4a4a4a"
            android:textSize="18sp" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="40dp"
            android:padding="20dp">

            <TextView
                android:id="@+id/content_textview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="我是文字"
                android:textColor="#666666"
                android:textSize="16sp" />

        </RelativeLayout>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#dddddd" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/cancel_button"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:background="@drawable/dialog_bottom_left_selector"
            android:gravity="center"
            android:text="取消"
            android:textColor="#1e90ff"
            android:textSize="16sp" />

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="#dddddd" />

        <Button
            android:id="@+id/asure_button"
            android:layout_width="0dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:background="@drawable/dialog_bottom_right_selector"
            android:gravity="center"
            android:text="确定"
            android:textColor="#1e90ff"
            android:textSize="16sp" />

    </LinearLayout>

</LinearLayout>


以上准备工作都弄完以后就可以上控件IosDialog的本体了,如下:

public class IosDialog extends Dialog {
    private Context context;

    private TextView titleTextView;
    private TextView contentTextView;
    private Button cancelButton;
    private Button asureButton;
    private View view;

    //标题
    private String title;

    //内容
    private String text;

    //确定按钮的文字
    private String asureText;

    //取消按钮是的文字
    private String cancelText;

    //对话框位于屏幕位置
    private int gravity;

    //标题大小
    private int titleTextSize;

    //标题颜色
    private int titleTextColor;

    //内容大小
    private int textSize;

    //内容颜色
    private int textColor;

    //确定和取消按钮文字大小
    private int buttonTextSize;

    //确定按钮文字颜色
    private int buttonAsureTextColor;

    //取消按钮文字颜色
    private int buttonCancelTextColor;

    //对话框宽度
    private int width;

    //对话框高度
    private int height;

    //确定和取消按钮点击回调接口
    private OnButtonClickListener listener;

    public IosDialog(Context context) {
        super(context, R.style.CustomDialog);
        this.context = context;
    }

    public IosDialog(Context context, int theme) {
        super(context, theme);
        this.context = context;
    }

    public IosDialog createDialog() {
        view = LayoutInflater.from(context).inflate(R.layout.dialog_ios, null);

        titleTextView = (TextView) view.findViewById(R.id.title_textview);
        contentTextView = (TextView) view.findViewById(R.id.content_textview);
        cancelButton = (Button) view.findViewById(R.id.cancel_button);
        asureButton = (Button) view.findViewById(R.id.asure_button);
        titleTextView.setVisibility(title != null ? View.VISIBLE : View.GONE);
        titleTextView.setText(title);
        titleTextView.setTextColor(titleTextColor != 0 ? titleTextColor : Color.parseColor("#4a4a4a"));
        titleTextView.setTextSize(titleTextSize != 0 ? titleTextSize : 18);
        contentTextView.setText(text);
        contentTextView.setTextColor(textColor != 0 ? textColor : Color.parseColor("#666666"));
        contentTextView.setTextSize(textSize != 0 ? textSize : 16);
        cancelButton.setText(cancelText != null ? cancelText : "取消");
        cancelButton.setTextColor(buttonCancelTextColor != 0 ? buttonCancelTextColor : Color.parseColor("#1e90ff"));
        cancelButton.setTextSize(buttonTextSize != 0 ? buttonTextSize : 16);
        asureButton.setText(asureText != null ? asureText : "确定");
        asureButton.setTextColor(buttonAsureTextColor != 0 ? buttonAsureTextColor : Color.parseColor("#1e90ff"));
        asureButton.setTextSize(buttonTextSize != 0 ? buttonTextSize : 16);
        cancelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) listener.onCancelClick();
            }
        });
        asureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) listener.onAsureClick();
            }
        });

        show();
        setContentView(view);
        getWindow().getAttributes().gravity = gravity != 0 ? gravity : Gravity.CENTER;
        getWindow().setLayout(width != 0 ? width : getWindowWidth((Activity) context)
                - 2 * dp2px(45), height != 0 ? height : WindowManager.LayoutParams.WRAP_CONTENT);
        setCanceledOnTouchOutside(false);
        setCancelable(true);

        return this;
    }

    public void setAsureText(String asureText) {
        this.asureText = asureText;
    }

    public void setButtonAsureTextColor(int buttonAsureTextColor) {
        this.buttonAsureTextColor = buttonAsureTextColor;
    }

    public void setButtonCancelTextColor(int buttonCancelTextColor) {
        this.buttonCancelTextColor = buttonCancelTextColor;
    }

    public void setButtonTextSize(int buttonTextSize) {
        this.buttonTextSize = buttonTextSize;
    }

    public void setCancelText(String cancelText) {
        this.cancelText = cancelText;
    }

    public void setGravity(int gravity) {
        this.gravity = gravity;
    }

    public void setTitleTextSize(int titleTextSize) {
        this.titleTextSize = titleTextSize;
    }

    public void setTitleTextColor(int titleTextColor) {
        this.titleTextColor = titleTextColor;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setText(String text) {
        this.text = text;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    public void setView(View view) {
        this.view = view;
    }

    public void setDialogSize(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public interface OnButtonClickListener {
        void onAsureClick();

        void onCancelClick();
    }

    public void setOnButtonClickListener(OnButtonClickListener listener) {
        this.listener = listener;
    }

    private int getWindowWidth(Activity activity) {
        WindowManager windowManager = activity.getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        return display.getWidth();
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    public static class DialogBuilder {
        IosDialog dialog;

        public DialogBuilder(Context context) {
            dialog = new IosDialog(context);
        }

        /**
         * 设置对话框在屏幕的位置
         * @param gravity 类Gravity下的位置常数
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setGravity(int gravity) {
            dialog.setGravity(gravity);

            return this;
        }

        /**
         * 设置确定按钮文字
         * @param asureText 文字内容
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setAsureText(String asureText) {
            dialog.setAsureText(asureText);
            return this;
        }

        /**
         * 设置确定按钮文字颜色
         * @param buttonAsureTextColor 颜色值
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setButtonAsureTextColor(int buttonAsureTextColor) {
            dialog.setButtonAsureTextColor(buttonAsureTextColor);
            return this;
        }

        /**
         * 设置取消按钮文字颜色
         * @param buttonCancelTextColor 颜色值
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setButtonCancelTextColor(int buttonCancelTextColor) {
            dialog.setButtonCancelTextColor(buttonCancelTextColor);
            return this;
        }

        /**
         * 设置确定和取消按钮的文字大小
         * @param buttonTextSize 文字大小,单位sp
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setButtonTextSize(int buttonTextSize) {
            dialog.setButtonTextSize(buttonTextSize);
            return this;
        }

        /**
         * 设置取消按钮文字
         * @param cancelText 文字内容
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setCancelText(String cancelText) {
            dialog.setCancelText(cancelText);
            return this;
        }

        /**
         * 设置对话框大小
         * @param width   对话框宽度,单位px
         * @param height  对话框高度,单位px
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setDialogSize(int width, int height) {
            dialog.setDialogSize(width, height);
            return this;
        }

        /**
         * 设置标题大小
         * @param titleTextSize 文字大小,单位sp
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setTitleTextSize(int titleTextSize) {
            dialog.setTextSize(titleTextSize);
            return this;
        }

        /**
         * 设置标题颜色
         * @param titleTextColor 颜色值
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setTitleTextColor(int titleTextColor) {
            dialog.setTitleTextColor(titleTextColor);
            return this;
        }

        /**
         * 设置标题
         * @param title 文字内容
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setTitle(String title) {
            dialog.setTitle(title);
            return this;
        }

        /**
         * 设置内容
         * @param text 文字内容
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setText(String text) {
            dialog.setText(text);
            return this;
        }

        /**
         * 设置内容颜色
         * @param textColor 颜色值
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setTextColor(int textColor) {
            dialog.setTextColor(textColor);
            return this;
        }

        /**
         * 设置内容大小
         * @param textSize 文字大小,单位sp
         * @return 当前的DialogBuilder
         */
        public DialogBuilder setTextSize(int textSize) {
            dialog.setTextSize(textSize);
            return this;
        }

        /**
         * 设置确定和取消按钮的点击回调
         * @param listener 回调接口
         * @return 当前的DialogBuilder
         */
        public DialogBuilder addListener(OnButtonClickListener listener) {
            dialog.setOnButtonClickListener(listener);
            return this;
        }

        /**
         * 创建对话框,放在最后执行
         * @return 创建的IosDialog实体
         */
        public IosDialog create() {
            return dialog.createDialog();
        }
    }
}

这里稍微说明一下,控价引用建造者模式的思想,通过创建内部类DialogBuilder(建造者)的实体,设置好相关参数后调用它下面的create方法即可,相关参数个方法的意义已经在注释里写的很清楚了,不再累述。


最后就可以调用了。贴上MainActivity的代码:
public class MainActivity extends Activity {
    private Button button;

    private IosDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initData() {

    }

    private void initView() {
        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog();
            }
        });
    }仿ios风格

    private void showDialog() {
        dialog = new IosDialog.DialogBuilder(this)
                .setText("嫁给我好吗?")
                .addListener(new IosDialog.OnButtonClickListener() {
                    @Override
                    public void onAsureClick() {
                        Toast.makeText(MainActivity.this, "太好了", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }

                    @Override
                    public void onCancelClick() {
                        Toast.makeText(MainActivity.this, "悲伤的故事", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .create();
    }
}

这里稍微说明一下,控价引用建造者模式的思想,通过创建内部类DialogBuilder(建造者)的实体,设置好相关参数后调用它下面的create方法即可,相关参数个方法的意义已经在注释里写的很清楚了,不再累述。


最后就可以调用了。贴上MainActivity的代码:

public class MainActivity extends Activity {
    private Button button;

    private IosDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initData() {

    }

    private void initView() {
        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog();
            }
        });
    }

    private void showDialog() {
        dialog = new IosDialog.DialogBuilder(this)
                .setText("嫁给我好吗?")
                .addListener(new IosDialog.OnButtonClickListener() {
                    @Override
                    public void onAsureClick() {
                        Toast.makeText(MainActivity.this, "太好了", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }

                    @Override
                    public void onCancelClick() {
                        Toast.makeText(MainActivity.this, "悲伤的故事", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                })
                .create();
    }
}

布局文件activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="SHOW DIALOG" />

</LinearLayout>

只有一个按钮。


最简单的调用方法只需要new IosDialog.DialogBuilder(this)创建一个DialogBuilder的实体,然后.setText设置文字内容,然后.addListener添加一个按钮点击的回调,最后.create(),一个对话框就弹出来了,效果如下:

                                                               

控件支持设置更多的自定义属性,比如在原来的代码上添加:

dialog = new IosDialog.DialogBuilder(this)
        ...

        .setAsureText("嗯")
        .setCancelText("你是个好人")
        .setTextColor(Color.parseColor("#bc8f8f"))
        
        ...
        .create();

就可以改变按钮的文字内容和说明文字的颜色,效果如下:

                                                                

控件还支持添加一个标题,使用setTitle方法(不设置标题时标题栏自动隐藏),添加如下代码:

dialog = new IosDialog.DialogBuilder(this)
       ...

        .setButtonCancelTextColor(Color.parseColor("#aaaaaa"))
        .setTitle("求婚大作战")
       
        ...
        .create();

再次运行,效果如下:

                                                                

更多设置方法的含义在控件源码中都有详细说明,大家可以自己试一试。

 

总结一下控件的用法就是:new一个DialogBulder,根据需要set一堆东西,最后create一下。是不是很简单?建造者模式真是懒人的福利,哈哈哈。


最后附上源码地址:点击打开链接


这次的内容就到这里,我们下次再见


2016-07-25 09:53:30 bfbx5173 阅读数 3229
  • 苹果iOS应用UI控件开发

    本视频是传智播客iOS学院精心录制的免费精华版UI基础视频,该视频特点在于较大程度保证了知识点的完整性,视频的起点都是针对有一定OC基础的同学

    14109 人正在学习 去看看 传智

尊重原创转载请注明:http://blog.csdn.net/bfbx5173/article/details/52020733


UI 老是喜欢以iOS风格为主,同时产品要求两边风格一致。这个时候就悲催了。 什么时候我md可以当家做主,不过事还是要继续做。


   


在此分享一个仿iOS7的底部弹出框。

自定义Dialog 之前在  滚轮控件LoopView+自定义Dialog [时间地域选择器] Picker

有谈到过写法,是java中常用的一种构造者模式,大家多多练习一下就都会了。


public class BottomMenuDialog extends Dialog {

    public BottomMenuDialog(Context context, int themeResId) {
        super(context, themeResId);
    }

    public static class Params {
        private final List<BottomMenu> menuList = new ArrayList<>();
        private View.OnClickListener cancelListener;
        private String menuTitle;
        private String cancelText;
        private Context context;
    }

    public static class Builder {
        private boolean canCancel = true;
        private boolean shadow = true;
        private final Params p;

        public Builder(Context context) {
            p = new Params();
            p.context = context;
        }

        public Builder setCanCancel(boolean canCancel) {
            this.canCancel = canCancel;
            return this;
        }

        public Builder setShadow(boolean shadow) {
            this.shadow = shadow;
            return this;
        }

        public Builder setTitle(String title) {
            this.p.menuTitle = title;
            return this;
        }

        public Builder addMenu(String text, View.OnClickListener listener) {
            BottomMenu bm = new BottomMenu(text, listener);
            this.p.menuList.add(bm);
            return this;
        }

        public Builder addMenu(int textId, View.OnClickListener listener) {
            return addMenu(p.context.getString(textId), listener);
        }

        public Builder setCancelListener(View.OnClickListener cancelListener) {
            p.cancelListener = cancelListener;
            return this;
        }

        public Builder setCancelText(int resId) {
            p.cancelText = p.context.getString(resId);
            return this;
        }

        public Builder setCancelText(String text) {
            p.cancelText = text;
            return this;
        }

        public BottomMenuDialog create() {
            final BottomMenuDialog dialog = new BottomMenuDialog(p.context, shadow ? R.style.Theme_Light_NoTitle_Dialog : R.style.Theme_Light_NoTitle_NoShadow_Dialog);
            Window window = dialog.getWindow();
            window.setWindowAnimations(R.style.Animation_Bottom_Rising);

            window.getDecorView().setPadding(0, 0, 0, 0);
            WindowManager.LayoutParams lp = window.getAttributes();
            lp.width = WindowManager.LayoutParams.MATCH_PARENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            window.setAttributes(lp);
            window.setGravity(Gravity.BOTTOM);

            View view = LayoutInflater.from(p.context).inflate(R.layout.dialog_bottom_menu, null);

            TextView btnCancel = (TextView) view.findViewById(R.id.btn_cancel);
            ViewGroup layContainer = (ViewGroup) view.findViewById(R.id.lay_container);
            LayoutParams lpItem = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
            LayoutParams lpDivider = new LayoutParams(LayoutParams.MATCH_PARENT, 1);
            int dip1 = (int) (1 * p.context.getResources().getDisplayMetrics().density + 0.5f);
            int spacing = dip1 * 12;

            boolean hasTitle = !TextUtils.isEmpty(p.menuTitle);
            if (hasTitle) {
                TextView tTitle = new TextView(p.context);
                tTitle.setLayoutParams(lpItem);
                tTitle.setGravity(Gravity.CENTER);
                tTitle.setTextColor(0xFF8F8F8F);
                tTitle.setText(p.menuTitle);
                tTitle.setTextSize(17);
                tTitle.setPadding(0, spacing, 0, spacing);
                tTitle.setBackgroundResource(R.drawable.common_dialog_selection_selector_top);
                layContainer.addView(tTitle);

                View viewDivider = new View(p.context);
                viewDivider.setLayoutParams(lpDivider);
                viewDivider.setBackgroundColor(0xFFCED2D6);
                layContainer.addView(viewDivider);
            }

            for (int i = 0; i < p.menuList.size(); i++) {
                BottomMenu bottomMenu = p.menuList.get(i);
                TextView bbm = new TextView(p.context);
                bbm.setLayoutParams(lpItem);
                int backgroundResId = R.drawable.common_dialog_selection_selector_center;
                if (p.menuList.size() > 1) {
                    if (i == 0) {
                        if (hasTitle) {
                            backgroundResId = R.drawable.common_dialog_selection_selector_center;
                        } else {
                            backgroundResId = R.drawable.common_dialog_selection_selector_top;
                        }
                    } else if (i == p.menuList.size() - 1) {
                        backgroundResId = R.drawable.common_dialog_selection_selector_bottom;
                    }
                } else if (p.menuList.size() == 1) {
                    backgroundResId = R.drawable.common_dialog_selection_selector_singleton;
                }
                bbm.setBackgroundResource(backgroundResId);
                bbm.setPadding(0, spacing, 0, spacing);
                bbm.setGravity(Gravity.CENTER);
                bbm.setText(bottomMenu.funName);
                bbm.setTextColor(0xFF007AFF);
                bbm.setTextSize(19);
                bbm.setOnClickListener(bottomMenu.listener);
                layContainer.addView(bbm);

                if (i != p.menuList.size() - 1) {
                    View viewDivider = new View(p.context);
                    viewDivider.setLayoutParams(lpDivider);
                    viewDivider.setBackgroundColor(0xFFCED2D6);
                    layContainer.addView(viewDivider);
                }
            }

            if (!TextUtils.isEmpty(p.cancelText)) {
                btnCancel.setText(p.cancelText);
            }

            if (p.cancelListener != null) {
                btnCancel.setOnClickListener(p.cancelListener);
            } else {
                btnCancel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialog.dismiss();
                    }
                });
            }


            dialog.setContentView(view);
            dialog.setCanceledOnTouchOutside(canCancel);
            dialog.setCancelable(canCancel);
            return dialog;
        }


    }

    private static class BottomMenu {
        public String funName;
        public View.OnClickListener listener;

        public BottomMenu(String funName, View.OnClickListener listener) {
            this.funName = funName;
            this.listener = listener;
        }
    }
}

主体代码如上,逻辑并不是很难。

名字不会取,所以就叫BottomMenuDialog了, 嘿嘿 通俗易懂。

先通过Builder配置一些可变的属性 ,然后在create的时候将这个自己配置的Bottom构建出来。


之后在activity中:

findViewById(R.id.b_5).setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                mBottomMenuDialog = new BottomMenuDialog.Builder(MainActivity.this)
                        .setTitle("更换封面")
                        .addMenu("从手机相册选择", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                mBottomMenuDialog.dismiss();
                                Toast.makeText(v.getContext(), "从手机相册选择" , Toast.LENGTH_SHORT).show();
                            }
                        }).addMenu("从空间相册选择", new View.OnClickListener() {
                             @Override
                             public void onClick(View v) {
                                 mBottomMenuDialog.dismiss();
                                 Toast.makeText(v.getContext(), "从空间相册选择" , Toast.LENGTH_SHORT).show();
                             }
                         }).addMenu("拍一张", new View.OnClickListener() {
                             @Override
                             public void onClick(View v) {
                                 mBottomMenuDialog.dismiss();
                                 Toast.makeText(v.getContext(), "拍一张" , Toast.LENGTH_SHORT).show();
                             }
                         }).create();
                mBottomMenuDialog.show();
            }
        });

希望能给刚入手的朋友提供帮助,同时节约时间。


[戳我转到源码地址,是一个demo工程,导入ide可直接运行]



2018-09-13 09:45:56 say_from_wen 阅读数 552
  • 苹果iOS应用UI控件开发

    本视频是传智播客iOS学院精心录制的免费精华版UI基础视频,该视频特点在于较大程度保证了知识点的完整性,视频的起点都是针对有一定OC基础的同学

    14109 人正在学习 去看看 传智

写在开头

项目中UI设计了一个仿IOS界面跳转3D翻转的效果,尼玛人家系统自带的啊。无奈只好找轮子了,看了看网上全是一个acitivity两个VIew或者两个Fragment的跳转,作为技术人的执着不想那么实现,本来没有关系的两个界面硬生生写在一个activity下不是我想要的。
下载链接在文末!!!

先看下效果吧,看是不是你想要的,背景大白,您可以设置你想要的默认背景。
这里写图片描述

实现思路思考

1.本来打算用系统提供的overridePendingTransition方法实现跳转,可无奈试了N种方法后我放弃了,如果您有好的方式可以沟通一下。
2.采用网上一个Activity两个VIew或者Fragment实现,我主动放弃了,如果符合你的要求可以自行Google。当时也考虑到了5.0以后加入的转场动画,最终也不能实现。
3.那为什么我不能单独给两个Activity的根View设置3D翻转动画,一个从-90度到0度,另一个从-270到-360度。那么,我们怎么实现View的3D翻转呢?Rotate3dAnimation,他能很轻松的帮助我们3D翻转的效果。

先撸一撸大体功能怎么实现

Activity1:
首先,在第一个Activity中我们先实现根View的翻转工作,在翻转结束后再实现界面的Intent跳转,我用Handler来实现这部分操作。看一下代码:我们首先得到屏幕的宽和高,然后确定中心翻转位置。

  val screenBounds = ScreenUtils.getScreenBounds(this)
        mWidth = screenBounds[0]
        mHeight = screenBounds[1]
        main_layout.setOnClickListener(View.OnClickListener {
            ll = findViewById<View>(R.id.main_layout)
            val animationSet = AnimationSet(true)
            val depthZ = 450f
            rotate3dAnimationX = Rotate3dAnimation()
            rotate3dAnimationX?.Rotate3dAnimation(0F, -90F, mWidth/2.0F, mHeight/2.0F, depthZ, true)
            animationSet.addAnimation(rotate3dAnimationX)
            animationSet.duration = 250
            animationSet.fillAfter = true
            animationSet.interpolator = AccelerateDecelerateInterpolator()
            ll?.startAnimation(animationSet)
            val mMessage = Message.obtain()
            mMessage.what = 1001
            // 使用sendEmptyMessageDelayed延时1s后发送一条消息
            mHandler.sendEmptyMessageDelayed(MainActivity.MESSAGE_WHAT, 240)
        })



 private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            when (msg?.what) {
                MainActivity.MESSAGE_WHAT -> {
                    gotoIntent()
                }
                else -> {
                }
            }
        }
    }

大家可以看到,我动画执行的时间为250ms,但是我在240ms就用handler实现界面的跳转了,这也是在调试的时候遇到的一个小问题吧,稍后会说明。在第一个界面,我逆向旋转了90度。

Activity2:

相同的,在第二个Activity中,我把View执行了从-270度到-360度的翻转,也就是视觉上从底下翻上来的效果,简单的看下代码:

  private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            when (msg?.what) {
                Main2Activity.MESSAGE_WHAT -> {
                    val ll = findViewById<View>(R.id.main2_layout)
                    //在此处练习了下动画集合的用法  可直接使用rotate3dAnimationX动画
                    val animationSet = AnimationSet(true)
                    val depthZ = 450f
                    val rotate3dAnimationX = Rotate3dAnimation()
                    rotate3dAnimationX.Rotate3dAnimation(-270F, -360F, mWidth/2.0F, mHeight/2.0F, depthZ, false)
                    animationSet.addAnimation(rotate3dAnimationX)
                    animationSet.duration = 250
                    animationSet.fillAfter = true
                    animationSet.interpolator = AccelerateDecelerateInterpolator()
                    ll?.startAnimation(animationSet)
                }
                else -> {
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.activity_main2)
        val screenBounds = ScreenUtils.getScreenBounds(this)
        mWidth = screenBounds[0]
        mHeight = screenBounds[1]
        val mMessage = Message.obtain()
        mMessage.what = 1001
        // 使用sendEmptyMessageDelayed延时1s后发送一条消息
        mHandler.sendEmptyMessageDelayed(Main2Activity.MESSAGE_WHAT, 0)
    }

就这样就实现了吗?未免太过分了,还有很多坑。

实现过程中遇到的问题和解决方法

(如果您有好的解决方法,烦请告知)

Tim1:我去除了Activity默认的跳转效果,但是在衔接的地方还是有明显的卡顿效果。
通过查阅资料,即使我们取消了默认的跳转效果,但是他是两个Activity,在转换的过程还是有一定的切换效果呢?那么我们就给它设置一个效果呗,只不过没有任何动画。例如:

在跳转时设置无动画效果:

  private fun gotoIntent() {
        val intent = Intent(this, Main2Activity().javaClass)
        this.startActivity(intent)
        //写两个空动画 去除两个activity间明显的卡顿效果
        this.overridePendingTransition(R.anim.fade_in, R.anim.fade_in)
    }

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="1.0" android:toXDelta="1.0"
        android:fromYDelta="1.0" android:toYDelta="1.0"
        android:duration="0" />
</set>

Tim2:第一个Activity跳转后在返回界面消失:
返回后界面消失了,我的天!!!翻转后状态没返回来?才疏学浅,找了找也没发现有方法可以重置状态,只能这么办了,自己看吧,太low了,哎!

        //在界面执行此方法时 把界面恢复原来的状态  暂时没想到其他好的方法
    override fun onStop() {
        val animationSet = AnimationSet(true)
        rotate3dAnimationX?.Rotate3dAnimation(-90F, 0F, mWidth/2.0F, mHeight/2.0F, 0F, true)
        animationSet.duration = 0
        animationSet.addAnimation(rotate3dAnimationX)
        ll?.startAnimation(animationSet)
        super.onStop()
    }

Tim3:之前的问题,在第一个界面我为什么提前10秒钟开始跳转逻辑呢?

哈哈,其实我也不知道,在时间同步的情况下,我发现在两个Activity的衔接处,还是有一点点的衔接效果,思考了下,我如果让下一个Activity提前开始动画呢,会不会好一点,事实证明了我的想法,至少在视觉上很好了。

写在最后

跌跌撞撞,反正效果实现了,如果您也有这样的需求,欢迎探讨更好的实现方式!!!

PS:下载链接:https://download.csdn.net/download/say_from_wen/10664221
github:https://github.com/loveAndroidAndroid/android-study

2018-01-13 23:02:29 Sure_Min 阅读数 1993
  • 苹果iOS应用UI控件开发

    本视频是传智播客iOS学院精心录制的免费精华版UI基础视频,该视频特点在于较大程度保证了知识点的完整性,视频的起点都是针对有一定OC基础的同学

    14109 人正在学习 去看看 传智

这次还是带来一个Android仿Ios风格的控件。Ios里有个控件叫ActionSheet,就是那种从下往上弹出的选项卡,比如下面这个效果:

                                                                 

UI在设计效果图的时候,添加图片、选择性别之类的功能经常会这么设计,ios那边有个ActionSheet可以用,android这边就比较麻烦了(有时候会感叹ios的一些控件确实要比android封装得更彻底)于是就自己封装了一个,名字也叫ActionSheet。控件其实是很久以前写的,现在拿出来跟大家分享一下。话不多说,正片开始。


首先这个控件继承自Dialog,需要先定义一个style和弹入弹出的动画。首先在res目录下新建一个anim文件夹,并在这个文件夹下新建两个动画文件

actionsheet_in.xml和 actionsheet_out,xml,如下:

actionsheet_in.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromYDelta="100%"
    android:toYDelta="0" />

actionsheet_out.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="200"
    android:fromYDelta="0"
    android:toYDelta="100%" />

然后就定义一个style并绑定这两个动画。在styles文件先添加以下内容:

<style name="ActionSheetStyle" parent="@android:style/Theme.Dialog">
    <!-- 背景透明 -->
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <!-- 浮于Activity之上 -->
    <item name="android:windowIsFloating">true</item>
    <!-- 边框 -->
    <item name="android:windowFrame">@null</item>
    <!-- Dialog以外的区域模糊效果 -->
    <item name="android:backgroundDimEnabled">true</item>
    <!-- 无标题 -->
    <item name="android:windowNoTitle">true</item>
    <!-- 半透明 -->
    <item name="android:windowIsTranslucent">true</item>
    <!-- Dialog进入及退出动画 -->
    <item name="android:windowAnimationStyle">@style/ActionSheetAnimation</item>
</style>


<!-- ActionSheet进出动画 -->
<style name="ActionSheetAnimation" parent="@android:style/Animation.Dialog">
    <item name="android:windowEnterAnimation">@anim/actionsheet_in</item>
    <item name="android:windowExitAnimation">@anim/actionsheet_out</item>
</style>

然后是最麻烦的地方,定义背景资源文件,一共12个(没办法,好看是有代价的 >_<)。在drawable目录下创建以下12个资源文件:

dialog_bottom_up.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="10dp" />

</shape>
dialog_bottom_down.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />

    <corners
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="10dp" />

</shape>

dialog_bottom_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/dialog_bottom_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/dialog_bottom_down" android:state_pressed="true"></item>

</selector>

dialog_top_up.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />

</shape>

dialog_top_down.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />

    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />

</shape>
dialog_top_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/dialog_top_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/dialog_top_down" android:state_pressed="true"></item>

</selector>

dialog_white_up.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />

    <corners android:radius="10dp" />

</shape>

dialog_white_down.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />
    
</shape>

dialog_white_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/dialog_white_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/dialog_white_down" android:state_pressed="true"></item>

</selector>

layout_white_up.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3ffffff" />
    
</shape>

layout_white_down.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#e3eeeeee" />
    
</shape>

layout_white_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/layout_white_up" android:state_pressed="false"></item>
    <item android:drawable="@drawable/layout_white_down" android:state_pressed="true"></item>

</selector>

终于搞好了,好麻烦的说。接下来就可以上ActionDialog的本体了,如下:

ActionDialog.java:

public class ActionSheet extends Dialog {
    private Context context;

    private LinearLayout parentLayout;
    private TextView titleTextView;
    private ArrayList<Button> sheetList;
    private Button cancelButton;

    // 标题
    private String title;

    //就取消按钮文字
    private String cancel;

    // 选择项文字列表
    private ArrayList<String> sheetTextList;

    // 标题颜色
    private int titleTextColor;

    // 取消按钮文字颜色
    private int cancelTextColor;

    // 选择项文字颜色
    private int sheetTextColor;

    // 标题大小
    private int titleTextSize;

    // 取消按钮文字大小
    private int cancelTextSize;

    // 选择项文字大小
    private int sheetTextSize;

    // 标题栏高度
    private int titleHeight;

    // 取消按钮高度
    private int cancelHeight;

    // 选择项高度
    private int sheetHeight;

    // 弹出框距离底部的高度
    private int marginBottom;

    // 取消按钮点击回调
    private View.OnClickListener cancelListener;

    // 选择项点击回调列表
    private ArrayList<View.OnClickListener> sheetListenerList;

    public ActionSheet(Context context) {
        super(context, R.style.ActionSheetStyle);
        init(context);
    }

    public ActionSheet(Context context, int theme) {
        super(context, theme);
        init(context);
    }

    private void init(Context context) {
        this.context = context;

        cancel = "取消";
        titleTextColor = Color.parseColor("#aaaaaa");
        cancelTextColor = Color.parseColor("#666666");
        sheetTextColor = Color.parseColor("#666666");
        titleTextSize = 14;
        cancelTextSize = 16;
        sheetTextSize = 16;
        titleHeight = dp2px(40);
        cancelHeight = dp2px(40);
        sheetHeight = dp2px(40);
        marginBottom = dp2px(10);

        sheetList = new ArrayList<>();
        sheetTextList = new ArrayList<>();
        sheetListenerList = new ArrayList<>();
    }

    private ActionSheet createDialog() {
        parentLayout = new LinearLayout(context);
        parentLayout.setBackgroundColor(Color.parseColor("#00000000"));
        parentLayout.setOrientation(LinearLayout.VERTICAL);

        if (title != null) {
            titleTextView = new TextView(context);
            titleTextView.setGravity(Gravity.CENTER);
            titleTextView.setText(title);
            titleTextView.setTextColor(titleTextColor);
            titleTextView.setTextSize(titleTextSize);
            titleTextView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_top_up));
            LinearLayout.LayoutParams titleLayoutParams = new LinearLayout.LayoutParams
                    (ViewGroup.LayoutParams.MATCH_PARENT, titleHeight);
            parentLayout.addView(titleTextView, titleLayoutParams);
        }
        for (int i = 0; i < sheetTextList.size(); i++) {
            if (i == 0 && title != null) {
                View topDividerLine = new View(context);
                topDividerLine.setBackgroundColor(Color.parseColor("#eeeeee"));
                parentLayout.addView(topDividerLine, new LinearLayout
                        .LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp2px(1)));
            }

            Button button = new Button(context);
            button.setGravity(Gravity.CENTER);
            button.setText(sheetTextList.get(i));
            button.setTextColor(sheetTextColor);
            button.setTextSize(sheetTextSize);
            if (title != null) {
                if (i == sheetTextList.size() - 1) {
                    button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_bottom_selector));
                } else {
                    button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.layout_white_selector));
                }
            } else {
                if (sheetTextList.size() == 1) {
                    button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_white_selector));
                } else {
                    if (i == 0) {
                        button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_top_selector));
                    } else if (i == sheetTextList.size() - 1) {
                        button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_bottom_selector));
                    } else {
                        button.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.layout_white_selector));
                    }
                }
            }
            button.setOnClickListener(sheetListenerList.get(i));
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
                    (ViewGroup.LayoutParams.MATCH_PARENT, sheetHeight);
            parentLayout.addView(button, layoutParams);
            sheetList.add(button);

            if (i != sheetTextList.size() - 1) {
                View bottomDividerLine = new View(context);
                bottomDividerLine.setBackgroundColor(Color.parseColor("#eeeeee"));
                parentLayout.addView(bottomDividerLine, new LinearLayout
                        .LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp2px(1)));
            }
        }

        cancelButton = new Button(context);
        cancelButton.setGravity(Gravity.CENTER);
        cancelButton.setText(cancel);
        cancelButton.setTextColor(cancelTextColor);
        cancelButton.setTextSize(cancelTextSize);
        cancelButton.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.dialog_white_selector));
        cancelButton.setOnClickListener(cancelListener);
        LinearLayout.LayoutParams cancelParams = new LinearLayout.LayoutParams
                (ViewGroup.LayoutParams.MATCH_PARENT, cancelHeight);
        cancelParams.setMargins(0, dp2px(10), 0, 0);
        parentLayout.addView(cancelButton, cancelParams);

        getWindow().setGravity(Gravity.BOTTOM);
        getWindow().getAttributes().y = marginBottom;
        show();
        setContentView(parentLayout);
        setCancelable(true);
        setCanceledOnTouchOutside(true);

        return this;
    }

    private void addSheet(String text, View.OnClickListener listener) {
        sheetTextList.add(text);
        sheetListenerList.add(listener);
    }

    public void setCancel(String text) {
        this.cancel = text;
    }

    public void setCancelHeight(int height) {
        this.cancelHeight = dp2px(height);
    }

    public void setCancelTextColor(int color) {
        this.cancelTextColor = color;
    }

    public void setCancelTextSize(int textSize) {
        this.cancelTextSize = textSize;
    }

    public void setSheetHeight(int height) {
        this.sheetHeight = dp2px(height);
    }

    public void setSheetTextColor(int color) {
        this.sheetTextColor = color;
    }

    public void setSheetTextSize(int textSize) {
        this.sheetTextSize = textSize;
    }

    public void setTitle(String text) {
        this.title = text;
    }

    public void setTitleHeight(int height) {
        this.titleHeight = height;
    }

    public void setTitleTextColor(int color) {
        this.titleTextColor = color;
    }

    public void setTitleTextSize(int textSize) {
        this.titleTextSize = textSize;
    }

    public void setMargin(int bottom) {
        this.marginBottom = dp2px(bottom);
    }

    public void addCancelListener(View.OnClickListener listener) {
        this.cancelListener = listener;
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    public static class DialogBuilder {
        ActionSheet dialog;

        public DialogBuilder(Context context) {
            dialog = new ActionSheet(context);
        }

        /**
         * 添加一个选择项
         * @param text 选择项文字
         * @param listener 选择项点击回调监听
         * @return 当前DialogBuilder
         */
        public DialogBuilder addSheet(String text, View.OnClickListener listener) {
            dialog.addSheet(text, listener);
            return this;
        }

        /**
         * 设置取消按钮文字
         * @param text 文字内容
         * @return 当前DialogBuilder
         */
        public DialogBuilder setCancel(String text) {
            dialog.setCancel(text);
            return this;
        }

        /**
         * 设置取消按钮高度
         * @param height 高度值,单位dp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setCancelHeight(int height) {
            dialog.setCancelHeight(height);
            return this;
        }

        /**
         * 设置取消按钮文字颜色
         * @param color 颜色值
         * @return 当前DialogBuilder
         */
        public DialogBuilder setCancelTextColor(int color) {
            dialog.setCancelTextColor(color);
            return this;
        }

        /**
         * 设置取消按钮文字大小
         * @param textSize 大小值,单位sp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setCancelTextSize(int textSize) {
            dialog.setCancelTextSize(textSize);
            return this;
        }

        /**
         * 设置选择项高度
         * @param height 高度值,单位dp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setSheetHeight(int height) {
            dialog.setSheetHeight(height);
            return this;
        }

        /**
         * 设置选择项文字颜色
         * @param color 颜色值
         * @return 当前DialogBuilder
         */
        public DialogBuilder setSheetTextColor(int color) {
            dialog.setSheetTextColor(color);
            return this;
        }

        /**
         * 设置选择项文字大小
         * @param textSize 大小值,单位sp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setSheetTextSize(int textSize) {
            dialog.setSheetTextSize(textSize);
            return this;
        }

        /**
         * 设置标题
         * @param text 文字内容
         * @return 当前DialogBuilder
         */
        public DialogBuilder setTitle(String text) {
            dialog.setTitle(text);
            return this;
        }

        /**
         * 设置标题栏高度
         * @param height 高度值,单位dp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setTitleHeight(int height) {
            dialog.setTitleHeight(height);
            return this;
        }

        /**
         * 设置标题颜色
         * @param color 颜色值
         * @return 当前DialogBuilder
         */
        public DialogBuilder setTitleTextColor(int color) {
            dialog.setTitleTextColor(color);
            return this;
        }

        /**
         * 设置标题大小
         * @param textSize 大小值,单位sp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setTitleTextSize(int textSize) {
            dialog.setTitleTextSize(textSize);
            return this;
        }

        /**
         * 设置弹出框距离底部的高度
         * @param bottom 距离值,单位dp
         * @return 当前DialogBuilder
         */
        public DialogBuilder setMargin(int bottom) {
            dialog.setMargin(bottom);
            return this;
        }

        /**
         * 设置取消按钮的点击回调
         * @param listener 回调监听
         * @return
         */
        public DialogBuilder addCancelListener(View.OnClickListener listener) {
            dialog.addCancelListener(listener);
            return this;
        }

        /**
         * 创建弹出框,放在最后执行
         * @return 创建的 ActionSheet 实体
         */
        public ActionSheet create() {
            return dialog.createDialog();
        }
    }
}

稍微说一下,依然是建造者模式的写法,内部类DialogBuilder是一个建造器,调用的时候通过新建一个DialogBuilder实体,设置好想要的参数,最后调用其create方法就建造完成了。
 
最后的最后,终于可以用了!MainActivity.class和activity_main.xml贴上:
MainActivity.class:
public class MainActivity extends Activity {
    private Button button;

    private ActionSheet actionSheet;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initData() {

    }

    private void initView() {
        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showSheet();
            }
        });
    }

    private void showSheet() {
        actionSheet=new ActionSheet.DialogBuilder(this)
                .addSheet("雷军", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "当然是雷布斯!", Toast.LENGTH_SHORT).show();
                        actionSheet.dismiss();
                    }
                })
                .addSheet("马化腾", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "当然是小马哥!", Toast.LENGTH_SHORT).show();
                        actionSheet.dismiss();
                    }
                })
                .addSheet("马云", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "当然是马爸爸!", Toast.LENGTH_SHORT).show();
                        actionSheet.dismiss();
                    }
                })
                .addCancelListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this, "容我三思", Toast.LENGTH_SHORT).show();
                        actionSheet.dismiss();
                    }
                })
                .create();
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="SHOW SHEET" />

</LinearLayout>

简单的说一下,调用方法之前已经说了,其中addSheet方法每调用一次就会添加一条选线栏,需要输入选项栏文字,和点击的回调监听,这里监听直接用的是View下的OnClickListener,是不是很亲切?顺带一提,取消按钮是默认存在的,所以务必设置一下addCancelListener,不然点击取消会没反应。

来看一下效果,运行走起! 

                                                                 

控件支持添加标题栏,改变文字大小、颜色什么的,几行代码搞定,如下:

actionSheet=new ActionSheet.DialogBuilder(this)
        ...

        .setTitle("你觉得以下谁最帅?")
        .setCancel("容我三思")
        .setTitleTextColor(Color.parseColor("#ff69b4"))
        .setCancelTextColor(Color.parseColor("#aaaaaa"))
        .setSheetTextColor(Color.parseColor("#1e90ff"))
        
        ...
        .create();

再次运行,看一下效果:

                                                                

是不是很简单?更多设置选项在控件源码里都已经注释清楚了,大家可以自己试一试。


总结一下控件的用法就是:new一个DialogBulder,根据需要set一堆东西有几个选项卡就调用几次addSheet,最后create一下,搞定。


最后附上源码地址:点击打开链接


这次的内容就到这里,我们下次再见。








没有更多推荐了,返回首页