热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android使用ListView实现滚轮的动画效果实例

这篇文章主要介绍了Android使用ListView实现滚轮的动画效果实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

之前收到一个需求,需要把一个数据展示列表页面做成像滚轮那样的动画效果:中间最大然后向上下两端逐渐缩小。我想了想iOS那边自带滚轮组件,安卓得自己去实现,目前网上仿ios的滚轮组件的也有一些,但是感觉不适合我,我的要求没那么复杂,于是决定自己动手去实现一下。

动手前先分析一下应该怎么做,归根到底只是要实现缩放效果,由中间向两边变小,当一个item越接近中间就放大,越远离中间就缩小。那么可以通过先获取ListView的中点,然后获取当前可视的所有item跟ListView的中点的垂直距离计算出一个比例,然后将item的大小根据这个比例进行缩放,各个item跟ListView的中点的垂直距离不同,计算出来的比例也就不同,然后每次滚动的时候都计算比例然后进行缩放,这样应该就能实现我们想要的效果了。

因为一开始我的列表展示就是用ListView做的,有其他效果在里面,也不方便换其他组件,所以依然还是用ListView实现就好了。由于我们是每次一滚动都要进行缩放,ListView有提供一个OnScrollListener,它的onScroll方法每次一开始滚动就会调用,所以我们选择重写它。当它被调用的时候,我们就开始获取ListView中点,然后开始计算每个item的距离进行缩放.

/** 
  * 中点的Y坐标 
  */ 
  private float centerY = 0f; 
  @Override 
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
    //计算中点 
    centerY = getHeight()/2; 
    //判断中点的有效性 
    if(centerY <= 0){ 
      return; 
    } 
    //开始对当前显示的View进行缩放 
    for(int i = 0; i  centerY){ 
        distance = itemY - centerY; 
      }else{ 
        distance = centerY - itemY; 
      } 
      //根据距离进行缩放 
      temp_view.setScaleY(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      temp_view.setScaleX(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      //根据距离改变透明度 
      temp_view.setAlpha(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
    } 
  } 

后面不想加demo了,所以直接上整个ListView的代码吧

/** 
 * 模仿滚轮动画缩放的ListView 
 * Created by xu on 2017/3/3. 
 */ 
public class XuListView extends ListView implements AbsListView.OnScrollListener { 
  private static final String TAG = "XuListView"; 
 
  /** 
   * 中点的Y坐标 
   */ 
  private float centerY = 0f; 
 
  public XuListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    //设置一个滚动监听 
    setOnScrollListener(this); 
  } 
 
  @Override 
  public void onScrollStateChanged(AbsListView view, int scrollState) { 
 
  } 
 
  @Override 
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
    //计算中点 
    centerY = getHeight()/2; 
    //判断中点的有效性 
    if(centerY <= 0){ 
      return; 
    } 
    //开始对当前显示的View进行缩放 
    for(int i = 0; i  centerY){ 
        distance = itemY - centerY; 
      }else{ 
        distance = centerY - itemY; 
      } 
      //根据距离进行缩放 
      temp_view.setScaleY(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      temp_view.setScaleX(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      //根据距离改变透明度 
      temp_view.setAlpha(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
    } 
  } 
} 

这样基本就实现了我们想要的效果了

但是现在有一个问题,就是第一个item和最后一个item无法滚动到中间从而放大突出显示。对此我暂时想了两个方法去解决:1、在头尾各种添加一些空白的item,使我们需要显示的数据都可以滚动到最中间。(我现在就是这么做的);2、使整个列表实现循环滚动。

添加空白的item的话,我是通过修改adapter去实现的。数据源是一个数组,我在数组前面和后面各加一些特殊的数据,adapter实现getview的时候,如果发现当前item的数据是特殊数据,那么item就变透明,从而实现了我们原本要显示的数据都可以被滚动最中间;

先从数据源下手,从头尾填充特殊的数据

public class MainActivity extends AppCompatActivity { 
  XuListView mLisetview; 
  MyAdapter adapter; 
  ArrayList nos = new ArrayList(); 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
     
    mLisetview = (XuListView) findViewById(R.id.list_test); 
 
    ArrayList temp = new ArrayList(); 
    for(int i = 0;i<10;i++){ 
      temp.add(i+""); 
    } 
    adapter = new MyAdapter(this,temp); 
    mLisetview.setAdapter(adapter); 
    resetitem(mLisetview); 
  } 
 
  /** 
   * 在头尾填充透明的item数据 
   */ 
  private void resetitem(ListView listview) { 
 
    if(listview == null){ 
      return; 
    } 
    //获取屏幕高度 
    WindowManager wm =getWindowManager(); 
    int displayheight = wm.getDefaultDisplay().getHeight(); 
    //计算一个item的高度 
    int itemhight = 0; 
    if(adapter!=null){ 
      View v=(View)adapter.getView(0, null, listview); 
      v.measure( 
          View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 
          View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 
      itemhight=v.getMeasuredHeight(); 
    } 
    //根据Item的高度和屏幕的高度计算需要多少个item可以填满一半的屏幕 
    int newcount = ((displayheight/2)/itemhight); 
    //填充前面的空白item 
    for (int i = 1; i <= newcount; i++) { 
      nos.add("full"); 
    } 
    //添加我们需要显示的数据 
    for(int i = 0;i<10;i++){ 
      nos.add(i+""); 
    } 
    //填充后面的空白item 
    for (int i = 1; i <= newcount; i++) { 
      nos.add("full"); 
    } 
    //刷新数据 
    adapter.refreshData(nos); 
  } 
} 

然后adapter里面对头尾的特殊数据进行识别,将item变为透明的。

public class MyAdapter extends BaseAdapter { 
 
  ArrayList nos = new ArrayList(); 
  private Context context; 
 
  public MyAdapter(Context context, ArrayList nos){ 
    this.cOntext= context; 
    this.nos = nos; 
  } 
  public void refreshData(ArrayList nos) { 
    this.nos = nos; 
    notifyDataSetChanged(); 
  } 
  @Override 
  public int getCount() { 
    return nos.size(); 
  } 
 
  @Override 
  public Object getItem(int position) { 
    return nos.get(position); 
  } 
 
  @Override 
  public long getItemId(int position) { 
    return position; 
  } 
 
  @Override 
  public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    if (cOnvertView== null) { 
    // 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用) 
      holder = new ViewHolder(); 
      cOnvertView= LayoutInflater.from(context).inflate(R.layout.item_test, null); 
      holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no); 
      convertView.setTag(holder); 
    } else { 
      holder = (ViewHolder) convertView.getTag(); 
    } 
    holder.tv_no.setText(nos.get(position)); 
    if(nos.get(position).equals("full")){ 
      convertView.setVisibility(View.INVISIBLE); 
    }else{ 
      convertView.setVisibility(View.VISIBLE); 
    } 
    return convertView; 
  } 
   
   
  private class ViewHolder { 
    TextView tv_no; 
  } 
} 

 这样我们就实现可以第一种解决方法

第二种方法,就是让整个ListView实现循环滚动,实现的方式有很多,大家可以自行百度,我这里就通过修改adapter的getCount方法去实现,就是在getCount方法return一个很大的值,getView获取数据的时候要模原本的数组大小,不然数组就越界了。然后ListView滚动到最中间,这样就实现伪循环滚动了

public class MainActivity extends AppCompatActivity { 
  XuListView mLisetview; 
  MyAdapter adapter; 
  ArrayList nos = new ArrayList(); 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
 
    mLisetview = (XuListView) findViewById(R.id.list_test); 
 
    ArrayList temp = new ArrayList(); 
    for(int i = 0;i<10;i++){ 
      temp.add(i+""); 
    } 
    adapter = new MyAdapter(this,temp); 
    mLisetview.setAdapter(adapter); 
    //滚动到中间 
    mLisetview.setSelection(adapter.getCount()/2); 
  } 
 
} 
/** 
 * Created by xu on 2017/6/27. 
 */ 
public class MyAdapter extends BaseAdapter { 
 
  ArrayList nos = new ArrayList(); 
  private Context context; 
 
  public MyAdapter(Context context, ArrayList nos){ 
    this.cOntext= context; 
    this.nos = nos; 
  } 
  @Override 
  public int getCount() { 
    return Integer.MAX_VALUE; 
  } 
 
  @Override 
  public Object getItem(int position) { 
    return nos.get(position); 
  } 
 
  @Override 
  public long getItemId(int position) { 
    return position; 
  } 
 
  @Override 
  public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    if (cOnvertView== null) { 
    // 如果是第一次显示该页面(要记得保存到viewholder中供下次直接从缓存中调用) 
      holder = new ViewHolder(); 
      cOnvertView= LayoutInflater.from(context).inflate(R.layout.item_test, null); 
      holder.tv_no = (TextView) convertView.findViewById(R.id.tv_no); 
      convertView.setTag(holder); 
    } else { 
      holder = (ViewHolder) convertView.getTag(); 
    } 
    holder.tv_no.setText(nos.get(position%nos.size())); 
    return convertView; 
  } 
 
 
  private class ViewHolder { 
    TextView tv_no; 
  } 
} 

这样我们就实现了使列表进行循环滚动,从而达到每个item都可以滚动到中间突出显示的效果了

既然我们把动画效果都做出来了,那么也可以直接做成一个滚轮选择器,只需要加多两步:1、把最靠近中间的item滚动到中间;2、把中间的item的序号通过一个接口返回出去。 我就直接贴代码吧,反正也不难。

把最靠近中间的item滚动到中间的实现我是这么做的:首先决定好整个ListView可视的的item数量是多少,必须是奇数,这样才能只有一个item处于正中间,然后根据ListView的高度计算出每个item符合要求的高度,然后更改现有的item的高度,同时对内容进行缩放(不缩放内容单纯高度变小的话布局就乱了)。最后我们利用smoothScrollToPosition方法回正可视item中的第一个item,就实现了将最中间的item回滚到最中间的效果了。因为可视的item我们是根据ListView的高度去计算item的高度的,所有的可视item刚好铺满ListView,所以只要顶部那个回正了,其他的item也会回正。所以我们可以重写一下OnScrollListener的onScrollStateChanged方法,每次滚动结束就执行一次回滚

/** 
 * 可视的item数 
 */ 
private int mVisibleItemCount = -1; 
/** 
 * 没调整之前每个item的高度 
 */ 
private float olditemheight = 0; 
/** 
 * 调整过后的每个item的高度 
 */ 
private float newitemheight = -1; 
 
/** 
 * 调整每个可视的item的高度 以及对内容进行缩放 
 */ 
public void reSetItemHeight() { 
  for (int i = 0; i  0) { 
    //除不尽的情况下把余数分给各个item,暂时发现分一次余数就够了,如果效果不理想就做个递归多分几次 
    float remainder = (getHeight() / mVisibleItemCount) % newitemheight; 
    newitemheight = remainder / mVisibleItemCount; 
 
  } 
} 
 
@Override 
public void onScrollStateChanged(AbsListView view, int scrollState) { 
 
  //滚动结束之后开始回滚item 
  if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1) { 
    //使离中间最近的item回滚到中点位置 
    smoothScrollToPosition(getFirstVisiblePosition()); 
  } 
 
} 

实现了把最靠近中间的item滚动到中间,那么选择的item就是滚动结束后处于最中间的item。对此我们需要再次重写一下OnScrollListener的onScrollStateChanged方法。每次滚动结束后,取可视item中的第一个item的序号加上我们之前设置的可视item数的一半(舍去小数部分)就是最中间的item的序号了,也是当前选择项的序号。

/** 
   * 当前选中项发生变化的监听者 
   */ 
  private onSelectionChangeLisenter selectionChangeLisenter; 
 
   
  /** 
   * 设置选中项的监听者 
   */ 
  public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) { 
    this.selectiOnChangeLisenter= selectionChangeLisenter; 
  } 
   
  @Override 
  public void onScrollStateChanged(AbsListView view, int scrollState) { 
 
     //滚动结束之后开始正常回滚item并记录最中间的item为选中项 (必须设置可视项,ListView才会改为选择器模式) 
    if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){ 
      //使离中间最近的item回滚到中点位置 
      smoothScrollToPosition(getFirstVisiblePosition()); 
      //计算当前选中项的序号 
      int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2; 
      //把当前选中项的序号存起来并通过listener回调出去 
      if(selectionChangeLisenter != null && nowPosition != curPosition){ 
        curPosition = nowPosition; 
        selectionChangeLisenter.onSelectionChange(curPosition); 
      } 
    } 
 
  } 

此处我是使用了一个接口去,用以实时把最新的数据返回出去

/** 
 * Created by xu on 2017/3/3. 
 */ 
public interface onSelectionChangeLisenter { 
  void onSelectionChange(int position); 
} 

使用这个滚轮选择器的方法也非常简单,除了跟正常的ListView初始化和绑定adapter之外,只需要额外调用两个方法就行了

//设置ListView的可视item数(必须是奇数) 
    mLisetview.setVisibleItemCount(3); 
//设置监听者监听选中项的变化 
    mLisetview.setSelectionChangeLisenter(new onSelectionChangeLisenter() { 
      @Override 
      public void onSelectionChange(final int position) { 
        mHandler.post(new Runnable() { 
          @Override 
          public void run() { 
            Toast.makeText(MainActivity.this,"选择项发生变化 当前选中序号:"+(temp.get(position)),Toast.LENGTH_SHORT).show(); 
          } 
        }); 
      } 
    }); 

这样我们就实现滚轮数字选择器的效果了

现在贴下整个滚轮选择器的完整代码

/** 
 * 模仿滚轮动画缩放的ListView 
 * Created by xu on 2017/3/3. 
 */ 
public class XuListView extends ListView implements AbsListView.OnScrollListener { 
  private static final String TAG = "XuListView"; 
 
  /** 
   * 中点的Y坐标 
   */ 
  private float centerY = 0f; 
  /** 
   * 可视的item数 
   */ 
  private int mVisibleItemCount = -1; 
  /** 
   * 没调整之前每个item的高度 
   */ 
  private float olditemheight = 0; 
  /** 
   * 调整过后的每个item的高度 
   */ 
  private float newitemheight = -1; 
  /** 
   * 当前选中项发生变化的监听者 
   */ 
  private onSelectionChangeLisenter selectionChangeLisenter; 
  /** 
   * 当前选中项的序号 
   */ 
  private int curPosition = -1; 
 
  public XuListView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    //设置一个滚动监听 
    setOnScrollListener(this); 
  } 
 
  /** 
   * 设置选中项的监听者 
   */ 
  public void setSelectionChangeLisenter(onSelectionChangeLisenter selectionChangeLisenter) { 
    this.selectiOnChangeLisenter= selectionChangeLisenter; 
  } 
 
  /** 
   * 设置ListView的显示item数 
   * @param count :必须是奇数  如果为-1 则表示只是使用动画效果的普通ListView 
   */ 
  public boolean setVisibleItemCount(int count){ 
    if(count % 2 == 0){ 
      return false; 
    }else{ 
      mVisibleItemCount = count; 
      return true; 
    } 
 
  } 
 
  /** 
   * 在这里第一次调整item高度 
   */ 
  @Override 
  public void onWindowFocusChanged(boolean hasWindowFocus) { 
    super.onWindowFocusChanged(hasWindowFocus); 
    if(mVisibleItemCount != -1){ 
      getNewItemHeight(); 
      reSetItemHeight(); 
    } 
  } 
 
  /** 
   * 调整每个可视的item的高度 以及对内容进行缩放 
   */ 
  public void reSetItemHeight(){ 
    for(int i = 0; i  0){ 
      //除不尽的情况下把余数分给各个item,暂时发现分一次余数就够了,如果效果不理想就做个递归多分几次 
      float remainder = (getHeight()/mVisibleItemCount) % newitemheight; 
      newitemheight = remainder/mVisibleItemCount; 
    } 
  } 
   
  @Override 
  public void onScrollStateChanged(AbsListView view, int scrollState) { 
 
     //滚动结束之后开始正常回滚item并记录最中间的item为选中项 (必须设置可视项,ListView才会改为选择器模式) 
    if( scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && mVisibleItemCount != -1){ 
      //使离中间最近的item回滚到中点位置 
      smoothScrollToPosition(getFirstVisiblePosition()); 
      //计算当前选中项的序号 
      int nowPosition = getFirstVisiblePosition() + mVisibleItemCount/2; 
      //把当前选中项的序号存起来并通过listener回调出去 
      if(selectionChangeLisenter != null && nowPosition != curPosition){ 
        curPosition = nowPosition; 
        selectionChangeLisenter.onSelectionChange(curPosition); 
      } 
    } 
     
  } 
 
  @Override 
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
    //计算中点 
    centerY = getHeight()/2; 
    //判断中点的有效性 
    if(centerY <= 0){ 
      return; 
    } 
    //开始对当前显示的View进行缩放 
    for(int i = 0; i  centerY){ 
        distance = itemY - centerY; 
      }else{ 
        distance = centerY - itemY; 
      } 
 
      //根据距离进行缩放 
      temp_view.setScaleY(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      temp_view.setScaleX(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
      //根据距离改变透明度 
      temp_view.setAlpha(1.1f - (distance / centerY) <0 &#63; 0 : 1.1f - (distance / centerY)); 
    } 
  } 
 
} 

注释很详细 相信小白看了也没什么难度。

滚轮效果的实现方式有很多,解决头尾两个item无法滚动到中间的方法也很多,我说的方法仅供参考,没有最好的方法,只有最符合自己的需求的方法。

demo下载地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
author-avatar
手机用户2502913853
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有