diff --git a/app/src/main/java/com/chaychan/powerfulviewlibrary/MainActivity.java b/app/src/main/java/com/chaychan/powerfulviewlibrary/MainActivity.java index 1db162c8b80408ad5c61355936cddd9a1e307b9a..bb0ec00ac25d864b2253d79bd80309b05e38a5a0 100644 --- a/app/src/main/java/com/chaychan/powerfulviewlibrary/MainActivity.java +++ b/app/src/main/java/com/chaychan/powerfulviewlibrary/MainActivity.java @@ -3,9 +3,11 @@ package com.chaychan.powerfulviewlibrary; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; +import android.view.View; import android.widget.EditText; import android.widget.Toast; +import com.chaychan.viewlib.ExpandableLinearLayout; import com.chaychan.viewlib.PowerfulEditText; public class MainActivity extends AppCompatActivity { @@ -25,5 +27,17 @@ public class MainActivity extends AppCompatActivity { } } }); + + View view1 = View.inflate(this, R.layout.item_expandable_linear_layout, null); + View view2 = View.inflate(this, R.layout.item_expandable_linear_layout, null); + View view3 = View.inflate(this, R.layout.item_expandable_linear_layout, null); + View view4 = View.inflate(this, R.layout.item_expandable_linear_layout, null); + + ExpandableLinearLayout expandableLinearLayout = (ExpandableLinearLayout) findViewById(R.id.ell); + + expandableLinearLayout.addItem(view1); + expandableLinearLayout.addItem(view2); + expandableLinearLayout.addItem(view3); + expandableLinearLayout.addItem(view4); } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8504cbb0ff4fe103991724a212a50045bd0a7a87..38a7e32c180de751b4feee406d899085c229584a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -15,6 +15,17 @@ android:drawableRight="@mipmap/search" /> + + diff --git a/app/src/main/res/layout/item_expandable_linear_layout.xml b/app/src/main/res/layout/item_expandable_linear_layout.xml new file mode 100644 index 0000000000000000000000000000000000000000..270d9949bc6d6202980007f02e59af2a22bdfe3d --- /dev/null +++ b/app/src/main/res/layout/item_expandable_linear_layout.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 77ce66ea36eed3ec5c10abb7b2618ed4748e0081..df774b890c28ca3144c4d12637f85ece714e170d 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:2.1.3' - // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gradle.properties b/gradle.properties index 1d3591c8a4c9c29578c36c87f80c05a6aea3ee3f..3a45fdc62824d3d01329e42173285457cb13ff69 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,17 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - +## Project-wide Gradle settings. +# # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html - +# # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx10248m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - +# # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +#Fri Mar 31 10:17:35 CST 2017 +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=9666 diff --git a/viewlib/build.gradle b/viewlib/build.gradle index adda51417830529eb6d3e4361275ecacab437282..12769590d03c39b112a98faf5b7fb23cf1d50f9d 100644 --- a/viewlib/build.gradle +++ b/viewlib/build.gradle @@ -22,4 +22,5 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.1' + compile 'com.nineoldandroids:library:2.4.0' } diff --git a/viewlib/src/main/java/com/chaychan/viewlib/BankCardNumEditText.java b/viewlib/src/main/java/com/chaychan/viewlib/BankCardNumEditText.java new file mode 100644 index 0000000000000000000000000000000000000000..a7826e0f2d547aacb8260738770e251928d4717e --- /dev/null +++ b/viewlib/src/main/java/com/chaychan/viewlib/BankCardNumEditText.java @@ -0,0 +1,41 @@ +package com.chaychan.viewlib; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.EditText; + +/** + * 银行卡号输入框 + * + * @author Administrator + * + */ +public class BankCardNumEditText extends EditText { + + public BankCardNumEditText(Context context) { + super(context); + + this.addTextChangedListener(new NumberTextWatcher(this,' ')); + } + + public BankCardNumEditText(Context context, AttributeSet attrs) { + super(context, attrs); + + this.addTextChangedListener(new NumberTextWatcher(this,' ')); + } + + /** + * 获取真实的text(去掉空格) + * + * @return + */ + public String getTextWithoutSpace() { + String text = super.getText().toString(); + if (android.text.TextUtils.isEmpty(text)) { + return ""; + } else { + return text.replace(" ", ""); + } + } + +} \ No newline at end of file diff --git a/viewlib/src/main/java/com/chaychan/viewlib/ExpandableLinearLayout.java b/viewlib/src/main/java/com/chaychan/viewlib/ExpandableLinearLayout.java new file mode 100644 index 0000000000000000000000000000000000000000..d2f15530f315775c57a0f5d043faeb1c5d2f13e3 --- /dev/null +++ b/viewlib/src/main/java/com/chaychan/viewlib/ExpandableLinearLayout.java @@ -0,0 +1,216 @@ +package com.chaychan.viewlib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.nineoldandroids.animation.Animator; +import com.nineoldandroids.animation.ObjectAnimator; +import com.nineoldandroids.animation.ValueAnimator; + + +/** + * 可以展开的LinearLayout + */ +public class ExpandableLinearLayout extends FrameLayout implements View.OnClickListener { + + private LinearLayout llContainer; + private TextView tvTip; + + private boolean isExpand = false;//是否是展开状态,默认是隐藏 + + private int defaultItemCount;//一开始展示的条目数 + private String expandText;//展开时显示的文字 + private String hideText;//隐藏时显示的文字 + private ImageView ivArrow; + + public ExpandableLinearLayout(Context context) { + this(context, null); + } + + public ExpandableLinearLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ExpandableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandableLinearLayout); + defaultItemCount = ta.getInt(R.styleable.ExpandableLinearLayout_defaultItemCount, 0); + expandText = ta.getString(R.styleable.ExpandableLinearLayout_expandText); + hideText = ta.getString(R.styleable.ExpandableLinearLayout_hideText); + float fontSize = ta.getDimension(R.styleable.ExpandableLinearLayout_tipTextSize,UIUtils.sp2px(context,14)); + int textColor = ta.getColor(R.styleable.ExpandableLinearLayout_tipTextColor, Color.parseColor("#666666")); + ta.recycle(); + + + View rootView = View.inflate(context, R.layout.expandable_linearlayout, null); + llContainer = (LinearLayout) rootView.findViewById(R.id.ll_container); + RelativeLayout rlBottom = (RelativeLayout) rootView.findViewById(R.id.rl_bottom); + ivArrow = (ImageView) rootView.findViewById(R.id.iv_arrow); + + tvTip = (TextView) rootView.findViewById(R.id.tv_tip); + tvTip.getPaint().setTextSize(fontSize); + tvTip.setTextColor(textColor); + + rlBottom.setOnClickListener(this); + + addView(rootView); + } + + + public void addItem(View view) { + llContainer.addView(view); + refreshUI(); + } + + /** + * 刷新UI + */ + private void refreshUI() { + int childCount = llContainer.getChildCount(); + tvTip.setVisibility(childCount > defaultItemCount ? VISIBLE : GONE);//控制隐藏 + if (childCount > defaultItemCount) { + hide(false); + } + } + + /** + * 展开 + */ + private void expand() { + int childCount = llContainer.getChildCount(); + //如果含有条目数大于默认显示的条目数,则可以展开,改变linearLayout的高度 + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) llContainer.getLayoutParams(); + int height = 0; + for (int i = 0; i < childCount; i++) { + View view = llContainer.getChildAt(i); + + int viewWidth = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int viewHeight = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + + view.measure(viewWidth, viewHeight); + height += view.getMeasuredHeight(); + } + + doAnimation(params.height,height);//执行动画 + } + + /** + * 收起 + */ + private void hide(boolean withAnimation) { + //改变linearLayout的高度为defaultItemCount个条目的高度 + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) llContainer.getLayoutParams(); + int height = 0; + for (int i = 0; i < defaultItemCount; i++) { + View view = llContainer.getChildAt(i); + + int viewWidth = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + int viewHeight = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + + view.measure(viewWidth, viewHeight); + height += view.getMeasuredHeight(); + } + + if (withAnimation){ + doAnimation(params.height, height);//执行动画 + }else{ + params.height = height; + llContainer.setLayoutParams(params); + } + } + + + private void doAnimation(int start, int end) { + ValueAnimator animator = ValueAnimator.ofInt(start, end);// 由初始值向结束值变化 + animator.setDuration(300);// 设置周期 + + // 设置监听 + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + + // 每次值变化后会回调此方法 + @Override + public void onAnimationUpdate(ValueAnimator animator) { + int height = (int) animator.getAnimatedValue(); + // 重新设置LineartLayout的高度从而实现动画效果 + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) llContainer.getLayoutParams(); + params.height = height; + llContainer.setLayoutParams(params); + } + }); + + + //动画执行后滚动至底部,设置监听 + animator.addListener(new Animator.AnimatorListener() { + + //动画结束后回调 + @Override + public void onAnimationEnd(Animator animator) { + if (animationFinishListener != null){ + animationFinishListener.onFinish(); + } + } + + @Override + public void onAnimationStart(Animator animator) { + + } + + @Override + public void onAnimationRepeat(Animator animator) { + + } + + @Override + public void onAnimationCancel(Animator animator) { + + } + }); + + + animator.start(); + } + + // 箭头的动画 + private void doArrowAnim() { + if (isExpand) { + // 当前是展开,将执行收起,箭头由上变为下 + ObjectAnimator.ofFloat(ivArrow, "rotation", -180, 0).start(); + } else { + // 当前是收起,将执行展开,箭头由下变为上 + ObjectAnimator.ofFloat(ivArrow, "rotation", 0, 180).start(); + } + } + + @Override + public void onClick(View v) { + if (isExpand) { + hide(true); + tvTip.setText(hideText); + } else { + expand(); + tvTip.setText(expandText); + } + doArrowAnim(); + isExpand = !isExpand; + } + + private AnimationFinishListener animationFinishListener; + + public void setOnAnimationFinishListener(AnimationFinishListener animationFinishListener) { + this.animationFinishListener = animationFinishListener; + } + + /**动画完成后的监听*/ + public interface AnimationFinishListener { + void onFinish(); + } +} diff --git a/viewlib/src/main/java/com/chaychan/viewlib/NumberTextWatcher.java b/viewlib/src/main/java/com/chaychan/viewlib/NumberTextWatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..4d1842f07755f84717dde43eb81b77353adf4d2d --- /dev/null +++ b/viewlib/src/main/java/com/chaychan/viewlib/NumberTextWatcher.java @@ -0,0 +1,101 @@ +package com.chaychan.viewlib; + +import android.text.Editable; +import android.text.Selection; +import android.text.TextWatcher; +import android.widget.EditText; + +/** + * 银行卡号输入框格式(每4位有个空格) + * + * @author Administrator + */ +class NumberTextWatcher implements TextWatcher { + + private EditText mEditText; + private char mDivider; + + int beforeTextLength = 0; + int onTextLength = 0; + boolean isChanged = false; + + int location = 0;// 记录光标的位置 + private char[] tempChar; + private StringBuffer buffer = new StringBuffer(); + int konggeNumberB = 0; + + public NumberTextWatcher(EditText editText, char divider) { + mEditText = editText; + mDivider = divider; + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + onTextLength = s.length(); + buffer.append(s.toString()); + if (onTextLength == beforeTextLength || onTextLength <= 3 + || isChanged) { + isChanged = false; + return; + } + isChanged = true; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + beforeTextLength = s.length(); + if (buffer.length() > 0) { + buffer.delete(0, buffer.length()); + } + konggeNumberB = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == mDivider) { + konggeNumberB++; + } + } + } + + @Override + public void afterTextChanged(Editable s) { + if (isChanged) { + location = mEditText.getSelectionEnd(); + int index = 0; + while (index < buffer.length()) { + if (buffer.charAt(index) == mDivider) { + buffer.deleteCharAt(index); + } else { + index++; + } + } + + index = 0; + int spaceNumberCount = 0;//空格的个数 + while (index < buffer.length()) { + if ((index == 4 || index == 9 || index == 14 || index == 19 || index == 24 || index == 29)) { + buffer.insert(index, mDivider); + spaceNumberCount++; + } + index++; + } + + if (spaceNumberCount > konggeNumberB) { + location += (spaceNumberCount - konggeNumberB); + } + + tempChar = new char[buffer.length()]; + buffer.getChars(0, buffer.length(), tempChar, 0); + String str = buffer.toString(); + if (location > str.length()) { + location = str.length(); + } else if (location < 0) { + location = 0; + } + mEditText.setText(str); + Editable etable = mEditText.getText(); + Selection.setSelection(etable, location); + isChanged = false; + } + } +} \ No newline at end of file diff --git a/viewlib/src/main/java/com/chaychan/viewlib/PhoneEditText.java b/viewlib/src/main/java/com/chaychan/viewlib/PhoneEditText.java new file mode 100644 index 0000000000000000000000000000000000000000..34cc7acaa536cd11066d4ee061402a9910b19965 --- /dev/null +++ b/viewlib/src/main/java/com/chaychan/viewlib/PhoneEditText.java @@ -0,0 +1,189 @@ +package com.chaychan.viewlib; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.CycleInterpolator; +import android.view.animation.TranslateAnimation; +import android.widget.EditText; + +public class PhoneEditText extends EditText implements View.OnFocusChangeListener { + private int lastLength = 0; + private TextWatcher mTextWatcher; + /** + * 删除按钮的引用 + */ + private Drawable mClearDrawable; + /** + * 控件是否有焦点 + */ + private boolean hasFoucs; + + private String divider = " "; + + + public PhoneEditText(Context context) { + this(context, null); + } + + public PhoneEditText(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.editTextStyle); // Attention here ! + } + + public PhoneEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PhoneEditText); + String dividerString = typedArray.getString(R.styleable.PhoneEditText_dividerString); + if (dividerString != null && dividerString.length() > 0){ + divider = dividerString; + } + typedArray.recycle(); + initContent(); + } + + private void initContent() { + + mTextWatcher = new 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) { + if(hasFoucs){ + //setClearIconVisible(s.length() > 0); + } + } + + @Override + public void afterTextChanged(Editable s) { + if (s.length() < lastLength){ + lastLength = s.length(); + return; + } + //防止进入死循环 + removeTextChangedListener(mTextWatcher); + String text = getText().toString().trim(); + if (text.contains(divider)){//删除已添加的divider + String[] ses = text.split(divider); + for (int j = 0; j< ses.length -1;j++){ + int length = 0; + for (int k = 0; k <= j;k++){ + length = length + ses[k].length(); + } + s.delete(length,length + divider.length()); + } + } + if (s.length() > 3){//插入divider + s.insert(3,divider); + } + if (s.length() > (7 + divider.length())){ + s.insert((7 + divider.length()),divider); + } + if (s.length() > (11 + divider.length()*2)){//删除最后添加的divider + s.delete((11 + divider.length()*2),getText().length()); + } + + lastLength = s.length(); + addTextChangedListener(mTextWatcher); + } + }; + addTextChangedListener(mTextWatcher); + + //获取EditText的DrawableRight,假如没有设置我们就使用默认的图片 + mClearDrawable = getCompoundDrawables()[2]; + if (mClearDrawable == null) { +// throw new NullPointerException("You can add drawableRight attribute in XML"); + mClearDrawable = getResources().getDrawable(R.drawable.delete_selector); + } + + mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); + //默认设置隐藏图标 + setClearIconVisible(false); + //设置焦点改变的监听 + setOnFocusChangeListener(this); + } + + /** + * + */ + public String getTextString(){ + return getText().toString().replace(divider,""); + } + + + /** + * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件 + * 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和 + * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑 + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + if (getCompoundDrawables()[2] != null) { + + boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight()) + && (event.getX() < ((getWidth() - getPaddingRight()))); + + if (touchable) { + this.setText(""); + } + } + } + + return super.onTouchEvent(event); + } + + /** + * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏 + */ + @Override + public void onFocusChange(View v, boolean hasFocus) { + this.hasFoucs = hasFocus; +// if (hasFocus) { +// setClearIconVisible(getText().length() > 0); +// } else { +// setClearIconVisible(false); +// } + } + + + /** + * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去 + * @param visible + */ + protected void setClearIconVisible(boolean visible) { + Drawable right = visible ? mClearDrawable : null; + setCompoundDrawables(getCompoundDrawables()[0], + getCompoundDrawables()[1], right, getCompoundDrawables()[3]); + } + + /** + * 设置晃动动画 + */ + public void setShakeAnimation(){ + this.setAnimation(shakeAnimation(50)); + } + + + /** + * 晃动动画 + * @param counts 1秒钟晃动多少下 + * @return + */ + public static Animation shakeAnimation(int counts){ + Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0); + translateAnimation.setInterpolator(new CycleInterpolator(counts)); + translateAnimation.setDuration(1000); + return translateAnimation; + } + +} \ No newline at end of file diff --git a/viewlib/src/main/java/com/chaychan/viewlib/PowerfulEditText.java b/viewlib/src/main/java/com/chaychan/viewlib/PowerfulEditText.java index 2fc24363554a139e624729c30292c2f35cd3931f..64f83b212dca77f03379c9c921883547421c3919 100644 --- a/viewlib/src/main/java/com/chaychan/viewlib/PowerfulEditText.java +++ b/viewlib/src/main/java/com/chaychan/viewlib/PowerfulEditText.java @@ -14,8 +14,12 @@ import android.widget.EditText; public class PowerfulEditText extends EditText { private static final String TAG = PowerfulEditText.class.getSimpleName(); + + /**普通类型*/ private static final int TYPE_NORMAL = -1; + /**自带清除功能的类型*/ private static final int TYPE_CAN_CLEAR = 0; + /**自带密码查看功能的类型*/ private static final int TYPE_CAN_WATCH_PWD = 1; @@ -131,7 +135,8 @@ public class PowerfulEditText extends EditText { @Override public void onTextChanged(CharSequence s, int start, int count, int after) { - if (funcType == 0) { + //如果是带有清除功能的类型,当文本内容发生变化的时候,根据内容的长度是否为0进行隐藏或显示 + if (funcType == TYPE_CAN_CLEAR) { setRightIconVisible(s.length() > 0); } @@ -157,6 +162,8 @@ public class PowerfulEditText extends EditText { }); } + + ta.recycle(); } @@ -170,17 +177,17 @@ public class PowerfulEditText extends EditText { if (event.getAction() == MotionEvent.ACTION_UP) { if (getCompoundDrawables()[2] != null) { - boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight()) + boolean isTouched = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight()))); - if (touchable) { + if (isTouched) { if (onRightClickListener == null) { if (funcType == TYPE_CAN_CLEAR) { //如果没有设置右边图标的点击事件,并且带有清除功能,默认清除文本 this.setText(""); } else if (funcType == TYPE_CAN_WATCH_PWD) { - //如果没有设置右边图标的点击事件,并且带有查看密码功能,点击查看密码 + //如果没有设置右边图标的点击事件,并且带有查看密码功能,点击切换密码查看方式 if (eyeOpen) { //变为密文 TYPE_CLASS_TEXT 和 TYPE_TEXT_VARIATION_PASSWORD 必须一起使用 this.setTransformationMethod(PasswordTransformationMethod.getInstance()); @@ -256,6 +263,7 @@ public class PowerfulEditText extends EditText { * 输入框文本变化的回调,如果需要进行多一些操作判断,则设置此listen替代TextWatcher */ public interface TextListener { + void onTextChanged(CharSequence s, int start, int count, int after); void beforeTextChanged(CharSequence s, int start, int count, int after); diff --git a/viewlib/src/main/java/com/chaychan/viewlib/UIUtils.java b/viewlib/src/main/java/com/chaychan/viewlib/UIUtils.java index 71aa0362dbf4e5827e0646bc3272ba639f65db0e..9f8473df7c1236756d40c40aa1df9447f4808d6b 100644 --- a/viewlib/src/main/java/com/chaychan/viewlib/UIUtils.java +++ b/viewlib/src/main/java/com/chaychan/viewlib/UIUtils.java @@ -23,4 +23,15 @@ public class UIUtils { int px = (int) (dip * density + 0.5f); return px; } + + /** + * 将sp值转换为px值,保证文字大小不变 + * + * @param spValue + * @return + */ + public static int sp2px(Context context,float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } } diff --git a/viewlib/src/main/res/layout/expandable_linearlayout.xml b/viewlib/src/main/res/layout/expandable_linearlayout.xml new file mode 100644 index 0000000000000000000000000000000000000000..1f477c670a8f0923a95d048817f09af79a1cbc85 --- /dev/null +++ b/viewlib/src/main/res/layout/expandable_linearlayout.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/viewlib/src/main/res/mipmap-hdpi/arrow_down.png b/viewlib/src/main/res/mipmap-hdpi/arrow_down.png new file mode 100644 index 0000000000000000000000000000000000000000..3976f2d98d84c51c9b3ad1f484776b0fc4243d0d Binary files /dev/null and b/viewlib/src/main/res/mipmap-hdpi/arrow_down.png differ diff --git a/viewlib/src/main/res/values/attr.xml b/viewlib/src/main/res/values/attr.xml index a6ed1c5157ff986ce3888def3b6141b39f41c562..5f59c83fea2c07cdc884ffb870315e03285daee2 100644 --- a/viewlib/src/main/res/values/attr.xml +++ b/viewlib/src/main/res/values/attr.xml @@ -1,5 +1,19 @@ + + + + + + + + + + + + + + @@ -20,4 +34,9 @@ + + + + + \ No newline at end of file