问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

android动态加载view一个一个刷新怎么实现

发布网友 发布时间:2022-04-19 23:30

我来回答

2个回答

懂视网 时间:2022-04-20 03:51

这篇文章主要为大家详细介绍了Android自定义环形LoadingView效果的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

最近项目有要用到环形的进度条,Github上有一个类似的DashedCircularProgress控件,但是他画的进度是通过设置画笔的虚线效果来实现间隔的:progressPaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace}, dashSpace));如果内层还有一层圆环,在动态设置时,内层和外层有细微的偏差.于是我在原有基础上改了一个,实现了我要的效果(设置进度时可以选择加动画或者不加动画):

控件实现:

这个控件继承RelativeLayout,在onDraw时做了两件事:

1、先画出底部的黑色环形;
2、按照当时的进度值画出对应比例的外层绿色环形.

对外提供一个接口,回调当前进度值:

public interface OnValueChangeListener {
 void onValueChange(float value);
}

核心绘制类:

InternalCirclePainterImp2,绘制内层的黑色的环形:

/**
 * @author Chuck
 */
public class InternalCirclePainterImp2 implements InternalCirclePainter {

 private RectF internalCircle;//画出圆弧时,圆弧的外切矩形
 private Paint internalCirclePaint;
 private int color;
 private float startAngle = 270f;
 int arcQuantity=100;//等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔
 float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1
 private int width;
 private int height;
 private int internalStrokeWidth = 48;//圆环宽度

 public InternalCirclePainterImp2(int color, int progressStrokeWidth, int arcQuantity,float ratio) {
 this.color = color;
 this.internalStrokeWidth = progressStrokeWidth;
 this.arcQuantity = arcQuantity;
 if(ratio>0&&ratio<1){
 this.ratio = ratio;
 }

 init();
 }

 private void init() {
 initExternalCirclePainter();
 }

 private void initExternalCirclePainter() {
 internalCirclePaint = new Paint();
 internalCirclePaint.setAntiAlias(true);
 internalCirclePaint.setStrokeWidth(internalStrokeWidth);
 internalCirclePaint.setColor(color);
 internalCirclePaint.setStyle(Paint.Style.STROKE);

 }

 //圆弧外切矩形
 private void initExternalCircle() {
 internalCircle = new RectF();
 float padding = internalStrokeWidth * 0.5f;
 internalCircle.set(padding, padding , width - padding, height - padding);
 initExternalCirclePainter();
 }


 @Override
 public void draw(Canvas canvas) {

 float eachAngle=360f/arcQuantity;

 float eachArcAngle=eachAngle*ratio;

 for(int i=0;i<arcQuantity*2;i++){
 if(i%2==0){//遇到偶数就画圆弧,基数则跳过
 canvas.drawArc(internalCircle, startAngle+eachAngle*i/2, eachArcAngle, false, internalCirclePaint);
 }
 else{
 continue;
 }
 }

 }

 public void setColor(int color) {
 this.color = color;
 internalCirclePaint.setColor(color);
 }

 @Override
 public int getColor() {
 return color;
 }

 @Override
 public void onSizeChanged(int height, int width) {
 this.width = width;
 this.height = height;
 initExternalCircle();
 }
}

ProgressPainterImp2,绘制内层的黑色的环形:

/**
 * @author Chuck
 */
public class ProgressPainterImp2 implements ProgressPainter {

 private RectF progressCircle;
 private Paint progressPaint;
 private int color = Color.RED;
 private float startAngle = 270f;
 private int internalStrokeWidth = 48;
 private float min;
 private float max;
 private int width;
 private int height;

 private int currentPecent;//当前的百分比

 int arcQuantity=100;//等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔
 float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1

 public ProgressPainterImp2(int color, float min, float max, int progressStrokeWidth, int arcQuantity,float ratio) {
 this.color = color;
 this.min = min;
 this.max = max;
 this.internalStrokeWidth = progressStrokeWidth;
 this.arcQuantity = arcQuantity;
 this.ratio = ratio;
 init();
 Log.e("ProgressPainterImp","构造函数执行");
 }

 private void init() {
 initInternalCirclePainter();

 }

 private void initInternalCirclePainter() {
 progressPaint = new Paint();
 progressPaint.setAntiAlias(true);
 progressPaint.setStrokeWidth(internalStrokeWidth);
 progressPaint.setColor(color);
 progressPaint.setStyle(Paint.Style.STROKE);

 }

 //初始化外切的那个矩形
 private void initInternalCircle() {
 progressCircle = new RectF();
 float padding = internalStrokeWidth * 0.5f;
 progressCircle.set(padding, padding , width - padding, height - padding);

 initInternalCirclePainter();
 }

 @Override
 public void draw(Canvas canvas) {

 float eachAngle=360f/arcQuantity;

 float eachArcAngle=eachAngle*ratio;

 int quantity=2*arcQuantity*currentPecent/100;
 for(int i=0;i<quantity;i++){
 if(i%2==0){//遇到偶数就画圆弧,基数则跳过
 canvas.drawArc(progressCircle, startAngle+eachAngle*i/2, eachArcAngle, false, progressPaint);
 }
 else{
 continue;
 }
 }
 }

 public float getMin() {
 return min;
 }

 public void setMin(float min) {
 this.min = min;
 }

 public float getMax() {
 return max;
 }

 public void setMax(float max) {
 this.max = max;
 }

 public void setValue(float value) {
 this.currentPecent = (int) (( 100f * value) / max);
 }

 @Override
 public void onSizeChanged(int height, int width) {
 Log.e("ProgressPainterImp","onSizeChanged执行");

 this.width = width;
 this.height = height;
 initInternalCircle();
 }

 public int getColor() {
 return color;
 }

 public void setColor(int color) {
 this.color = color;
 progressPaint.setColor(color);
 }
}

可以自定义的属性:

<declare-styleable name="CircularLoadingView">
 <attr name="base_color" format="color" /> <!--内层圆环的颜色-->
 <attr name="progress_color" format="color" /><!--进度圆环的颜色-->
 <attr name="max" format="float" /><!--最小值-->
 <attr name="min" format="float" /><!--最大值-->
 <attr name="duration" format="integer" /><!--动画时长-->
 <attr name="progress_stroke_width" format="integer" /><!--圆环宽度-->

 <!--等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔-->
 <attr name="argQuantity" format="integer" />
 
 <!--每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1-->
 <attr name="ratio" format="float" />
</declare-styleable>

调用:

main_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 xmlns:custom="http://schemas.android.com/apk/res-auto"
 android:background="#ffffff"
 >

 <!--自定义控件,继承RelativeLayout-->
 <qdong.com.mylibrary.CircularLoadingView
 android:id="@+id/simple"
 custom:base_color="@color/pager_bg"
 custom:min="0"
 custom:max="100"
 custom:argQuantity="100"
 custom:ratio="0.6"
 custom:progress_color="@android:color/holo_green_light"
 custom:progress_icon="@mipmap/ic_launcher"
 custom:duration="1000"
 custom:progress_stroke_width="28"
 android:layout_centerInParent="true"
 android:layout_width="200dp"
 android:layout_height="200dp">

 <RelativeLayout
 android:layout_centerInParent="true"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 

 <TextView
  android:layout_centerInParent="true"

  android:textSize="20sp"
  android:layout_centerHorizontal="true"
  android:id="@+id/number"
  android:text="0"
  android:gravity="center"
  android:textColor="@color/pager_bg"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />

 </RelativeLayout>

 </qdong.com.mylibrary.CircularLoadingView>

 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Set_Value"
 android:id="@+id/button"
 android:layout_alignParentBottom="true"
 android:layout_alignParentStart="true"/>

 <Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Animation"
 android:id="@+id/button3"
 android:layout_alignTop="@+id/button"
 android:layout_alignParentEnd="true"/>
</RelativeLayout>

MainActivity:

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 try {
 mDashedCircularProgress.setValue(66);//没有动画的,直接设置
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
});
findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 try {
 mDashedCircularProgress.setValue(0);//无动画,归零
 mDashedCircularProgress.setValueWithAnimation(100,2000);//带动画
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
});

Github地址:https://github.com/506954774/AndroidCircularLoadingView

热心网友 时间:2022-04-20 00:59

先看一下结构图

可以看到ViewSwitcher和ViewFlipper都是继承自ViewAnimator。


下面通过一个Demo了解一下ViewFlipper的用法

main.xml

Html代码

<?xml version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="htt p:/ /schemas.andro id.co m/apk/res/android"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:orientation="vertical" >  

  

    <ViewFlipper  

        android:id="@+id/viewFlipper"  

        android:layout_width="fill_parent"  

        android:layout_height="fill_parent" >  

  

        <include  

            android:id="@+id/layout01"  

            layout="@layout/layout01" />  

  

        <include  

            android:id="@+id/layout02"  

            layout="@layout/layout02" />  

    </ViewFlipper>  

  

</LinearLayout>  


layout01.xml

Html代码

<?xml version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="htt p:/ /schem as.andro id.c om/apk/res/android"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:orientation="vertical" >  

  

    <TextView  

        android:layout_width="fill_parent"  

        android:layout_height="fill_parent"  

        android:gravity="center"  

        android:text="一个TextView"  

        android:textSize="40dip" />  

  

</LinearLayout>  


layout02.xml

Html代码

<?xml version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="htt p://schema s.andro id.c om/apk/res/android"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:orientation="vertical" >  

  

    <LinearLayout  

        android:layout_width="fill_parent"  

        android:layout_height="fill_parent"  

        android:gravity="center"  

        android:orientation="vertical" >  

  

        <ImageView  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:src="@drawable/ic_launcher" />  

  

        <TextView  

            android:layout_width="wrap_content"  

            android:layout_height="wrap_content"  

            android:text="一个TextView + 一个ImageView"  

            android:textSize="20dip" />  

    </LinearLayout>  

  

</LinearLayout>  


ViewFlipperDemoActivity.java

Java代码

package com.tianjf;  

  

import android.app.Activity;  

import android.os.Bundle;  

import android.view.MotionEvent;  

import android.view.View;  

import android.view.View.OnTouchListener;  

import android.view.animation.AnimationUtils;  

import android.widget.ViewFlipper;  

  

public class ViewFlipperDemoActivity extends Activity implements  

        OnTouchListener {  

  

    private ViewFlipper viewFlipper;  

  

    // 左右滑动时手指按下的X坐标  

    private float touchDownX;  

    // 左右滑动时手指松开的X坐标  

    private float touchUpX;  

  

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.main);  

  

        viewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);  

        viewFlipper.setOnTouchListener(this);  

    }  


        }  

  

        float XFrom = e1.getX();  

        float XTo = e2.getX();  

        float YFrom = e1.getY();  

        float YTo = e2.getY();  

        // 左右滑动的X轴幅度大于100,并且X轴方向的速度大于100  

        if (Math.abs(XFrom - XTo) > 100.0f && Math.abs(speedX) > 100.0f) {  

            // X轴幅度大于Y轴的幅度  

            if (Math.abs(XFrom - XTo) >= Math.abs(YFrom - YTo)) {  

                if (XFrom > XTo) {  

                    // 下一个  

                    mOnFlingListener.flingToNext();  

                } else {  

                    // 上一个  

                    mOnFlingListener.flingToPrevious();  

                }  

            }  

        } else {  

            return false;  

        }  

        return true;  

    }  

  

    public interface OnFlingListener {  

        void flingToNext();  

  

        void flingToPrevious();  

    }  

}  


MyViewFlipper.java

Java代码

package com.tianjf;  

  

import com.tianjf.MyGestureListener.OnFlingListener;  

  

import android.content.Context;  

import android.util.AttributeSet;  

import android.view.GestureDetector;  

import android.view.MotionEvent;  

import android.view.View;  

import android.widget.ViewFlipper;  

  

public class MyViewFlipper extends ViewFlipper implements OnFlingListener {  

  

    private GestureDetector mGestureDetector = null;  

  

    private OnViewFlipperListener mOnViewFlipperListener = null;  

  

    public MyViewFlipper(Context context) {  

        super(context);  

    }  

  

    public MyViewFlipper(Context context, AttributeSet attrs) {  

        super(context, attrs);  

    }  

  

    public void setOnViewFlipperListener(OnViewFlipperListener mOnViewFlipperListener) {  

        this.mOnViewFlipperListener = mOnViewFlipperListener;  

        MyGestureListener myGestureListener = new MyGestureListener();  

        myGestureListener.setOnFlingListener(this);  

        mGestureDetector = new GestureDetector(myGestureListener);  

    }  

  

    @Override  

    public boolean onInterceptTouchEvent(MotionEvent ev) {  

        if (null != mGestureDetector) {  

            return mGestureDetector.onTouchEvent(ev);  

        } else {  

            return super.onInterceptTouchEvent(ev);  

        }  

    }  

  

    @Override  

    public void flingToNext() {  

        if (null != mOnViewFlipperListener) {  

            int childCnt = getChildCount();  

            if (childCnt == 2) {  

                removeViewAt(1);  

            }  

            addView(mOnViewFlipperListener.getNextView(), 0);  

            if (0 != childCnt) {  

                setInAnimation(getContext(), R.anim.left_slip_in);  

                setOutAnimation(getContext(), R.anim.left_slip_out);  

                setDisplayedChild(0);  

            }  

        }  

    }  

  

    @Override  

    public void flingToPrevious() {  

        if (null != mOnViewFlipperListener) {  

            int childCnt = getChildCount();  

            if (childCnt == 2) {  

                removeViewAt(1);  

            }  

            addView(mOnViewFlipperListener.getPreviousView(), 0);  

            if (0 != childCnt) {  

                setInAnimation(getContext(), R.anim.right_slip_in);  

                setOutAnimation(getContext(), R.anim.right_slip_out);  

                setDisplayedChild(0);  

            }  

        }  

    }  

  

    public interface OnViewFlipperListener {  

        View getNextView();  

  

        View getPreviousView();  

    }  

}  


ViewFlipperDemoActivity.java

Java代码

package com.tianjf;  

  

import com.tianjf.MyViewFlipper.OnViewFlipperListener;  

  

import android.app.Activity;  

import android.os.Bundle;  

import android.view.LayoutInflater;  

import android.view.View;  

import android.widget.ScrollView;  

import android.widget.TextView;  

  

public class ViewFlipperDemoActivity extends Activity implements OnViewFlipperListener {  

  

    private MyViewFlipper myViewFlipper;  

    private int currentNumber;  

  

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.main);  

  

        currentNumber = 1;  

        myViewFlipper = (MyViewFlipper) findViewById(R.id.myViewFlipper);  

        myViewFlipper.setOnViewFlipperListener(this);  

        myViewFlipper.addView(creatView(currentNumber));  

    }  

  

    @Override  

    public View getNextView() {  

        currentNumber = currentNumber == 10 ? 1 : currentNumber + 1;  

        return creatView(currentNumber);  

    }  

  

    @Override  

    public View getPreviousView() {  

        currentNumber = currentNumber == 1 ? 10 : currentNumber - 1;  

        return creatView(currentNumber);  

    }  

  

    private View creatView(int currentNumber) {  

        LayoutInflater layoutInflater = LayoutInflater.from(this);  

        ScrollView resultView = (ScrollView) layoutInflater.inflate(R.layout.flipper_view, null);  

        ((TextView) resultView.findViewById(R.id.textView)).setText(currentNumber + "");  

        return resultView;  

    }  

}  


好了,代码上完了,开始讲解!

ViewFilpper的showPrevious()方法和showNext()方法是用来显示已经在布局文件中定义好了的View,现在我们没有在布局文件中为ViewFlipper添加View,那么showPrevious()方法和showNext()方法就不能用了。但是我们怎么实现滑动来切换View呢?用什么方法呢?

这时候,我们就要自定义一个MyViewFlipper来监听滑动事件,并做切换视图的处理。

你可以让MyViewFlipper实现OnTouchListener接口,然后实现onTouch方法,然后根据MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP的坐标判断是不是滑动事件,就像ImageSwitcher中讲解的那样(htt p://bl og.csd n.n et/tianjf0514/article/details/7556487)

除了自己判断是不是滑动事件,那么Android有没有直接提供哪个方法作为滑动事件的回调函数呢?答案是:提供了。OnGestureListener中的onFling方法就是滑动事件的回调函数。这时候你也许会毫不犹豫的让MyViewFlipper实现OnGestureListener接口,并复写onFling方法。这样做当然可以,不过实现OnGestureListener接口不仅仅要复写onFling方法,还要复写其他的方法(onDown()、onShowPress()、onSingleTapUp()、onScroll()、onLongPress()),但是这些回调函数我们不需要,这就造成了垃圾代码。

为了避免垃圾代码,Android提供了一个类SimpleOnGestureListener已经实现了OnGestureListener接口和OnDoubleTapListener接口,并复写了所有方法。那么我们只要新建一个自己的MyGestureListener.java来继承SimpleOnGestureListener,并有选择性的复写需要的方法(我们在此只复写onFling方法)。

这时,我们就自定义了一个手势类,并且这个手势类会监听滑动事件来做一些处理。但是我们怎么利用这个手势类呢?怎么利用到MyViewFlipper类中去呢?

关于onFling方法,有一点要注意:不是每个View都能有onFling回调函数,一开始,我的flipper_view.xml布局文件最外层是一个LinearLayout,死活都走不到onFling方法,后来在外层又套了一个ScrollView,就能正常走到OnFling方法里面了。

可以看到flingToNext方法和flingToPrevious方法里面会判断childCnt,如果为2,就removeViewAt(1);,然后再addView(mOnViewFlipperListener.getNextView(), 0);。这就要回顾一下ImageSwitcher的原理,ViewFlipper的原理和ImageSwitcher一样,有且仅有2个子View,滑动时候就在这两个子View上来回切换。index为0的就是当前看到的,index为1的就是看不见的。上面代码的意思就是:当滑动时,必然要新添加一个View,那么子View的个数有可能大于2,随意要先判断一下如果childCnt == 2,那么就把index == 1的那个View(即看不见的View)给Remove调,然后把新添加的View添加到index == 0处。这样可以减少内存消耗。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
给利达消防电话插孔h丫5714b上怎么编码呢? 一个手机号码怎么创两个号 微信注册小号用同一个手机号-怎么用一个手机号注册两个微信 谁懂男人心?感情问题求助 从哪些细节可以看出一个男人是不是百分之一百的真心 天通猫哪家好 211一本 城市规划专业的 今年大三 全部加权平均分81.5 只算专业课的... 什么叫头部券商 《重装机兵》那些经典的卖战车桥段,还记得帕特港买蓝色战车吗?_百度... 钢之季节情节简述 江苏省盐城市有什么特别的地方啊? 想知道: 盐城市 是否属于北极 在哪 《影视大全》和《360影视大全》这两个应用那个更好用和不用会员 盐城是哪座城市 盐城是什么地方啊 江苏盐城市在江苏什么地方 想知道: 盐城市在哪? 怎么将word文档转化为pdf文档 在贵阳营养师证好考吗??? 想考个证,消防师证与健康管理师证,营养师证哪个好考? 1. 房地产单个楼盘调研主要包括哪些内容? android 开发 imgview 怎么弄成圆形 领导对下属工作认可的简短评语 东南亚排名靠前的公立大学 本人高二,想高三毕业后去马来西亚留学,公立大学费用多少?那所学校比较不错? pscc版的字体怎样用不了 这样的字体在PScc上面怎么做?是直接下载字体还是咋回事?求大神讲解 谁有PScc2015的字体素材?? 克拉玛依的生活怎么样? PS CC 版字体素材哪里有下载 致胜2.3车子打着倒车雷达响两声再不响啦什么情况? 09年致胜倒车雷达设置 到车雷达有图像没有声音怎么办啊? 倒车雷达有显示无声音 突然倒车雷达不响了,转向灯也没有哒哒声了,怎么回事 怎么我的倒车雷达没有声音了 长安福特蒙迪欧致胜08年倒车 雷达无响应是什么问题 致胜倒车经常显示故障,倒车雷达功能失效,有时候又很正常,线路插口检测正常,请教高手,谢谢,急 2013款蒙迪欧1、5t倒车雷达没声音怎么调 蒙迪欧致胜的倒车雷达提示音的音量怎么能调大一些? 致胜的倒车雷达时好时坏 有谁类似过这样的问题 福特翼虎倒车雷达不响了就连车内中控台上的按键都没有声音了是什么问题? 一部小说男主小时候没有父亲很穷学生时代就喜欢女主但是女主不喜欢他 穷男主暗恋富人家的女主 女主姓谢男主卑微暗恋女主的古代言情 一年级上册老师的语文书长什么样写的是什么字 男女主是高中同学,女主暗恋男主,男主也知道,男主家里特别穷,靠他母亲捡破烂为生,这是什么小说 一年级上册语文书 一年级上册都是有哪几本书? 天津市预约科目一考试怎么约不上去