一步一步走向自定义控件
2017-04-01 10:08
141 查看
上个月搭配了自己的开发环境。
有了自己的环境=有了环境想搞事情。
然后这个月就想搞搞事情了。
自定义控件确实很强大,看到灵机上的OppositeLayout不禁深深钦佩。
其实一直想自定义控件,但是到底怎么自定义的呢,需要怎么样去学呢?我也不怎么晓得。
我比较笨–>我的想法是一步一步慢慢探索,摸着石头过河。–>会用别人定义的–>看懂别人的代码–>模仿着来写–>写自己的
大神博客
自定义dialog
BaseDialog
ChildrenDialog
关键代码
Animation
核心代码
Dialog
自定义TextView
自定义Button
StateButton
神一样的控件自定义FrameLayout
自定义View
总结
正常来说我们可以先写一个BaseDialog
BaseDialog:身为一个dialog的爸爸应该怎么去写?我的话开始的时候写得不多,感觉不需要写太多–>先写孩纸,然后把孩纸的共同点交给爸爸。爸爸是有很多共同点的存在,而孩纸是青出于蓝而胜于蓝的存在。
R.style.dialogWindowAnim:这个就是动画效果。先讲完dialog的,动画等等再说。
在项目里,我们有各种各样的dialog
而且根据需求会写各种各样的dialog,那我们就写呗
列举一下项目中我们都有用到的dialog
LoadingDialog
GetPhotoDialog
TipsDialog
PayDialog
PermissionDialog
ExitDialog
DownloadDialog
等等
然后自己想干嘛干嘛。哈。哈。
怎么加入自己想要的动画呢?
这个开始我也不大会,然后就找别人的代码啊。
https://github.com/gepriniusce/NiftyDialogEffects
https://github.com/gepriniusce/NiftyNotification
其实原理很简单,dialog有一个OnShowListener,然后再start动画!
直接看代码吧–>
核心代码
https://github.com/niniloveyou/StateButton
先看懂大神代码吧–>
values中的attrs –>自定义属性
获取attrs属性
利用这些属性与GradientDrawable对控件的属性做设置
真的写得不错的代码,觉得很值得我学习
好强大,也是看懂代码先,然后一步一步学习,代码看多了,敲多了就会自己写了嘛。
代码不晓得贴不贴不出来好[捂脸]。
以上的算是自定义控件的一个入门吧。
大神博客
更详细的入门教程。
先睡觉,以后再补充
有了自己的环境=有了环境想搞事情。
然后这个月就想搞搞事情了。
自定义控件确实很强大,看到灵机上的OppositeLayout不禁深深钦佩。
其实一直想自定义控件,但是到底怎么自定义的呢,需要怎么样去学呢?我也不怎么晓得。
我比较笨–>我的想法是一步一步慢慢探索,摸着石头过河。–>会用别人定义的–>看懂别人的代码–>模仿着来写–>写自己的
大神博客
自定义dialog
BaseDialog
ChildrenDialog
关键代码
Animation
核心代码
Dialog
自定义TextView
自定义Button
StateButton
神一样的控件自定义FrameLayout
自定义View
总结
自定义dialog
这个自定义dialog的灵感来自于加载动画–>正常来说我们可以先写一个BaseDialog
BaseDialog
/** * <b>Project:</b> ${file_name}<br> * <b>Create Date:</b> 2017/3/18<br> * <b>Author:</b> Tongson<br> * <b>Description:</b> Tongson's Dialog的爸爸 <br> */ public abstract class TongsonBaseDialog extends Dialog { private Context mContext; public TongsonBaseDialog(Context context) { super(context, R.style.TongsonBaseDialogStyle); mContext = context; initEnterExitAnim(); } public TongsonBaseDialog(Context context, int theme) { super(context, theme); mContext = context; initEnterExitAnim(); } /** * 进场动画 */ public void initEnterExitAnim() { Window dialogWindow = getWindow(); dialogWindow.setGravity(Gravity.CENTER); // 此处可以设置dialog显示的位置为居中 dialogWindow.setWindowAnimations(R.style.dialogWindowAnim);// 添加动画效果 int widthPixels; int heightPixels; WindowManager.LayoutParams layoutParams = dialogWindow.getAttributes(); DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); widthPixels = dm.widthPixels; heightPixels = dm.heightPixels; layoutParams.height = heightPixels; layoutParams.width = widthPixels; dialogWindow.setAttributes(layoutParams); } }
BaseDialog:身为一个dialog的爸爸应该怎么去写?我的话开始的时候写得不多,感觉不需要写太多–>先写孩纸,然后把孩纸的共同点交给爸爸。爸爸是有很多共同点的存在,而孩纸是青出于蓝而胜于蓝的存在。
R.style.dialogWindowAnim:这个就是动画效果。先讲完dialog的,动画等等再说。
ChildrenDialog
然后我们来看看这个孩纸的dialog怎么去写呢?在项目里,我们有各种各样的dialog
而且根据需求会写各种各样的dialog,那我们就写呗
列举一下项目中我们都有用到的dialog
LoadingDialog
GetPhotoDialog
TipsDialog
PayDialog
PermissionDialog
ExitDialog
DownloadDialog
等等
关键代码
setContentView(R.layout.dialog_layout);
然后自己想干嘛干嘛。哈。哈。
Animation
感觉是很重要的,Dialog飞来飞去的炫酷感会使用户飞。怎么加入自己想要的动画呢?
这个开始我也不大会,然后就找别人的代码啊。
https://github.com/gepriniusce/NiftyDialogEffects
https://github.com/gepriniusce/NiftyNotification
核心代码
this.setOnShowListener(new OnShowListener() { @Override public void onShow(DialogInterface dialogInterface) { mLinearLayoutView.setVisibility(View.VISIBLE); if (type == null) { type = Effectstype.Slidetop; } start(type); } });
private void start(Effectstype type) { BaseEffects animator = type.getAnimator(); if (mDuration != -1) { animator.setDuration(Math.abs(mDuration)); } animator.start(mRelativeLayoutView); }
其实原理很简单,dialog有一个OnShowListener,然后再start动画!
Dialog
其实自定义Dialog的话,还是要多看看Dialog这个类的代码,我们重写一下方法就行了是不是好简单!?自定义TextView
对于自定义的TextView感觉比较有用的是setTypeface(加载自己的字体库)直接看代码吧–>
/** * <b>Project:</b> ${file_name}<br> * <b>Create Date:</b> 2017/4/4<br> * <b>Author:</b> Tongson<br> * <b>Description:</b> 自定义字体库TextView <br> */ public class TongsonTextView extends TextView { public static Typeface myTypeface; public TongsonTextView(Context context) { super(context); setTTFstyle(); } public TongsonTextView(Context context, AttributeSet attrs) { super(context, attrs); setTTFstyle(); } public TongsonTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setTTFstyle(); } private void setTTFstyle() { Typeface typeface= getTtf(); if (null != typeface) { setTypeface(typeface); } } /** * 加载字体库 * <p> * 此处应该在Application中 * * @param context */ public static void loadTtf(Context context) { Typeface fontFace = null; try { fontFace = Typeface.createFromAsset(context.getAssets(), "fonts/msyhl.ttc"); } catch (RuntimeException e) { e.printStackTrace(); } if (fontFace != null) { myTypeface = fontFace; } } /** * 获取字体 * * @return */ private Typeface getTtf() { return myTypeface; } }
核心代码
setTypeface(typeface);
自定义Button
Button的话个人比较喜欢StateButtonhttps://github.com/niniloveyou/StateButton
先看懂大神代码吧–>
values中的attrs –>自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> </declare-styleable> <declare-styleable name="StateButton"> <attr name="xxx" format="xxx|reference"/> </declare-styleable> </resources>
获取attrs属性
利用这些属性与GradientDrawable对控件的属性做设置
真的写得不错的代码,觉得很值得我学习
StateButton
public class StateButton extends AppCompatButton { //text color private int mNormalTextColor = 0; private int mPressedTextColor = 0; private int mUnableTextColor = 0; ColorStateList mTextColorStateList; //animation duration private int mDuration = 0; //radius private float mRadius = 0; private boolean mRound; //stroke private float mStrokeDashWidth = 0; private float mStrokeDashGap = 0; private int mNormalStrokeWidth = 0; private int mPressedStrokeWidth = 0; private int mUnableStrokeWidth = 0; private int mNormalStrokeColor = 0; private int mPressedStrokeColor = 0; private int mUnableStrokeColor = 0; //background color private int mNormalBackgroundColor = 0; private int mPressedBackgroundColor = 0; private int mUnableBackgroundColor = 0; private GradientDrawable mNormalBackground; private GradientDrawable mPressedBackground; private GradientDrawable mUnableBackground; private int[][] states; StateListDrawable mStateBackground; public StateButton(Context context) { this(context, null); } public StateButton(Context context, AttributeSet attrs) { this(context, attrs, android.support.v7.appcompat.R.attr.buttonStyle); } public StateButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setup(attrs); } private void setup(AttributeSet attrs) { states = new int[4][]; Drawable drawable = getBackground(); if(drawable != null && drawable instanceof StateListDrawable){ mStateBackground = (StateListDrawable) drawable; }else{ mStateBackground = new StateListDrawable(); } mNormalBackground = new GradientDrawable(); mPressedBackground = new GradientDrawable(); mUnableBackground = new GradientDrawable(); //pressed, focused, normal, unable states[0] = new int[] { android.R.attr.state_enabled, android.R.attr.state_pressed }; states[1] = new int[] { android.R.attr.state_enabled, android.R.attr.state_focused }; states[3] = new int[] { -android.R.attr.state_enabled}; states[2] = new int[] { android.R.attr.state_enabled }; TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.StateButton); //get original text color as default //set text color mTextColorStateList = getTextColors(); int mDefaultNormalTextColor = mTextColorStateList.getColorForState(states[2], getCurrentTextColor()); int mDefaultPressedTextColor = mTextColorStateList.getColorForState(states[0], getCurrentTextColor()); int mDefaultUnableTextColor = mTextColorStateList.getColorForState(states[3], getCurrentTextColor()); mNormalTextColor = a.getColor(R.styleable.StateButton_normalTextColor, mDefaultNormalTextColor); mPressedTextColor = a.getColor(R.styleable.StateButton_pressedTextColor, mDefaultPressedTextColor); mUnableTextColor = a.getColor(R.styleable.StateButton_unableTextColor, mDefaultUnableTextColor); setTextColor(); //set animation duration mDuration = a.getInteger(R.styleable.StateButton_animationDuration, mDuration); mStateBackground.setEnterFadeDuration(mDuration); mStateBackground.setExitFadeDuration(mDuration); //set background color mNormalBackgroundColor = a.getColor(R.styleable.StateButton_normalBackgroundColor, 0); mPressedBackgroundColor = a.getColor(R.styleable.StateButton_pressedBackgroundColor, 0); mUnableBackgroundColor = a.getColor(R.styleable.StateButton_unableBackgroundColor, 0); mNormalBackground.setColor(mNormalBackgroundColor); mPressedBackground.setColor(mPressedBackgroundColor); mUnableBackground.setColor(mUnableBackgroundColor); //set radius mRadius = a.getDimensionPixelSize(R.styleable.StateButton_radius, 0); mRound = a.getBoolean(R.styleable.StateButton_round, false); mNormalBackground.setCornerRadius(mRadius); mPressedBackground.setCornerRadius(mRadius); mUnableBackground.setCornerRadius(mRadius); //set stroke mStrokeDashWidth = a.getDimensionPixelSize(R.styleable.StateButton_strokeDashWidth, 0); mStrokeDashGap = a.getDimensionPixelSize(R.styleable.StateButton_strokeDashWidth, 0); mNormalStrokeWidth = a.getDimensionPixelSize(R.styleable.StateButton_normalStrokeWidth, 0); mPressedStrokeWidth = a.getDimensionPixelSize(R.styleable.StateButton_pressedStrokeWidth, 0); mUnableStrokeWidth = a.getDimensionPixelSize(R.styleable.StateButton_unableStrokeWidth, 0); mNormalStrokeColor = a.getColor(R.styleable.StateButton_normalStrokeColor, 0); mPressedStrokeColor = a.getColor(R.styleable.StateButton_pressedStrokeColor, 0); mUnableStrokeColor = a.getColor(R.styleable.StateButton_unableStrokeColor, 0); setStroke(); //set background mStateBackground.addState(states[0], mPressedBackground); mStateBackground.addState(states[1], mPressedBackground); mStateBackground.addState(states[3], mUnableBackground); mStateBackground.addState(states[2], mNormalBackground); setBackgroundDrawable(mStateBackground); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setRound(mRound); } /****************** stroke color *********************/ public void setNormalStrokeColor(@ColorInt int normalStrokeColor) { this.mNormalStrokeColor = normalStrokeColor; setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth); } public void setPressedStrokeColor(@ColorInt int pressedStrokeColor) { this.mPressedStrokeColor = pressedStrokeColor; setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth); } public void setUnableStrokeColor(@ColorInt int unableStrokeColor) { this.mUnableStrokeColor = unableStrokeColor; setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth); } public void setStateStrokeColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable){ mNormalStrokeColor = normal; mPressedStrokeColor = pressed; mUnableStrokeColor = unable; setStroke(); } /****************** stroke width *********************/ public void setNormalStrokeWidth(int normalStrokeWidth) { this.mNormalStrokeWidth = normalStrokeWidth; setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth); } public void setPressedStrokeWidth(int pressedStrokeWidth) { this.mPressedStrokeWidth = pressedStrokeWidth; setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth); } public void setUnableStrokeWidth(int unableStrokeWidth) { this.mUnableStrokeWidth = unableStrokeWidth; setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth); } public void setStateStrokeWidth(int normal, int pressed, int unable){ mNormalStrokeWidth = normal; mPressedStrokeWidth = pressed; mUnableStrokeWidth= unable; setStroke(); } public void setStrokeDash(float strokeDashWidth, float strokeDashGap) { this.mStrokeDashWidth = strokeDashWidth; this.mStrokeDashGap = strokeDashWidth; setStroke(); } private void setStroke(){ setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth); setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth); setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth); } private void setStroke(GradientDrawable mBackground, int mStrokeColor, int mStrokeWidth) { mBackground.setStroke(mStrokeWidth, mStrokeColor, mStrokeDashWidth, mStrokeDashGap); } /******************** radius *******************************/ public void setRadius(@FloatRange(from = 0) float radius) { this.mRadius = radius; mNormalBackground.setCornerRadius(mRadius); mPressedBackground.setCornerRadius(mRadius); mUnableBackground.setCornerRadius(mRadius); } public void setRound(boolean round){ this.mRound = round; int height = getMeasuredHeight(); if(mRound){ setRadius(height / 2f); } } public void setRadius(float[] radii){ mNormalBackground.setCornerRadii(radii); mPressedBackground.setCornerRadii(radii); mUnableBackground.setCornerRadii(radii); } /******************** background color **********************/ public void setStateBackgroundColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable){ mPressedBackgroundColor = normal; mNormalBackgroundColor = pressed; mUnableBackgroundColor = unable; mNormalBackground.setColor(mNormalBackgroundColor); mPressedBackground.setColor(mPressedBackgroundColor); mUnableBackground.setColor(mUnableBackgroundColor); } public void setNormalBackgroundColor(@ColorInt int normalBackgroundColor) { this.mNormalBackgroundColor = normalBackgroundColor; mNormalBackground.setColor(mNormalBackgroundColor); } public void setPressedBackgroundColor(@ColorInt int pressedBackgroundColor) { this.mPressedBackgroundColor = pressedBackgroundColor; mPressedBackground.setColor(mPressedBackgroundColor); } public void setUnableBackgroundColor(@ColorInt int unableBackgroundColor) { this.mUnableBackgroundColor = unableBackgroundColor; mUnableBackground.setColor(mUnableBackgroundColor); } /*******************alpha animation duration********************/ public void setAnimationDuration(@IntRange(from = 0)int duration){ this.mDuration = duration; mStateBackground.setEnterFadeDuration(mDuration); } /*************** text color ***********************/ private void setTextColor() { int[] colors = new int[] {mPressedTextColor, mPressedTextColor, mNormalTextColor, mUnableTextColor}; mTextColorStateList = new ColorStateList(states, colors); setTextColor(mTextColorStateList); } public void setStateTextColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable){ this.mNormalTextColor = normal; this.mPressedTextColor = pressed; this.mUnableTextColor = unable; setTextColor(); } public void setNormalTextColor(@ColorInt int normalTextColor) { this.mNormalTextColor = normalTextColor; setTextColor(); } public void setPressedTextColor(@ColorInt int pressedTextColor) { this.mPressedTextColor = pressedTextColor; setTextColor(); } public void setUnableTextColor(@ColorInt int unableTextColor) { this.mUnableTextColor = unableTextColor; setTextColor(); } }
神一样的控件自定义FrameLayout
这个就是公司的OppositeLayout好强大,也是看懂代码先,然后一步一步学习,代码看多了,敲多了就会自己写了嘛。
代码不晓得贴不贴不出来好[捂脸]。
以上的算是自定义控件的一个入门吧。
自定义View
回过头来,我们可以再看看大神的博客大神博客
更详细的入门教程。
总结
如果想真正弄明白怎样自定义View,绘制各种View,还是要先把基础搞好,参考优秀代码,多敲大神demo,学着写,自己写。先睡觉,以后再补充
相关文章推荐
- 一步一步实现自定义控件(二)
- 一步一步实现自定义控件(四)
- 人类正在一步一步的走向作茧自缚 (2)
- 人类正在一步一步的走向作茧自缚(3)
- C#自定义控件一步一步走
- 人类正在一步一步的走向作茧自缚(4)
- 这8个原因,让我们一步一步走向平庸
- 分享我这8年(目前在阿里就职),是如何一步一步走向架构师的
- 人类正在一步一步的走向作茧自缚(6)
- 一步一步实现自定义控件(三)
- 这8个原因,让我们一步一步走向平庸
- 我是如何从程序员一步一步走向产品经理
- 一步一步实现自定义控件(一)
- 一步一步定制自己的google map(预备知识)
- 【Asp.net之旅】--因自定义控件注册而引发的思考
- 走向面试之数据库基础:一、你必知必会的SQL语句练习-Part 1
- 一步一步学习Git(2)——Git基本操作
- 自定义控件-MultipleTextView(自动换行、自动补齐宽度的排列多个TextView)
- 神州数码首席IT专家郑小维:走向云中新IT的两次大转身
- C# WinForm控件、自定义控件整理(大全)