几个现有控件,组合起来,达到使用的目的。初始化时,新布局填充到控件上。
组合控件定义一个密码输入框,右侧可以点击图标,来切换密码是显示或隐藏。
布局文件:由editText和img组成。
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="60dp"
tools:context="com.example.yijian.testanination.MainActivity">
android:hint="请输入密码"
android:singleLine="true"
android:maxLength="50"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"/>
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
>
android:background="@drawable/gy_password_eye_off"
android:clickable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
定义控件类继承RelativeLayout
public class MyTextView extends RelativeLayout { private RelativeLayout layout = null; private EditText mEtPassword; private RelativeLayout mLlRightPic; public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MyTextView(Context context) { super(context); init(context); } /** * 初始化 * @param context */ private void init(Context context) { if (layout == null) layout = (RelativeLayout) ((LayoutInflater) (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))). inflate(R.layout.my_textview,this); mEtPassword = (EditText) layout.findViewById(R.id.et_password); mLlRightPic = (RelativeLayout) layout.findViewById(R.id.gy_rl_edittext_right); mLlRightPic.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //右侧图标点击时,切换 显示密码和隐藏密码的设置 } }); } public String getText(){ //返回用户输入的密码 return mEtPassword.getEditableText().toString(); } }
代码中使用:当做正常控件来使用。
android:layout_width="match_parent"
android:layout_height="60dp">
有些情况下直接继承现有控件,也十分方便。
这种情况要求,对要继承的类较为熟悉。
比如防止Button控件连续点击,可以重写button
/** * Created by gj on 2016/5/11. * 统一按钮 */ public class GyButton extends Button { public GyButton(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public GyButton(Context context) { super(context); init(context); } //button_selecter private void init(Context context) { setBackgroundDrawable(getResources().getDrawable(R.drawable.button)); setTextSize(16); setTextColor(context.getResources().getColor(R.color.textcolor_on_up_widget)); } @Override public boolean performClick() { if(DataTimeUtil.buttonIsDoubleClick()){ return false; }else{ return super.performClick(); } } }
ViewPager添加小圆点指示器
onDraw中去绘制圆点。getAdapter能拿到适配器。getCount可以拿到元素的数量。getCurrentItem当前索引。
这样就可以自动的设置指示器。
/** * Created by gj on 2017/2/8. */ public class IndicatorViewPager extends ViewPager{ Context context; Paint paint; List
实现文字的垂直滚动效果。
继承TextSwitcher(文字转换器)。即可正常设置文字。
/** * 自动垂直滚动的TextView */ public class VerticalScrollTextView extends TextSwitcher implements ViewSwitcher.ViewFactory { private Context mContext; //mInUp,mOutUp分别构成向下翻页的进出动画 private Animation mInAnimation; private Animation mOutAnimation; public VerticalScrollTextView(Context context) { this(context, null); } public VerticalScrollTextView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; init(); } private void init() { //设置TextView的产生,会调用ViewFactory.makeView() setFactory(this); //设置出入动画 mInAnimation = AnimationUtils.loadAnimation(mContext, R.anim.vertical_in); mOutAnimation = AnimationUtils.loadAnimation(mContext, R.anim.vertical_out); setInAnimation(mInAnimation); setOutAnimation(mOutAnimation); } //这里返回的TextView,就是我们看到的View,可以设置自己想要的效果 @Override public View makeView() { TextView textView = new TextView(mContext); textView.setTextSize(36); // textView.setSingleLine(true); // textView.setGravity(Gravity.CENTER_VERTICAL); return textView; } }
动画vertical_in
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" > android:duration="1000" android:fromYDelta="100%p" android:toYDelta="0%p" />
verrical_out
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" > android:duration="1000" android:fromYDelta="0%p" android:toYDelta="-100%p" />
Values/attrs.xml
xml version="1.0" encoding="utf-8"?>
CustomerView继承成View类
构造方法走三个参数的。
public CustomerView(Context context) { this(context,null); } public CustomerView(Context context, AttributeSet attrs) { this(context, attrs,0); }
public CustomerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTxtView, defStyleAttr, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CustomTxtView_text: this.text = a.getString(attr); break; case R.styleable.CustomTxtView_textSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); mBound = new Rect(); mPaint.getTextBounds(text, 0, text.length(), mBound); }
实现onDraw、onMeasure
@Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.YELLOW); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(Color.BLACK); canvas.drawText(text, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); } // 先了解MeasureSpec的specMode,一共三种类型: // EXACTLY:一般是设置了明确的值或者是MATCH_PARENT // AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT // UNSPECIFIED:表示子布局想要多大就多大,很少使用 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height ; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(text, 0, text.length(), mBound); float textWidth = mBound.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(text, 0, text.length(), mBound); float textHeight = mBound.height(); int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom()); height = desired; } setMeasuredDimension(width, height); }
在布局中使用(需要添加约束)
xmlns:customtext="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
customtext:text="12378"
customtext:textSize="16sp"
/>