zoukankan      html  css  js  c++  java
  • wheelView实现滚动选择 三方开源的封装控件 spannableString autofitTextView、PinnedSectionListView SwipeListView等等

    wheelView多用于popupwindow用来滚动选择条目

    github上的开源三方控件     spannableString   autofitTextView、PinnedSectionListView(固定标签)   SwipeListView(右滑删除) Titanic(loading动画) AutoHideListView(自动隐藏上下View的ListView)   pullToZoomScrollView(下拉图片会放大的、上滑会遮盖的ScrollView)  coverFlow(画廊效果)

    大部分的三方控件都是类似的流程    用自己的布局  封装控件

    package com.wangjie.wheelview;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.ColorFilter;
    import android.graphics.Paint;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.ScrollView;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Author: wangjie
     * Email: tiantian.china.2@gmail.com
     * Date: 7/1/14.
     */
    public class WheelView extends ScrollView {
        public static final String TAG = WheelView.class.getSimpleName();
    
        public static class OnWheelViewListener {
            public void onSelected(int selectedIndex, String item) {
            }
        }
    
    
        private Context context;
    //    private ScrollView scrollView;
    
        private LinearLayout views;
    
        public WheelView(Context context) {
            super(context);
            init(context);
        }
    
        public WheelView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public WheelView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context);
        }
    
        //    String[] items;
        List<String> items;
    
        private List<String> getItems() {
            return items;
        }
    
        public void setItems(List<String> list) {
            if (null == items) {
                items = new ArrayList<String>();
            }
            items.clear();
            items.addAll(list);
    
            // 前面和后面补全
            for (int i = 0; i < offset; i++) {
                items.add(0, "");
                items.add("");
            }
    
            initData();
    
        }
    
    
        public static final int OFF_SET_DEFAULT = 1;
        int offset = OFF_SET_DEFAULT; // 偏移量(需要在最前面和最后面补全)
    
        public int getOffset() {
            return offset;
        }
    
        public void setOffset(int offset) {
            this.offset = offset;
        }
    
        int displayItemCount; // 每页显示的数量
    
        int selectedIndex = 1;
    
    
        private void init(Context context) {
            this.context = context;
    
    //        scrollView = ((ScrollView)this.getParent());
    //        Log.d(TAG, "scrollview: " + scrollView);
            Log.d(TAG, "parent: " + this.getParent());
    //        this.setOrientation(VERTICAL);
            this.setVerticalScrollBarEnabled(false);
    
            views = new LinearLayout(context);
            views.setOrientation(LinearLayout.VERTICAL);
            this.addView(views);
    
            scrollerTask = new Runnable() {
    
                public void run() {
    
                    int newY = getScrollY();
                    if (initialY - newY == 0) { // stopped
                        final int remainder = initialY % itemHeight;
                        final int divided = initialY / itemHeight;
    //                    Log.d(TAG, "initialY: " + initialY);
    //                    Log.d(TAG, "remainder: " + remainder + ", divided: " + divided);
                        if (remainder == 0) {
                            selectedIndex = divided + offset;
    
                            onSeletedCallBack();
                        } else {
                            if (remainder > itemHeight / 2) {
                                WheelView.this.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        WheelView.this.smoothScrollTo(0, initialY - remainder + itemHeight);
                                        selectedIndex = divided + offset + 1;
                                        onSeletedCallBack();
                                    }
                                });
                            } else {
                                WheelView.this.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        WheelView.this.smoothScrollTo(0, initialY - remainder);
                                        selectedIndex = divided + offset;
                                        onSeletedCallBack();
                                    }
                                });
                            }
    
    
                        }
    
    
                    } else {
                        initialY = getScrollY();
                        WheelView.this.postDelayed(scrollerTask, newCheck);
                    }
                }
            };
    
    
        }
    
        int initialY;
    
        Runnable scrollerTask;
        int newCheck = 50;
    
        public void startScrollerTask() {
    
            initialY = getScrollY();
            this.postDelayed(scrollerTask, newCheck);
        }
    
        private void initData() {
            displayItemCount = offset * 2 + 1;
    
            for (String item : items) {
                views.addView(createView(item));
            }
    
            refreshItemView(0);
        }
    
        int itemHeight = 0;
    
        private TextView createView(String item) {
            TextView tv = new TextView(context);
            tv.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            tv.setSingleLine(true);
            tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
            tv.setText(item);
            tv.setGravity(Gravity.CENTER);
            int padding = dip2px(15);
            tv.setPadding(padding, padding, padding, padding);
            if (0 == itemHeight) {
                itemHeight = getViewMeasuredHeight(tv);
                Log.d(TAG, "itemHeight: " + itemHeight);
                views.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight * displayItemCount));
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) this.getLayoutParams();
                this.setLayoutParams(new LinearLayout.LayoutParams(lp.width, itemHeight * displayItemCount));
            }
            return tv;
        }
    
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
    
    //        Log.d(TAG, "l: " + l + ", t: " + t + ", oldl: " + oldl + ", oldt: " + oldt);
    
    //        try {
    //            Field field = ScrollView.class.getDeclaredField("mScroller");
    //            field.setAccessible(true);
    //            OverScroller mScroller = (OverScroller) field.get(this);
    //
    //
    //            if(mScroller.isFinished()){
    //                Log.d(TAG, "isFinished...");
    //            }
    //
    //        } catch (Exception e) {
    //            e.printStackTrace();
    //        }
    
    
            refreshItemView(t);
    
            if (t > oldt) {
    //            Log.d(TAG, "向下滚动");
                scrollDirection = SCROLL_DIRECTION_DOWN;
            } else {
    //            Log.d(TAG, "向上滚动");
                scrollDirection = SCROLL_DIRECTION_UP;
    
            }
    
    
        }
    
        private void refreshItemView(int y) {
            int position = y / itemHeight + offset;
            int remainder = y % itemHeight;
            int divided = y / itemHeight;
    
            if (remainder == 0) {
                position = divided + offset;
            } else {
                if (remainder > itemHeight / 2) {
                    position = divided + offset + 1;
                }
    
    //            if(remainder > itemHeight / 2){
    //                if(scrollDirection == SCROLL_DIRECTION_DOWN){
    //                    position = divided + offset;
    //                    Log.d(TAG, ">down...position: " + position);
    //                }else if(scrollDirection == SCROLL_DIRECTION_UP){
    //                    position = divided + offset + 1;
    //                    Log.d(TAG, ">up...position: " + position);
    //                }
    //            }else{
    ////                position = y / itemHeight + offset;
    //                if(scrollDirection == SCROLL_DIRECTION_DOWN){
    //                    position = divided + offset;
    //                    Log.d(TAG, "<down...position: " + position);
    //                }else if(scrollDirection == SCROLL_DIRECTION_UP){
    //                    position = divided + offset + 1;
    //                    Log.d(TAG, "<up...position: " + position);
    //                }
    //            }
    //        }
    
    //        if(scrollDirection == SCROLL_DIRECTION_DOWN){
    //            position = divided + offset;
    //        }else if(scrollDirection == SCROLL_DIRECTION_UP){
    //            position = divided + offset + 1;
            }
    
            int childSize = views.getChildCount();
            for (int i = 0; i < childSize; i++) {
                TextView itemView = (TextView) views.getChildAt(i);
                if (null == itemView) {
                    return;
                }
                if (position == i) {
                    itemView.setTextColor(Color.parseColor("#0288ce"));
                } else {
                    itemView.setTextColor(Color.parseColor("#bbbbbb"));
                }
            }
        }
    
        /**
         * 获取选中区域的边界
         */
        int[] selectedAreaBorder;
    
        private int[] obtainSelectedAreaBorder() {
            if (null == selectedAreaBorder) {
                selectedAreaBorder = new int[2];
                selectedAreaBorder[0] = itemHeight * offset;
                selectedAreaBorder[1] = itemHeight * (offset + 1);
            }
            return selectedAreaBorder;
        }
    
    
        private int scrollDirection = -1;
        private static final int SCROLL_DIRECTION_UP = 0;
        private static final int SCROLL_DIRECTION_DOWN = 1;
    
        Paint paint;
        int viewWidth;
    
        @Override
        public void setBackgroundDrawable(Drawable background) {
    
            if (viewWidth == 0) {
                viewWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();
                Log.d(TAG, "viewWidth: " + viewWidth);
            }
    
            if (null == paint) {
                paint = new Paint();
                paint.setColor(Color.parseColor("#83cde6"));
                paint.setStrokeWidth(dip2px(1f));
            }
    
            background = new Drawable() {
                @Override
                public void draw(Canvas canvas) {
                    canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[0], viewWidth * 5 / 6, obtainSelectedAreaBorder()[0], paint);
                    canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[1], viewWidth * 5 / 6, obtainSelectedAreaBorder()[1], paint);
                }
    
                @Override
                public void setAlpha(int alpha) {
    
                }
    
                @Override
                public void setColorFilter(ColorFilter cf) {
    
                }
    
                @Override
                public int getOpacity() {
                    return 0;
                }
            };
    
    
            super.setBackgroundDrawable(background);
    
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            Log.d(TAG, "w: " + w + ", h: " + h + ", oldw: " + oldw + ", oldh: " + oldh);
            viewWidth = w;
            setBackgroundDrawable(null);
        }
    
        /**
         * 选中回调
         */
        private void onSeletedCallBack() {
            if (null != onWheelViewListener) {
                onWheelViewListener.onSelected(selectedIndex, items.get(selectedIndex));
            }
    
        }
    
        public void setSeletion(int position) {
            final int p = position;
            selectedIndex = p + offset;
            this.post(new Runnable() {
                @Override
                public void run() {
                    WheelView.this.smoothScrollTo(0, p * itemHeight);
                }
            });
    
        }
    
        public String getSeletedItem() {
            return items.get(selectedIndex);
        }
    
        public int getSeletedIndex() {
            return selectedIndex - offset;
        }
    
    
        @Override
        public void fling(int velocityY) {
            super.fling(velocityY / 3);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_UP) {
    
                startScrollerTask();
            }
            return super.onTouchEvent(ev);
        }
    
        private OnWheelViewListener onWheelViewListener;
    
        public OnWheelViewListener getOnWheelViewListener() {
            return onWheelViewListener;
        }
    
        public void setOnWheelViewListener(OnWheelViewListener onWheelViewListener) {
            this.onWheelViewListener = onWheelViewListener;
        }
    
        private int dip2px(float dpValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        private int getViewMeasuredHeight(View view) {
            int width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
            view.measure(width, expandSpec);
            return view.getMeasuredHeight();
        }
    
    }
    WheelView
    package com.wangjie.wheelview.sample;
    
    import android.app.AlertDialog;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import com.wangjie.wheelview.R;
    import com.wangjie.wheelview.WheelView;
    
    import java.util.Arrays;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private static final String TAG = MainActivity.class.getSimpleName();
        private static final String[] PLANETS = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Uranus", "Neptune", "Pluto"};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            WheelView wva = (WheelView) findViewById(R.id.main_wv);
    
            wva.setOffset(1);
            wva.setItems(Arrays.asList(PLANETS));
            wva.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
                @Override
                public void onSelected(int selectedIndex, String item) {
                    Log.d(TAG, "selectedIndex: " + selectedIndex + ", item: " + item);
                }
            });
    
            findViewById(R.id.main_show_dialog_btn).setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.main_show_dialog_btn:
                    View outerView = LayoutInflater.from(this).inflate(R.layout.wheel_view, null);
                    WheelView wv = (WheelView) outerView.findViewById(R.id.wheel_view_wv);
                    wv.setOffset(2);
                    wv.setItems(Arrays.asList(PLANETS));
                    wv.setSeletion(3);
                    wv.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
                        @Override
                        public void onSelected(int selectedIndex, String item) {
                            Log.d(TAG, "[Dialog]selectedIndex: " + selectedIndex + ", item: " + item);
                        }
                    });
    
                    new AlertDialog.Builder(this)
                            .setTitle("WheelView in Dialog")
                            .setView(outerView)
                            .setPositiveButton("OK", null)
                            .show();
    
                    break;
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    }
    MAinActivity
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
    >
    
        <com.wangjie.wheelview.WheelView
            android:id="@+id/main_wv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />
    
    
        <Button
            android:id="@+id/main_show_dialog_btn"
            android:layout_width="match_parent" android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:text="show WheelView in Dialog!"
        />
    
    </LinearLayout>
    activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent">
    
        <com.wangjie.wheelview.WheelView
            android:id="@+id/wheel_view_wv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />
    
    
    </LinearLayout>
    wheelView.xml

    注意: MainActivity中的list数据如果使用BaseAdapter的话 因为其中wheelView设置了offset所以取数据的时候需要减去offset值否则会报错list.get(position-offset);

    效果如图

  • 相关阅读:
    C复制字符串
    C语言分解数组
    perlCGI编程之测试环境
    linux下c语言 读取文件
    C++的组合(Composite)模式
    C#GDI+绘制多行文本和格式化文本
    shell中引号的应用
    perlCGI编程之Apache服务器安装配置
    求二叉树的深度
    perlCGI编程之页面参数传递
  • 原文地址:https://www.cnblogs.com/bimingcong/p/5175876.html
Copyright © 2011-2022 走看看