4.5.3 Go Android 下拉刷新的整理:SwipeRefreshLayout,android-Ultra-Pull-To-Refresh(ptr),PullToRefreshListView

本文主要是介绍4.5.3 Go Android 下拉刷新的整理:SwipeRefreshLayout,android-Ultra-Pull-To-Refresh(ptr),PullToRefreshListView,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1: 使用SwipeRefreshLayout 来实现下拉刷新和上拉加载, 和RecyclerView 来实现


http://blog.csdn.net/Rodulf/article/details/50514742


首先获取mSwipeRefreshLayout =(SwipeRefreshLayout)ret.findViewById(R.id.leibie_swiperefreshlayout);
然后可以设置这个SwipeRefreshLayout
mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE, Color.CYAN);
        mSwipeRefreshLayout.setSize(SwipeRefreshLayout.LARGE);


下拉刷新可以直接通过onRefresh 来执行。
然后在回调方法里面执行请求:
    @Override
    public void onRefresh() {
        HttpUtils.getLeiBieService().getLeiBie(1446).enqueue(this);
    }
}


上拉加载的实现是通过:例如这里是RecyclerView,设置一个监听器,在这里面有两个方法onScrolled,onScrollStateChanged
里面设置一个全局变量lastVisisbleItem,这个值在每次的onScrolled 里面修改,在最后的onScrollStateChanged里面 判断状态是否为SCROLL_STATE_IDEL
就是滑动结束,如果是的话,在判断这个lastViewItem是否到底了,到底了就进行加载的操作。


mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {  
  
   @Override  
   public void onScrollStateChanged(RecyclerView recyclerView,  
     int newState) {  
    super.onScrollStateChanged(recyclerView, newState);  
    if (newState == RecyclerView.SCROLL_STATE_IDLE  
      && lastVisibleItem + 1 == adapter.getItemCount()) {  
     mSwipeRefreshWidget.setRefreshing(true);  
     // 此处在现实项目中,请换成网络请求数据代码,sendRequest .....  
     handler.sendEmptyMessageDelayed(0, 3000);  
    }  
   }
  


   @Override  
   public void onScrolled(RecyclerView recyclerView, int dx, int dy) {  
    super.onScrolled(recyclerView, dx, dy);  
    lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();  
   }  
  
  });  


我之前的 代码:
mouge_lei_bie_detail_recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
            /**
             * 在这个方法里面判断当前状态是不是SCROLL_STATE_IDLE,并且 最后一个可见的Item也就是lastVisibleItem
             * 是倒数第二个 数据 ,如果两个条件都满足,那么进行上拉加载的操作,就是发送一个 新的handle的消息。
             * 这个消息的what是ADD
             */
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(newState==RecyclerView.SCROLL_STATE_IDLE&&lastVisibleItem+1==adapter.getItemCount()){
                        Message message = new Message();
                        message.what=ADD;
                        handler.sendMessage(message);
                }
            }


            /**
             * 通过recyclerView_layoutManager,这个recyclerView_layoutManager是通过下面的两句话来设置的
             * recyclerView_layoutManager = new LinearLayoutManager(this);
             * mouge_lei_bie_detail_recyclerView.setLayoutManager(recyclerView_layoutManager);
             * 得到最后一个可见的item的位置,并且把这个传递给变量lastVisibleItem ,
             */
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                lastVisibleItem = recyclerView_layoutManager.findLastVisibleItemPosition();
            }
        });




关于 state 还有 2中状态:
SCROLL_STATE_TOUCH_SCROLL:  // 手指触屏拉动准备滚动,只触发一次        
        SCROLL_STATE_FLING:  // 持续滚动开始,只触发一次 
        SCROLL_STATE_IDLE:  // 整个滚动事件结束,只触发一次 






2: 使用PullToRefresh 来实现下拉刷新,上拉加载,里面可以添加一个Header
http://blog.csdn.net/rodulf/article/details/50766369
首先将这个包导入为model。
<com.handmark.pulltorefresh.library.PullToRefreshListView  
        xmlns:ptr = "http://schemas.android.com/apk/res-auto"   
        android:id="@+id/pull_refresh_list"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:dividerHeight="4dp"  
        android:fadingEdge="none"  
        android:fastScrollEnabled="false"  
        android:footerDividersEnabled="false"  
        android:headerDividersEnabled="false"  
        android:smoothScrollbar="true"  
        ptr:ptrMode="both"  
         />  
在布局里面要设置几个参数,最重要的是要设置这个ptrMode 为Both,ptr:ptrMode="both" 
android:fadingEdge="none"  
        android:fastScrollEnabled="false"  
        android:footerDividersEnabled="false"  
        android:headerDividersEnabled="false"  
        android:smoothScrollbar="true"  
        ptr:ptrMode="both" 


然后在activity 中获取这个PullToRefreshListView
通过 setOnRefreshListener 来添加 监听器。 监听器里面有两个方法:onPullDownToRefresh,onPullUpToRefresh


mPullRefreshListView.setOnRefreshListener(new OnRefreshListener2<ListView>() {  
            @Override  
            public void onPullDownToRefresh( PullToRefreshBase<ListView> refreshView) {  
                Toast.makeText(MainActivity.this, "onPullDownToRefresh", Toast.LENGTH_SHORT).show();  
                new GetDataTask().execute();  
            }  
            @Override  
            public void onPullUpToRefresh( PullToRefreshBase<ListView> refreshView) {  
                Toast.makeText(MainActivity.this, "onPullUpToRefresh", Toast.LENGTH_SHORT).show();  
                new GetDataTask().execute();  
            }  
        });  


获取ListView,然后就是直接使用listview的添加adapter这些东西了。


ListView actualListView =mPullRefreshListView.getRefreshableView()
通过registerForContextMenu(actualListView)来注册上下文茶蛋
mListItems = new LinkedList<String>();
mListItems.addAll();
mAdapter= new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mListItems);
actualListView.setAdapter(mAdapter);




在 请求的里面进行添加:通过mAdapter.notifyDataSetChanged()来通知变化。


 protected void onPostExecute(String[] result) {  
              
            //向RefreshListView Item 添加一行数据  并刷新ListView  
            //mListItems.addLast("Added after refresh...");  
            mListItems.addFirst("Added after refresh...");  
            mAdapter.notifyDataSetChanged();  
  
            //通知RefreshListView 我们已经更新完成  
            // Call onRefreshComplete when the list has been refreshed.  
            mPullRefreshListView.onRefreshComplete();  
  
            super.onPostExecute(result);  
        }  


这里面可以通过,设置一个page 的全局变量,在进行数据请求的时候,
先判断这个变量,如果是1 的话,就进行重新的加载
如果是大于1的话就进行,添加的操作。




/** 
         *   设置下拉刷新和上拉加载时的 铃声(可有可无) 
         */  
        SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(this);  
        soundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event);  
        soundListener.addSoundEvent(State.RESET, R.raw.reset_sound);  
        soundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound);  
        mPullRefreshListView.setOnPullEventListener(soundListener);  

<?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="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"><!--  xmlns:ptr = "http://schemas.android.com/apk/res-auto"  为我们要使用PullToRefresh 里面一些属性需要引的命名空间 -->
    <com.handmark.pulltorefresh.library.PullToRefreshListView
        xmlns:ptr = "http://schemas.android.com/apk/res-auto"
        android:id="@+id/pull_refresh_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="4dp"
        android:fadingEdge="none"
        android:fastScrollEnabled="false"
        android:footerDividersEnabled="false"
        android:headerDividersEnabled="false"
        android:smoothScrollbar="true"
        ptr:ptrMode="both"
        />
</RelativeLayout>



package tech.androidstudio.pulltorefresh;import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.handmark.pulltorefresh.library.extras.SoundPullEventListener;import java.util.Arrays;
import java.util.LinkedList;public class MainActivity extends AppCompatActivity {static final int MENU_MANUAL_REFRESH = 0;static final int MENU_DISABLE_SCROLL = 1;static final int MENU_SET_MODE = 2;static final int MENU_DEMO = 3;private LinkedList<String> mListItems;private PullToRefreshListView mPullRefreshListView;private ArrayAdapter<String> mAdapter;private int mPage=1;@Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);/**
         * 实现 接口  OnRefreshListener2<ListView>  以便与监听  滚动条到顶部和到底部
         */
        mPullRefreshListView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {@Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {Toast.makeText(MainActivity.this, "onPullDownToRefresh", Toast.LENGTH_SHORT).show();mPage=1;new GetDataTask().execute();}@Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {Toast.makeText(MainActivity.this, "onPullUpToRefresh", Toast.LENGTH_SHORT).show();mPage++;new GetDataTask().execute();}});ListView actualListView = mPullRefreshListView.getRefreshableView();// Need to use the Actual ListView when registering for Context Menu
        registerForContextMenu(actualListView);mListItems = new LinkedList<String>();mListItems.addAll(Arrays.asList(mStrings));mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);/**
         * Add Sound Event Listener
         */

        /**
         *   设置下拉刷新和上拉加载时的 铃声(可有可无)
         */
        SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(this);
//        soundListener.addSoundEvent(PullToRefreshBase.State.PULL_TO_REFRESH, R.raw.pull_event);
//        soundListener.addSoundEvent(PullToRefreshBase.State.RESET, R.raw.reset_sound);
//        soundListener.addSoundEvent(PullToRefreshBase.State.REFRESHING, R.raw.refreshing_sound);
        mPullRefreshListView.setOnPullEventListener(soundListener);// You can also just use setListAdapter(mAdapter) or
        // mPullRefreshListView.setAdapter(mAdapter)
        actualListView.setAdapter(mAdapter);}//模拟网络加载数据的   异步请求类
    //
    private class GetDataTask extends AsyncTask<Void, Void, String[]> {//子线程请求数据
        @Override
        protected String[] doInBackground(Void... params) {// Simulates a background job.
            try {Thread.sleep(10);} catch (InterruptedException e) {}return mStrings;}//主线程更新UI
        @Override
        protected void onPostExecute(String[] result) {//RefreshListView Item 添加一行数据  并刷新ListView
            //mListItems.addLast("Added after refresh...");
            if(mPage==1){mListItems.clear();mListItems.addAll(Arrays.asList(mStrings));}else {mListItems.addFirst("Added after refresh...");}mAdapter.notifyDataSetChanged();//通知RefreshListView 我们已经更新完成
            // Call onRefreshComplete when the list has been refreshed.
            mPullRefreshListView.onRefreshComplete();super.onPostExecute(result);}}//数据源
    private String[] mStrings = { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi","Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre","Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi","Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre","Allgauer Emmentaler" };
}





3: 使用Utrl-PullToRefresh 来实现下拉刷新,里面可以添加一个Header
https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh


首先 导入包:in.srain.cube:ultra-ptr:1.0.11
导入布局进去in.srain.cube.views.ptr.PtrFrameLayout


<in.srain.cube.views.ptr.PtrFrameLayout
    android:id="@+id/store_house_ptr_frame"
    xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"


    cube_ptr:ptr_resistance="1.7"
    cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
    cube_ptr:ptr_duration_to_close="300"
    cube_ptr:ptr_duration_to_close_header="2000"
    cube_ptr:ptr_keep_header_when_refresh="true"
    cube_ptr:ptr_pull_to_fresh="false" >


    <LinearLayout
        android:id="@+id/store_house_ptr_image_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/cube_mints_333333"
        android:clickable="true"
        android:padding="10dp">


        <in.srain.cube.image.CubeImageView
            android:id="@+id/store_house_ptr_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>


</in.srain.cube.views.ptr.PtrFrameLayout>




在 布局里面获取然后设置头部。


        final PtrFrameLayout ptrFrameLayout = (PtrFrameLayout)findViewById(R.id.store_house_ptr_frame);
        StoreHouseHeader header = new StoreHouseHeader(this);
        header.setPadding(0, 20, 0, 20);
        header.initWithString("Updating");


        ptrFrameLayout.setDurationToCloseHeader(2500);
        ptrFrameLayout.setHeaderView(header);
        ptrFrameLayout.addPtrUIHandler(header);




设置数据Handler:这里面有onRefreshBegin里面开始数据加载,
然后在checkCanDoRefresh里面判断是否进行刷新。


        ptrFrameLayout.setPtrHandler(new PtrHandler() {
            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
            }


            @Override
            public void onRefreshBegin(PtrFrameLayout frame) {
                mPage=1;
                new GetDataTask().execute();


                ptrFrameLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ptrFrameLayout.refreshComplete();
                    }
                }, 1500);
            }
        });


    }

完整的代码:


上拉加载和上面的一样只是在listView.setOnScrollListener(this);
注意了这里是setOnScrollListener(this),setOnScrollChangeListener(this);


@Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
            if(scrollState==AbsListView.OnScrollListener.SCROLL_STATE_IDLE&&
                    view.getLastVisiblePosition()>=list.size()-1){
                mPage++;
                new GetDataTask().execute();
            }
    }


    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            

    }


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"><in.srain.cube.views.ptr.PtrFrameLayout
        android:id="@+id/store_house_ptr_frame"
        xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        cube_ptr:ptr_resistance="1.7"
        cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
        cube_ptr:ptr_duration_to_close="300"
        cube_ptr:ptr_duration_to_close_header="2000"
        cube_ptr:ptr_keep_header_when_refresh="true"
        cube_ptr:ptr_pull_to_fresh="false" ><ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/list_item"></ListView></in.srain.cube.views.ptr.PtrFrameLayout></LinearLayout>

package tech.androidstudio.ultrapulltorefreshdemo;import android.os.AsyncTask;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.ListView;import java.util.ArrayList;
import java.util.Arrays;import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.PtrHandler;
import in.srain.cube.views.ptr.PtrUIHandler;
import in.srain.cube.views.ptr.header.StoreHouseHeader;
import in.srain.cube.views.ptr.indicator.PtrIndicator;public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener {private ArrayList<String> list;private ArrayAdapter<String> adapter;private int mPage=1;@Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ListView listView =(ListView)findViewById(android.support.v7.appcompat.R.id.list_item);list = new ArrayList<String>();adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, list);listView.setAdapter(adapter);listView.setOnScrollListener(this);final PtrFrameLayout ptrFrameLayout = (PtrFrameLayout)findViewById(R.id.store_house_ptr_frame);StoreHouseHeader header = new StoreHouseHeader(this);header.setPadding(0, 20, 0, 20);header.initWithString("Updating");ptrFrameLayout.setDurationToCloseHeader(2500);ptrFrameLayout.setHeaderView(header);ptrFrameLayout.addPtrUIHandler(header);ptrFrameLayout.setPtrHandler(new PtrHandler() {@Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);}@Override
            public void onRefreshBegin(PtrFrameLayout frame) {mPage=1;new GetDataTask().execute();ptrFrameLayout.postDelayed(new Runnable() {@Override
                    public void run() {ptrFrameLayout.refreshComplete();}}, 1500);}});}@Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {if(scrollState==AbsListView.OnScrollListener.SCROLL_STATE_IDLE&&view.getLastVisiblePosition()>=list.size()-1){mPage++;new GetDataTask().execute();}}@Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}//模拟网络加载数据的   异步请求类
    //
    private class GetDataTask extends AsyncTask<Void, Void, String[]> {//子线程请求数据
        @Override
        protected String[] doInBackground(Void... params) {// Simulates a background job.
            try {Thread.sleep(10);} catch (InterruptedException e) {}return new String[]{"hello"};}//主线程更新UI
        @Override
        protected void onPostExecute(String[] result) {if(mPage==1) {list.clear();list.addAll(Arrays.asList(array));}else{list.add("new");}adapter.notifyDataSetChanged();//RefreshListView Item 添加一行数据  并刷新ListView
            //mListItems.addLast("Added after refresh...");
            super.onPostExecute(result);}}private String[] array={"0","1","2","3","1","2","3","1","2","3","1","2","3","1","2","3","1","2","3"};}


这篇关于4.5.3 Go Android 下拉刷新的整理:SwipeRefreshLayout,android-Ultra-Pull-To-Refresh(ptr),PullToRefreshListView的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/196799

相关文章

Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题

《Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题》:本文主要介绍Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录一、前言二、系统架构检测三、卸载旧版 Go四、下载并安装正确版本五、配置环境变量六、验证安装七、常见

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

Spring Boot 常用注解整理(最全收藏版)

《SpringBoot常用注解整理(最全收藏版)》本文系统整理了常用的Spring/SpringBoot注解,按照功能分类进行介绍,每个注解都会涵盖其含义、提供来源、应用场景以及代码示例,帮助开发... 目录Spring & Spring Boot 常用注解整理一、Spring Boot 核心注解二、Spr

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮