首页 > 代码库 > 自制WheelView沉浸式菜单及Dialog样式Activit
自制WheelView沉浸式菜单及Dialog样式Activit
本文为 兄弟连IT教育 机构官方 主要介绍:自制WheelView沉浸式菜单及Dialog样式Activit
自制一个简单的WheelView控件,配合Dialog样式的Activity使用
为什么不直接用Dialog呢?
因为感觉Dialog有时候传值会很麻烦,而且写起来也不方便。用Activity仿的话就很方便,效果也不错。
当然用Dialog也是可以的,具体根据项目需求和个人习惯而定。
效果图如下:
那么直接贴核心代码,源码我会在博客底部发链接
Dialog样式的Activity布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <? xml version = "1.0" encoding = "utf-8" ?> < RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:tools = "http://schemas.android.com/tools" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:layout_gravity = "center" android:layout_margin = "80dp" > < TextView android:id = "@+id/rate_tv" android:layout_width = "fill_parent" android:layout_height = "45dp" android:background = "@drawable/more_top_nor" android:gravity = "center" android:text = "选项" android:drawableBottom = "@drawable/cell_cut_line" android:textColor = "@android:color/black" android:textSize = "18sp" /> < com.lg.wheelviewdemo.PickerView android:id = "@+id/pickerview" android:layout_below = "@id/rate_tv" android:background = "@drawable/more_content_nor" android:layout_width = "match_parent" android:layout_height = "150dp" /> < TextView android:onClick = "onClick" android:layout_width = "fill_parent" android:layout_height = "45dp" android:drawableTop = "@drawable/cell_cut_line" android:layout_below = "@id/pickerview" android:text = "确定" android:textColor = "@android:color/black" android:textSize = "18sp" android:gravity = "center" android:background = "@drawable/more_bottom_nor" /> </ RelativeLayout > |
PickerView也就是自制的WheelView,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | /** * 滚动选择器 */ public class PickerView extends View { public static final String TAG = "PickerView" ; /** * text之间间距和minTextSize之比 */ public static final float MARGIN_ALPHA = 2 .3f; /** * 自动回滚到中间的速度 */ public static final float SPEED = 2 ; private List<String> mDataList; /** * 选中的位置,这个位置是mDataList的中心位置,一直不变 */ private int mCurrentSelected; private Paint mPaint; private float mMaxTextSize = 30 ; private float mMinTextSize = 15 ; private float mMaxTextAlpha = 255 ; private float mMinTextAlpha = 100 ; private int mViewHeight; private int mViewWidth; private float mLastDownY; /** * 滑动的距离 */ private float mMoveLen = 0 ; private boolean isInit = false ; private onSelectListener mSelectListener; private Timer timer; private MyTimerTask mTask; Handler updateHandler = new Handler() { @Override public void handleMessage(Message msg) { if (Math.abs(mMoveLen) < SPEED) { mMoveLen = 0 ; if (mTask != null ) { mTask.cancel(); mTask = null ; performSelect(); } } else // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚 mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED; invalidate(); } }; public PickerView(Context context) { super (context); init(); } public PickerView(Context context, AttributeSet attrs) { super (context, attrs); init(); } public void setOnSelectListener(onSelectListener listener) { mSelectListener = listener; } private void performSelect() { if (mSelectListener != null ) mSelectListener.onSelect(mDataList.get(mCurrentSelected)); } public void setData(List<String> datas) { mDataList = datas; mCurrentSelected = datas.size() / 2 ; invalidate(); } /** * 选择选中的item的index * * @param selected */ public void setSelected( int selected) { mCurrentSelected = selected; int distance = mDataList.size() / 2 - mCurrentSelected; if (distance < 0 ) for ( int i = 0 ; i < -distance; i++) { moveHeadToTail(); mCurrentSelected--; } else if (distance > 0 ) for ( int i = 0 ; i < distance; i++) { moveTailToHead(); mCurrentSelected++; } invalidate(); } /** * 选择选中的内容 * * @param mSelectItem */ public void setSelected(String mSelectItem) { for ( int i = 0 ; i < mDataList.size(); i++) if (mDataList.get(i).equals(mSelectItem)) { setSelected(i); break ; } } private void moveHeadToTail() { String head = mDataList.get( 0 ); mDataList.remove( 0 ); mDataList.add(head); } private void moveTailToHead() { String tail = mDataList.get(mDataList.size() - 1 ); mDataList.remove(mDataList.size() - 1 ); mDataList.add( 0 , tail); } @Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { super .onMeasure(widthMeasureSpec, heightMeasureSpec); mViewHeight = getMeasuredHeight(); mViewWidth = getMeasuredWidth(); // 按照View的高度计算字体大小 mMaxTextSize = mViewHeight / 4 .0f; mMinTextSize = mMaxTextSize / 2f; isInit = true ; invalidate(); } private void init() { timer = new Timer(); mDataList = new ArrayList<String>(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Style.FILL); mPaint.setTextAlign(Align.CENTER); mPaint.setColor(Color.WHITE); } @Override protected void onDraw(Canvas canvas) { super .onDraw(canvas); // 根据index绘制view if (isInit) drawData(canvas); } private void drawData(Canvas canvas) { // 先绘制选中的text再往上往下绘制其余的text float scale = parabola(mViewHeight / 4 .0f, mMoveLen); float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize; mPaint.setTextSize(size); mPaint.setColor( this .getResources().getColor(android.R.color.black)); mPaint.setAlpha(( int ) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标 float x = ( float ) (mViewWidth / 2.0 ); float y = ( float ) (mViewHeight / 2.0 + mMoveLen); FontMetricsInt fmi = mPaint.getFontMetricsInt(); float baseline = ( float ) (y - (fmi.bottom / 2.0 + fmi.top / 2.0 )); canvas.drawText(mDataList.get(mCurrentSelected), x, baseline, mPaint); // 绘制上方data for ( int i = 1 ; (mCurrentSelected - i) >= 0 ; i++) { drawOtherText(canvas, i, - 1 ); } // 绘制下方data for ( int i = 1 ; (mCurrentSelected + i) < mDataList.size(); i++) { drawOtherText(canvas, i, 1 ); } } /** * @param canvas * @param position 距离mCurrentSelected的差值 * @param type 1表示向下绘制,-1表示向上绘制 */ private void drawOtherText(Canvas canvas, int position, int type) { float d = ( float ) (MARGIN_ALPHA * mMinTextSize * position + type * mMoveLen); float scale = parabola(mViewHeight / 4 .0f, d); float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize; mPaint.setTextSize(size); mPaint.setAlpha(( int ) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); float y = ( float ) (mViewHeight / 2.0 + type * d); FontMetricsInt fmi = mPaint.getFontMetricsInt(); float baseline = ( float ) (y - (fmi.bottom / 2.0 + fmi.top / 2.0 )); canvas.drawText(mDataList.get(mCurrentSelected + type * position), ( float ) (mViewWidth / 2.0 ), baseline, mPaint); } /** * 抛物线 * * @param zero 零点坐标 * @param x 偏移量 * @return scale */ private float parabola( float zero, float x) { float f = ( float ) ( 1 - Math.pow(x / zero, 2 )); return f < 0 ? 0 : f; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: doDown(event); break ; case MotionEvent.ACTION_MOVE: doMove(event); break ; case MotionEvent.ACTION_UP: doUp(event); break ; } return true ; } private void doDown(MotionEvent event) { if (mTask != null ) { mTask.cancel(); mTask = null ; } mLastDownY = event.getY(); } private void doMove(MotionEvent event) { mMoveLen += (event.getY() - mLastDownY); if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2 ) { // 往下滑超过离开距离 moveTailToHead(); mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize; } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2 ) { // 往上滑超过离开距离 moveHeadToTail(); mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize; } mLastDownY = event.getY(); invalidate(); } private void doUp(MotionEvent event) { // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置 if (Math.abs(mMoveLen) < 0.0001 ) { mMoveLen = 0 ; return ; } if (mTask != null ) { mTask.cancel(); mTask = null ; } mTask = new MyTimerTask(updateHandler); timer.schedule(mTask, 0 , 10 ); } class MyTimerTask extends TimerTask { Handler handler; public MyTimerTask(Handler handler) { this .handler = handler; } @Override public void run() { handler.sendMessage(handler.obtainMessage()); } } public interface onSelectListener { void onSelect(String text); } |
Dialog样式Activity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | private PickerView pickerView; private List<String> mDatas; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_wheel); pickerView = (PickerView) findViewById(R.id.pickerview); mDatas= new ArrayList<>(); for ( int i = 1 ; i < 60 ; i++) { mDatas.add( "" +i); } pickerView.setData(mDatas); pickerView.setSelected(MainActivity.num- 1 ); pickerView.setOnSelectListener( new PickerView.onSelectListener() { @Override public void onSelect(String text) { MainActivity.num=Integer.parseInt(text); } }); } public void onClick(View view){ MainActivity.tv.setText( "当前选择 " +MainActivity.num); finish(); } |
接下来要给Activity换上Dialog样式
在styles.xml中加上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | < style name = "MyDialogStyle" parent = "Theme.AppCompat.Dialog" > < item name = "android:windowFrame" >@null</ item > < item name = "windowNoTitle" >true</ item > <!-- 边框 --> < item name = "android:windowIsFloating" >true</ item > <!-- 是否浮现在activity之上 --> < item name = "android:windowIsTranslucent" >true</ item > <!-- 半透明 --> < item name = "android:windowNoTitle" >true</ item > <!-- 无标题 --> < item name = "android:windowBackground" >@android:color/transparent</ item > <!-- 背景透明 --> < item name = "android:backgroundDimEnabled" >true</ item > <!-- 模糊 --> </ style > |
AndroidManifest.xml中:
1 2 | < activity android:name = ".WheelActivity" |
自制WheelView沉浸式菜单及Dialog样式Activit
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。