美文网首页
P2PInvest笔记02

P2PInvest笔记02

作者: GeekGray | 来源:发表于2018-09-27 22:35 被阅读3次

    阅读原文

    09-HomeFragment中自定义圆形进度条ui-RoundProgress

    /**
     * @author: Hashub
     * @WeChat: NGSHMVP
     * @Date: 2018/9/19 21:30
     * @function:自定义的圆形进度条
     */
    public class RoundProgress extends View
    {
    //设置绘制的圆环及文本的属性---->使用自定义属性替换
    //    private int roundColor = Color.GRAY;//圆环的颜色
    //    private int roundProgressColor = Color.RED;//圆弧的颜色
    //    private int textColor = Color.BLUE;//文本的颜色
    //
    //    private int roundWidth = UIUtils.dp2px(10);//圆环的宽度
    //    private int textSize = UIUtils.dp2px(20);//文本的字体大小
    //
    //    private int max = 100;//圆环的最大值
    //    private int progress = 60;//圆环的进度
    
        //使用自定义属性来初始化如下的变量
        private int roundColor;//圆环的颜色
        private int roundProgressColor;//圆弧的颜色
        private int textColor;//文本的颜色
    
        private float roundWidth;//圆环的宽度
        private float textSize;//文本的字体大小
    
        private int max;//圆环的最大值
        private int progress;//圆环的进度
    
        private int width;//当前视图的宽度(=高度)
    
        private Paint paint;//画笔
    
        public RoundProgress(Context context)
        {
            this(context, null);
        }
    
        public RoundProgress(Context context, AttributeSet attrs)
        {
            this(context, attrs, 0);
        }
    
        public RoundProgress(Context context, AttributeSet attrs, int defStyleAttr)
        {
            super(context, attrs, defStyleAttr);
    
            //初始化画笔
            paint = new Paint();
            paint.setAntiAlias(true);//去除毛边
    
            //获取自定义的属性
            //1.获取TypeArray的对象(调用两个参数的方法)
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgress);
    
            //2.取出所有的自定义属性
            roundColor = typedArray.getColor(R.styleable.RoundProgress_roundColor, Color.GRAY);
            roundProgressColor = typedArray.getColor(R.styleable.RoundProgress_roundProgressColor, Color.RED);
            textColor = typedArray.getColor(R.styleable.RoundProgress_textColor, Color.GREEN);
            roundWidth = typedArray.getDimension(R.styleable.RoundProgress_roundWith, UIUtils.dp2px(10));
            textSize = typedArray.getDimension(R.styleable.RoundProgress_textSize, UIUtils.dp2px(20));
            max = typedArray.getInteger(R.styleable.RoundProgress_max, 100);
            progress = typedArray.getInteger(R.styleable.RoundProgress_progress, 30);
    
            //3.回收处理
            typedArray.recycle();
        }
    
        public int getMax()
        {
            return max;
        }
    
        public void setMax(int max)
        {
            this.max = max;
        }
    
        public int getProgress()
        {
            return progress;
        }
    
        public void setProgress(int progress)
        {
            this.progress = progress;
        }
    
        //测量:获取当前视图宽高
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = this.getMeasuredWidth();
        }
    
    
        /**
         * canvas:画布,对应着视图在布局中的范围区间。范围的左上顶点即为坐标原点
         *
         * @param canvas
         */
        @Override
        protected void onDraw(Canvas canvas)
        {
            //1.绘制圆环
            //获取圆心坐标
            int cx = width / 2;
            int cy = width / 2;
            float radius = width / 2 - roundWidth / 2;
            paint.setColor(roundColor);//设置画笔颜色
            paint.setStyle(Paint.Style.STROKE);//设置圆环的样式
            paint.setStrokeWidth(roundWidth);//设置圆环的宽度
            canvas.drawCircle(cx, cy, radius, paint);
    
            //2.绘制圆弧
            RectF rectF = new RectF(roundWidth / 2, roundWidth / 2, width - roundWidth / 2, width - roundWidth / 2);
            paint.setColor(roundProgressColor);//设置画笔颜色
            canvas.drawArc(rectF, 0, progress * 360 / max, false, paint);
    
            //3.绘制文本
            String text = progress * 100 / max + "%";
            //设置paint
            paint.setColor(textColor);
            paint.setTextSize(textSize);
            paint.setStrokeWidth(0);
            Rect rect = new Rect();//创建了一个矩形,此时矩形没有具体的宽度和高度
            paint.getTextBounds(text, 0, text.length(), rect);//此时的矩形的宽度和高度即为整好包裹文本的矩形的宽高
            //获取左下顶点的坐标
            int x = width / 2 - rect.width() / 2;
            int y = width / 2 + rect.height() / 2;
    
    
            canvas.drawText(text, x, y, paint);
    
        }
    }
    

    010-HomeFragment中自定义ui-MyScrollView,实现头尾部的下拉、上拉

    /**
     * @author: Hashub
     * @WeChat: NGSHMVP
     * @Date: 2018/9/19 21:31
     * @function:自定义尾部上拉下拉
     */
    public class MyScrollView extends ScrollView
    {
        private View childView;
    
        public MyScrollView(Context context)
        {
            super(context);
        }
    
        public MyScrollView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
        }
    
        public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr)
        {
            super(context, attrs, defStyleAttr);
        }
    
        //获取子视图
        @Override
        protected void onFinishInflate()
        {
            super.onFinishInflate();
            if (getChildCount() > 0)
            {
                childView = getChildAt(0);
            }
        }
    
        private int lastY;//上一次y轴方向操作的坐标位置
        private Rect normal = new Rect();//用于记录临界状态的左、上、右、下
        private boolean isFinishAnimation = true;//是否动画结束
    
        private int lastX, downX, downY;
    
        //拦截:实现父视图对子视图的拦截
        //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev)
        {
            boolean isIntercept = false;
            int eventX = (int) ev.getX();
            int eventY = (int) ev.getY();
            switch (ev.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    lastX = downX = eventX;
                    lastY = downY = eventY;
                    break;
                case MotionEvent.ACTION_MOVE:
                    //获取水平和垂直方向的移动距离
                    int absX = Math.abs(eventX - downX);
                    int absY = Math.abs(eventY - downY);
    
                    if (absY > absX && absY >= UIUtils.dp2px(10))
                    {
                        isIntercept = true;//执行拦截
                    }
    
                    lastX = eventX;
                    lastY = eventY;
                    break;
            }
    
            return isIntercept;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev)
        {
            if (childView == null || !isFinishAnimation)
            {
                return super.onTouchEvent(ev);
            }
    
            int eventY = (int) ev.getY();//获取当前的y轴坐标
            switch (ev.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    lastY = eventY;
                    break;
                case MotionEvent.ACTION_MOVE:
    
                    int dy = eventY - lastY;//微小的移动量
    
                    if (isNeedMove())
                    {
                        if (normal.isEmpty())
                        {
                            //记录了childView的临界状态的左、上、右、下
                            normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
    
                        }
                        //重新布局
                        childView.layout(childView.getLeft(), childView.getTop() + dy / 2, childView.getRight(), childView.getBottom() + dy / 2);
                    }
    
                    lastY = eventY;//重新赋值
                    break;
                case MotionEvent.ACTION_UP:
                    if (isNeedAnimation())
                    {
                        //使用平移动画
                        int translateY = childView.getBottom() - normal.bottom;
                        TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
                        translateAnimation.setDuration(200);
    //                translateAnimation.setFillAfter(true);//停留在最终位置上
    
                        translateAnimation.setAnimationListener(new Animation.AnimationListener()
                        {
                            @Override
                            public void onAnimationStart(Animation animation)
                            {
                                isFinishAnimation = false;
                            }
    
                            @Override
                            public void onAnimationEnd(Animation animation)
                            {
                                isFinishAnimation = true;
                                childView.clearAnimation();//清除动画
                                //重新布局
                                childView.layout(normal.left, normal.top, normal.right, normal.bottom);
                                //清除normal的数据
                                normal.setEmpty();
                            }
    
                            @Override
                            public void onAnimationRepeat(Animation animation)
                            {
    
                            }
                        });
    
                        //启动动画
                        childView.startAnimation(translateAnimation);
                    }
    
    
                    break;
            }
    
    
            return super.onTouchEvent(ev);
        }
    
        //判断是否需要执行平移动画
        private boolean isNeedAnimation()
        {
            return !normal.isEmpty();
    
        }
    
        private boolean isNeedMove()
        {
            int childMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度
            int scrollViewMeasuredHeight = this.getMeasuredHeight();//获取布局的高度
    
            Log.e("TAG", "childMeasuredHeight = " + childMeasuredHeight);
            Log.e("TAG", "scrollViewMeasuredHeight = " + scrollViewMeasuredHeight);
    
            int dy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0
    
            int scrollY = this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -)
            if (scrollY <= 0 || scrollY >= dy)
            {
                return true;//按照我们自定义的MyScrollView的方式处理
            }
            //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理
            return false;
        }
    }
    

    011-BaseFragment的抽取

    public abstract class BaseFragment extends Fragment
    {
        private LoadingPage loadingPage;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            loadingPage = new LoadingPage(container.getContext())
            {
    
                @Override
                public int layoutId()
                {
                    return getLayoutId();
                }
    
                @Override
                protected void onSuccss(ResultState resultState, View view_success)
                {
                    ButterKnife.bind(BaseFragment.this, view_success);
                    initTitle();
                    initData(resultState.getContent());
                }
    
                @Override
                protected RequestParams params()
                {
                    return getParams();
                }
    
                @Override
                public String url()
                {
                    return getUrl();
                }
            };
    
    
            return loadingPage;
        }
    
    
    
        /**
         * 为了保证loadingPage不为null
         * @param savedInstanceState
         */
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState)
        {
            super.onActivityCreated(savedInstanceState);
    
            getDataFromNet();
        }
    
        protected abstract RequestParams getParams();
    
        protected abstract String getUrl();
    
        //初始化界面的数据
        protected abstract void initData(String content);
    
        //初始化title
        protected abstract void initTitle();
    
        //提供布局
        public abstract int getLayoutId();
    
        @Override
        public void onDestroyView()
        {
            super.onDestroyView();
            ButterKnife.unbind(this);
        }
    
        public void getDataFromNet()
        {
            loadingPage.getDataFromNet();
        }
    
    }
    

    012-LoadingPage的抽取

    提供抽象的LoadingPage

    /**
     * @author: Hashub
     * @WeChat: NGSHMVP
     * @Date: 2018/9/19 18:51
     * @function:根据实际联网获取数据情况加载不同的界面
     */
    public abstract class LoadingPage extends FrameLayout
    {
        //1.定义4种不同的显示状态
        private static final int STATE_LOADING = 1;
        private static final int STATE_ERROR = 2;
        private static final int STATE_EMPTY = 3;
        private static final int STATE_SUCCESS = 4;
    
        private int state_current = STATE_LOADING;//默认情况下,当前状态为正在加载
    
        //2.提供4种不同的界面
        private View view_loading;
        private View view_error;
        private View view_empty;
        private View view_success;
        private LayoutParams params;
    
        private ResultState resultState;//状态枚举类对象
    
        public LoadingPage(Context context)
        {
            this(context, null);
        }
    
        public LoadingPage(Context context, AttributeSet attrs)
        {
            this(context, attrs, 0);
        }
    
        public LoadingPage(Context context, AttributeSet attrs, int defStyleAttr)
        {
            super(context, attrs, defStyleAttr);
    
            initLayout();//初始化布局
        }
    
        /**
         * 初始化布局方法
         */
        private void initLayout()
        {
            //实例化view
            //1.提供布局显示的参数
            params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            if (view_loading == null)
            {
                //2.加载布局
                view_loading =  UIUtils.getView(R.layout.page_loading);
                //3.添加到当前的frameLayout中
                addView(view_loading, params);//viewGroup中的addView()方法
            }
    
            if (view_empty == null)
            {
                //2.加载布局
                view_empty = UIUtils.getView(R.layout.page_empty);
                //3.添加到当前的frameLayout中
                addView(view_empty, params);
            }
    
            if (view_error == null)
            {
                //2.加载布局
                view_error = UIUtils.getView(R.layout.page_error);
                //3.添加到当前的frameLayout中
                addView(view_error, params);
            }
    
            showSafePage();
        }
    
        /**
         * 保证如下的操作在主线程中执行的:更新界面
         */
        private void showSafePage()
        {
            UIUtils.runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    //保证run()中的操作在主线程中执行
                    showPage();
                }
            });
        }
    
        /**
         * 四套界面实际上是叠加显示的,根据当前state_current的值,决定显示哪个view,隐藏其他view
         */
        private void showPage()
        {
            view_loading.setVisibility(state_current == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
            view_error.setVisibility(state_current == STATE_ERROR ? View.VISIBLE : View.INVISIBLE);
            view_empty.setVisibility(state_current == STATE_EMPTY ? View.VISIBLE : View.INVISIBLE);
    
            if (view_success == null)
            {
                view_success = UIUtils.getView(layoutId());
                addView(view_success, params);
            }
    
            view_success.setVisibility(state_current == STATE_SUCCESS ? View.VISIBLE : View.INVISIBLE);
        }
    
        /**
         * 在getDataFromNet()中实现联网加载数据
         */
        public void getDataFromNet()
        {
            String url = url();
            //如果页面不需要联网请求,即url为空,则成功显示本身页面
            if (TextUtils.isEmpty(url))
            {
                resultState = ResultState.SUCCESS;
                resultState.setContent("");
                return;
            }
            //如果不为空,根据实际url联网请求数据
            //模拟联网延迟2s效果
            UIUtils.getHandler().postDelayed(new Runnable()
            {
                @Override
                public void run()
                {
                    AsyncHttpClient client = new AsyncHttpClient();
                    client.get(url(), params(), new AsyncHttpResponseHandler()
                    {
                        @Override
                        public void onSuccess(String content)
                        {
                            if (TextUtils.isEmpty(content))
                            {// "" or null
    //                    state_current = STATE_EMPTY;
                                resultState = ResultState.EMPTY;
                                resultState.setContent("");
                            }
                            else
                            {
    //                    state_current = STATE_SUCCESS;
                                resultState = ResultState.SUCCESS;
                                resultState.setContent(content);
                            }
    
    //                showSafePage();
                            loadPage();
                        }
    
                        @Override
                        public void onFailure(Throwable error, String content)
                        {
    //                state_current = STATE_ERROR;
                            resultState = ResultState.ERROR;
                            resultState.setContent("");
    
    //                showSafePage();
                            loadPage();
    
                        }
                    });
                }
            }, 2000);
        }
    
        private void loadPage()
        {
            switch (resultState)
            {
                case ERROR:
                    state_current = STATE_ERROR;
                    break;
                case EMPTY:
                    state_current = STATE_EMPTY;
                    break;
                case SUCCESS:
                    state_current = STATE_SUCCESS;
                    break;
            }
            //根据修改以后的state_current,更新视图的显示。
            showSafePage();
    
            if (state_current == STATE_SUCCESS)
            {
                onSuccss(resultState, view_success);
            }
        }
    
        /**
         * 抽象方法,当显示的是成功界面时,加载的是实际的fragment布局
         *
         * @return
         */
        public abstract int layoutId();
    
    
        /**
         * 提供联网的请求参数
         *
         * @return
         */
        protected abstract RequestParams params();
    
    
        /**
         * 提供联网的请求地址
         *
         * @return
         */
        public abstract String url();
    
        /**
         * 成功显示的页面
         * @param resultState
         * @param view_success
         */
        protected abstract void onSuccss(ResultState resultState, View view_success);
    
        /**
         * 提供枚举类,封装联网以后的状态值和数据
         */
        public enum ResultState
        {
            //public static final ERROR=new ResultState(2);一样的部分省略,不同的抽取出来,用逗号隔开
            ERROR(2), EMPTY(3), SUCCESS(4);
    
            int state;
    
            ResultState(int state)
            {
                this.state = state;
            }
    
            private String content;
    
            public String getContent()
            {
                return content;
            }
    
            public void setContent(String content)
            {
                this.content = content;
            }
        }
    }
    

    013-投资模块布局fragment_invest.xml的设置

    上面是:TabPageIndicator

    下面是:ViewPager + Fragment(3个:ProductListFragment,ProductRecommondFragment,ProductHotFragment)

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:orientation="vertical"
            >
        
            <include layout="@layout/common_title"></include>
        
            <com.viewpagerindicator.TabPageIndicator
                android:id="@+id/tabpage_invest"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"></com.viewpagerindicator.TabPageIndicator>
        
            <android.support.v4.view.ViewPager
                android:id="@+id/vp_invest"
                android:layout_width="match_parent"
                android:layout_height="match_parent"></android.support.v4.view.ViewPager>
        
        </LinearLayout>
    

    014-ViewPager+FragmentPagerAdapter显示投资整体模块数据

    /**
     * @author: Hashub
     * @WeChat: NGSHMVP
     * @Date: 2018/9/15 14:39
     * @function:投资理财fragment
     */
    public class InvestFragment extends BaseFragment
    {
        @Bind(R.id.iv_title_back)
        ImageView ivTitleBack;
        @Bind(R.id.tv_title)
        TextView tvTitle;
        @Bind(R.id.iv_title_setting)
        ImageView ivTitleSetting;
        @Bind(R.id.tabpage_invest)
        com.viewpagerindicator.TabPageIndicator tabpageInvest;
        @Bind(R.id.vp_invest)
        ViewPager vpInvest;
    
    
        @Override
        protected RequestParams getParams()
        {
            return null;
        }
    
        @Override
        protected String getUrl()
        {
            return null;
        }
    
        @Override
        protected void initData(String content)
        {
    //1.加载三个不同的Fragment:ProductListFragment,ProductRecommondFragment,ProductHotFragment.
            initFragments();
            //2.ViewPager设置三个Fragment的显示
            MyAdapter adapter = new MyAdapter(getFragmentManager());
            vpInvest.setAdapter(adapter);
            //将TabPagerIndicator与ViewPager关联
            tabpageInvest.setViewPager(vpInvest);
        }
    
        private List<Fragment> fragmentList = new ArrayList<>();
    
        private void initFragments()
        {
            ProductListFragment productListFragment = new ProductListFragment();
            ProductRecommondFragment productRecommondFragment = new ProductRecommondFragment();
            ProductHotFragment productHotFragment = new ProductHotFragment();
            //添加到集合中
            fragmentList.add(productListFragment);
            fragmentList.add(productRecommondFragment);
            fragmentList.add(productHotFragment);
        }
    
    
        protected void initTitle()
        {
            ivTitleBack.setVisibility(View.GONE);
            tvTitle.setText("投资");
            ivTitleSetting.setVisibility(View.GONE);
        }
    
        @Override
        public int getLayoutId()
        {
            return R.layout.fragment_invest;
        }
    
        /**
         * 提供PagerAdapter的实现
         * 如果ViewPager中加载的是Fragment,则提供的Adpater可以继承于具体的:FragmentStatePagerAdapter或FragmentPagerAdapter
         * FragmentStatePagerAdapter:适用于ViewPager中加载的Fragment过多,会根据最近最少使用算法,实现内存中Fragment的清理,避免溢出
         * FragmentPagerAdapter:适用于ViewPager中加载的Fragment不多时,系统不会清理已经加载的Fragment。
         */
        class MyAdapter extends FragmentPagerAdapter
        {
    
    
            public MyAdapter(FragmentManager fm)
            {
                super(fm);
            }
    
            @Override
            public Fragment getItem(int position)
            {
                return fragmentList.get(position);
            }
    
            @Override
            public int getCount()
            {
                return fragmentList == null ? 0 : fragmentList.size();
            }
    
            //提供TabPageIndicator的显示内容
            @Override
            public CharSequence getPageTitle(int position)
            {
                //方式一:
    //            if(position == 0){
    //                return "全部理财";
    //            }else if(position == 1){
    //                return "推荐理财";
    //            }else if(position == 2){
    //                return "热门理财";
    //            }
                //方式二:
                return UIUtils.getStringArr(R.array.invest_tab)[position];
            }
        }
    }
    

    关于主题:

    android:theme="@style/Theme.PageIndicatorDefaults"

    创建相应的styles.xml中的主题,并在功能清单文件中使用

    <!--自定义viewpagerIndicator样式-->
        <style name="StyledIndicators" parent="@android:style/Theme.Light">
            <item name="vpiTabPageIndicatorStyle">@style/CustomTabPageIndicator</item>
            <item name="android:windowNoTitle">true</item>
        </style>
    
        <style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
            <item name="android:background">@drawable/tab_indicator</item>
            <item name="android:textAppearance">@style/CustomTabPageIndicator.Text</item>
            <item name="android:textSize">14sp</item>
            <item name="android:dividerPadding">8dp</item>
            <item name="android:showDividers">middle</item>
            <item name="android:paddingLeft">10dp</item>
            <item name="android:paddingRight">10dp</item>
            <item name="android:fadingEdge">horizontal</item>
            <item name="android:fadingEdgeLength">8dp</item>
        </style>
    
        <style name="CustomTabPageIndicator.Text" parent="android:TextAppearance.Medium">
            <item name="android:typeface">monospace</item>
            <item name="android:textColor">@drawable/selector_tabtext</item>
        </style>
    

    关于Context的实现类:Application和Activity的不同

    ①new AlertDialog.Builder(activity):只能使用activity
    
    ②在地图的集成中:只能使用application
    
    ③Toast.makeText(application/activity):都可以使用
    
    ④View.inflate(activity,..):二者都可,但建议使用activity
    
    ⑤new TextView(activity);二者都可,但建议使用activity.
    
    ⑥其他情况下,如果使用activity会造成内存泄漏的话,建议替换为application。

    相关文章

      网友评论

          本文标题:P2PInvest笔记02

          本文链接:https://www.haomeiwen.com/subject/vnwyoftx.html