服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android集成腾讯X5实现文档浏览功能

Android集成腾讯X5实现文档浏览功能

2022-11-03 15:41hardWork_yulu Android

Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题这篇文章主要介绍了Android集成腾讯X5实现文档浏览功能,需要的朋友可以参考下

Android内部没有控件来直接显示文档,跳转WPS或其他第三方文档App体验性不好,使用腾讯X5内核能很好的解决的这一问题。

一、下载腾讯X5内核

1.前往https://x5.tencent.com/下载Android的内核,新版本的腾讯X5可以直接在bulid.gradle集成 api 'com.tencent.tbs.tbssdk:sdk:43697',如果是在App里集成可以把api换成implementation

Android集成腾讯X5实现文档浏览功能

2.AndroidStudio导入腾讯X5

a.把下载好的jar包导入libs,然后run as,再把jnilibs导入main包下

Android集成腾讯X5实现文档浏览功能

b. module的build.gradle添加cpu适配

Android集成腾讯X5实现文档浏览功能

3.Application中腾讯X5初始化,在onCreate()方法调用init方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
QbSdk.initX5Environment(this, new QbSdk.PreInitCallback() {
   @Override
   public void onCoreInitFinished() {
 
   }
 
   @Override
   public void onViewInitFinished(boolean b) {
    Log.e("xxx","hasLoad"+b);
   //此处将内核加载是否成功的状态保存到本地,SharePreference工具类可换为自己的
    SharedPreferenceUtils.saveBoolean(getApplicationContext(),"hasLoad",b);
   }
  });

4.应用内调用,无论是否加载内核,都是把在线的文档下载到本地然后打开,不同的是,未加载内核会借助QQ浏览器或其他App的文件浏览功能类似微信(这个调用,腾讯X5已自动处理,我们无需关心),而加载内核后,使用X5的TbsReaderView来打开文件,接下来就是具体代码。

a.bulid.gradle中集成Retrofit,RxJava和进度管理器ProgressManager

?
1
2
3
4
5
6
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'io.reactivex:rxjava:1.2.6'
implementation 'me.jessyan:progressmanager:1.5.0'

写网络下载工具

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface LoadFileApi {
 @GET
 Call<ResponseBody> loadPdfFile(@Url String fileUrl);
}
public class LoadFileModel {
 //使用该方法来下载文件
 public static void loadPdfFile(String url, Callback<ResponseBody> callback) {
  Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://www.baidu.com/")
    .client(ProgressManager.getInstance().with(new OkHttpClient.Builder())
      .build())
    .addConverterFactory(GsonConverterFactory.create())
    .build();
  LoadFileApi mLoadFileApi = retrofit.create(LoadFileApi.class);
  if (!TextUtils.isEmpty(url)) {
   Call<ResponseBody> call = mLoadFileApi.loadPdfFile(url);
   call.enqueue(callback);
  }
 }
}

b.具体调用

首先注册文件进度下载监听

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private ProgressDialog commonProgressDialog;//切换为自己的进度控件
 private ProgressInfo mLastDownloadingInfo;
 ProgressManager.getInstance().addResponseListener(url, new ProgressListener() {
            @Override
            public void onProgress(ProgressInfo progressInfo) {
             if (mLastDownloadingInfo == null) {
              mLastDownloadingInfo = progressInfo;
             }
             //因为是以请求开始时的时间作为 Id ,所以值越大,说明该请求越新
             if (progressInfo.getId() < mLastDownloadingInfo.getId()) {
              return;
             } else if (progressInfo.getId() > mLastDownloadingInfo.getId()) {
              mLastDownloadingInfo = progressInfo;
             }
             int progress = mLastDownloadingInfo.getPercent();
             commonProgressDialog.setProgress(progress);
             Log.d("xxx", "--Download-- " + progress + " % " + mLastDownloadingInfo.getSpeed() + " byte/s " + mLastDownloadingInfo.toString());
             if (mLastDownloadingInfo.isFinish()) {
              //说明已经下载完成
              commonProgressDialog.dismiss();
              Log.d("xxx", "--Download-- finish");
             }
            }
            @Override
            public void onError(long id, Exception e) {
             e.printStackTrace();
             new Handler().post(new Runnable() {
              @Override
              public void run() {
                commonProgressDialog.dismiss();
              }
             });
            }
           });
          }

然后打开文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download"; //文件下载的路径,可以自定义
//打开文件
 private void openFile(String filePath,String fileName) {
  boolean hasLoad = SharedPreferenceUtils.getBoolean(mContext, "hasLoad");//是否记载内核
  if (hasLoad){
  //展示文件的Activity
   Intent intentDoc = new Intent(this,FileDisplayActivity.class);
   intentDoc.putExtra("path",filePath);
   intentDoc.putExtra("fileName",fileName);
   startActivity(intentDoc);
  }else {
   if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
    Toast.makeText(this,"当前SD不可用",Toast.LENGTH_LONG).show();
    return;
   }
   try {
    File file = new File(DOWN_DIR, fileName);
    if (file.exists()){
     QbSdk.openFileReader(this, file.getAbsolutePath(), null, new ValueCallback<String>() {
      @Override
      public void onReceiveValue(String s) {
       Log.e("xxx",s);
      }
     });
    } else {
     downLoadFile(filePath,fileName);
    }
   } catch (Exception e) {
    e.printStackTrace();
    ToastUtils.showShortToast(mContext, "已下载过了");
   }
  }
 }
 private void downLoadFile(final String url, final String fileName) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
   @Override
   public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
     if (responseBody != null) {
      is = responseBody.byteStream();
      final File file = new File(DOWN_DIR, fileName);
      fos = new FileOutputStream(file);
      while ((len = is.read(buf)) != -1) {
       fos.write(buf, 0, len);
      }
      fos.flush();
      //未加载内核调用方法
      QbSdk.openFileReader(mContext, file.getAbsolutePath(), null, new ValueCallback<String>() {
       @Override
       public void onReceiveValue(String s) {
        Log.e("xxx",s);
       }
      });
      ToastUtils.showLongToast(MeetingDetailActivity.this, "下载成功,保存在Download文件夹下");
     }
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ProgressManager.getInstance().notifyOnErorr(url,e);
     ToastUtils.showLongToast(MeetingDetailActivity.this, "下载失败");
    } finally {
     try {
      if (is != null)
       is.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     try {
      if (fos != null)
       fos.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
   @Override
   public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(MeetingDetailActivity.this, "下载失败");
    commonProgressDialog.dismiss();
   }
  });
 }

FileDisplayActivity代码,对于一些包名可以切换为自己的包名,还有一些第三方库像进度展示,也可以切换为自己的进度控件

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.anshi.oatencentschool.R;
import com.anshi.oatencentschool.utils.DialogBuild;
import com.anshi.oatencentschool.utils.StatusBarUtils;
import com.anshi.oatencentschool.utils.ToastUtils;
import com.anshi.oatencentschool.utils.WeakHandler;
import com.anshi.oatencentschool.utils.filetool.LoadFileModel;
import com.anshi.oatencentschool.utils.filetool.SuperFileView2;
import com.kaopiz.kprogresshud.KProgressHUD;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import me.jessyan.progressmanager.ProgressListener;
import me.jessyan.progressmanager.ProgressManager;
import me.jessyan.progressmanager.body.ProgressInfo;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FileDisplayActivity extends AppCompatActivity {
 private String TAG = "FileDisplayActivity";
 //Tencent 提供的TBS阅读浏览功能,不借助第三方软件打开office和pdf文件
 private SuperFileView2 mSuperFileView;
 private String filePath;
 private TextView mTextView;
 private static final String DOWN_DIR = Environment.getExternalStorageDirectory()
   + File.separator+"Download";
 private String fileName;
 private KProgressHUD commonProgressDialog;
 private WeakHandler weakHandler = new WeakHandler(new Handler.Callback() {
  @Override
  public boolean handleMessage(Message msg) {
   int progress = msg.arg1;
   if (progress==100){
    commonProgressDialog.setProgress(progress);
    commonProgressDialog.dismiss();
   }else {
    commonProgressDialog.setProgress(progress);
   }
   return true;
  }
 });
 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_file_display);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_FULLSCREEN);
  commonProgressDialog = DialogBuild.getBuild().createCommonProgressDialog(this, "下载中");
  init();
 }
 /**
  * 初始化
  */
 public void init() {
  mTextView = (TextView) findViewById(R.id.file_album_name);
  fileName = getIntent().getStringExtra("fileName");
  int lastIndexOf = fileName.lastIndexOf(".");
  String substring = fileName.substring(0, lastIndexOf);
  mTextView.setText(substring);
  mSuperFileView = (SuperFileView2) findViewById(R.id.mSuperFileView);
  mSuperFileView.setOnGetFilePathListener(new SuperFileView2.OnGetFilePathListener() {
   @Override
   public void onGetFilePath(SuperFileView2 mSuperFileView2) {
    getFilePathAndShowFile(mSuperFileView);
   }
  });
  Intent intent = this.getIntent();
  String path = (String) intent.getSerializableExtra("path");
  if (!TextUtils.isEmpty(path)) {
   Log.d(TAG, "文件path:" + path);
   setFilePath(path);
  }
  mSuperFileView.show();
  ProgressManager.getInstance().addResponseListener(path, new ProgressListener() {
   @Override
   public void onProgress(ProgressInfo progressInfo) {
    int percent = progressInfo.getPercent();
    Message obtain = Message.obtain();
    obtain.arg1 = percent;
    weakHandler.sendMessage(obtain);
   }
   @Override
   public void onError(long id, Exception e) {
   }
  });
 }
 @Override
 protected void onResume() {
  super.onResume();
  StatusBarUtils.setWindowStatusBarColor(this,R.color.color_main);
 }
 /**
  * 显示文件
  * @param mSuperFileView2 控件
  */
 private void getFilePathAndShowFile(SuperFileView2 mSuperFileView2) {
  if (getFilePath().contains("http")&&!new File(DOWN_DIR, fileName).exists()) {//网络地址要先下载
   downLoadFile(getFilePath(),fileName,mSuperFileView2);
  } else {
   try {
    mSuperFileView2.displayFile(new File(DOWN_DIR, fileName));
   }catch (Exception e){
    e.printStackTrace();
   }
  }
 }
 public void setFilePath(String fileUrl) {
  this.filePath = fileUrl;
 }
 private String getFilePath() {
  return filePath;
 }
 /**
  * 回退上一级菜单
  * @param view 控件
  */
 public void onClick(View view) {
  finish();
 }
 private void downLoadFile(final String url, final String fileName,final SuperFileView2 mSuperFileView2) {
  commonProgressDialog.show();
  LoadFileModel.loadPdfFile(url, new Callback<ResponseBody>() {
   @Override
   public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len;
    FileOutputStream fos = null;
    try {
     ResponseBody responseBody = response.body();
      is = responseBody.byteStream();
     final File file = new File(DOWN_DIR, fileName);
     fos = new FileOutputStream(file);
     while ((len = is.read(buf)) != -1) {
      fos.write(buf, 0, len);
     }
     fos.flush();
     mSuperFileView2.displayFile(file);
     ToastUtils.showLongToast(FileDisplayActivity.this, "下载成功,保存在Download文件夹下");
    } catch (Exception e) {
     commonProgressDialog.dismiss();
     ToastUtils.showLongToast(FileDisplayActivity.this, "下载失败");
    } finally {
     try {
      if (is != null)
       is.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     try {
      if (fos != null)
       fos.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }
   @Override
   public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
    t.printStackTrace();
    ToastUtils.showShortToast(FileDisplayActivity.this, "下载失败");
    commonProgressDialog.dismiss();
   }
  });
  }
}

布局Layout:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_file_display"
 android:layout_width="match_parent"
 android:fitsSystemWindows="true"
 android:layout_height="match_parent">
 <android.support.v7.widget.Toolbar
  android:layout_width="match_parent"
  android:layout_height="46dp"
  android:background="@color/color_main"
  android:id="@+id/file_toolbar"
  >
  <TextView
   android:layout_width="wrap_content"
   android:layout_height="match_parent"
   android:id="@+id/file_album_name"
   android:layout_gravity="center"
   android:gravity="center"
   android:maxLines="2"
   android:ellipsize="end"
   android:textSize="14sp"
   android:textColor="#FFF"
   />
 </android.support.v7.widget.Toolbar>
 <FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_below="@id/file_toolbar"
  >
  <com.anshi.oatencentschool.utils.filetool.SuperFileView2
   android:id="@+id/mSuperFileView"
   android:layout_width="match_parent"
   android:layout_height="match_parent"/>
  <RelativeLayout
   android:layout_width="wrap_content"
   android:layout_gravity="center|start"
   android:layout_height="wrap_content">
   <RadioButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:button="@null"
    android:onClick="onClick"
    android:id="@+id/back_icon"
    android:drawableStart="@drawable/svg_left_back_blur"
    android:layout_marginStart="10dp"
    />
  </RelativeLayout>
  <!--<RadioButton-->
   <!--android:layout_width="wrap_content"-->
   <!--android:layout_height="wrap_content"-->
   <!--android:button="@null"-->
   <!--android:visibility="gone"-->
   <!--android:layout_gravity="end|bottom"-->
   <!--android:onClick="saveLocal"-->
   <!--android:layout_marginBottom="10dp"-->
   <!--android:layout_marginEnd="10dp"-->
   <!--android:drawableStart="@drawable/vector_drawable_down_load"-->
   <!--android:layout_marginStart="10dp"-->
   <!--/>-->
 </FrameLayout>
</RelativeLayout>

SuperFileView2代码,这个自定义的类是从https://github.com/ZhongXiaoHong/superFileView导入

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.tencent.smtt.sdk.TbsReaderView;
import java.io.File;
/**
 *
 * Created by 12457 on 2017/8/29.
 */
public class SuperFileView2 extends FrameLayout {
 private static String TAG = "SuperFileView";
 private TbsReaderView mTbsReaderView;
 private Context context;
 public SuperFileView2(Context context) {
  this(context, null, 0);
 }
 public SuperFileView2(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 public SuperFileView2(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  mTbsReaderView = new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
   @Override
   public void onCallBackAction(Integer integer, Object o, Object o1) {
   }
  });
  this.addView(mTbsReaderView, new LinearLayout.LayoutParams(-1, -1));
  this.context = context;
 }
 private OnGetFilePathListener mOnGetFilePathListener;
 public void setOnGetFilePathListener(OnGetFilePathListener mOnGetFilePathListener) {
  this.mOnGetFilePathListener = mOnGetFilePathListener;
 }
 private TbsReaderView getTbsReaderView(Context context) {
  return new TbsReaderView(context, new TbsReaderView.ReaderCallback() {
   @Override
   public void onCallBackAction(Integer integer, Object o, Object o1) {
   }
  });
 }
 public void displayFile(File mFile) {
  if (mFile != null && !TextUtils.isEmpty(mFile.toString())) {
   //增加下面一句解决没有TbsReaderTemp文件夹存在导致加载文件失败
   String bsReaderTemp = Environment.getExternalStorageDirectory()+ File.separator+"TbsReaderTemp";
   File bsReaderTempFile =new File(bsReaderTemp);
   if (!bsReaderTempFile.exists()) {
    Log.d("xxx","准备创建/storage/emulated/0/TbsReaderTemp!!");
    boolean mkdir = bsReaderTempFile.mkdir();
    if(!mkdir){
     Log.d("xxx","创建/storage/emulated/0/TbsReaderTemp失败!!!!!");
    }
   }
   //加载文件
   Bundle localBundle = new Bundle();
   Log.d("xxx",mFile.toString());
   localBundle.putString("filePath", mFile.toString());
   localBundle.putString("tempPath", bsReaderTemp);
   if (mTbsReaderView == null){
    mTbsReaderView = getTbsReaderView(context.getApplicationContext());
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }else {
    String fileType = getFileType(mFile.toString());
    boolean bool = mTbsReaderView.preOpen(fileType,false);
    if (bool) {
     try {
      mTbsReaderView.openFile(localBundle);
     }catch (Exception e){
      e.printStackTrace();
     }
    }
   }
  } else {
   Log.d("xxx","文件路径无效!");
  }
 }
 /***
  * 获取文件类型
  *
  * @param paramString
  * @return
  */
 private String getFileType(String paramString) {
  String str = "";
  if (TextUtils.isEmpty(paramString)) {
   Log.d(TAG, "paramString---->null");
   return str;
  }
  Log.d(TAG, "paramString:" + paramString);
  int i = paramString.lastIndexOf('.');
  if (i <= -1) {
   Log.d(TAG, "i <= -1");
   return str;
  }
  str = paramString.substring(i + 1);
  Log.d(TAG, "paramString.substring(i + 1)------>" + str);
  return str;
 }
 public void show() {
  if(mOnGetFilePathListener!=null){
   mOnGetFilePathListener.onGetFilePath(this);
  }
 }
 /***
  * 将获取File路径的工作,“外包”出去
  */
 public interface OnGetFilePathListener {
  void onGetFilePath(SuperFileView2 mSuperFileView2);
 }
 public void onStopDisplay() {
  if (mTbsReaderView != null) {
   mTbsReaderView.onStop();
  }
 }
}

加载内核后打开文件

Android集成腾讯X5实现文档浏览功能

未加载内核打开文件

Android集成腾讯X5实现文档浏览功能

总结

以上所述是小编给大家介绍的Android集成腾讯X5实现文档浏览功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

原文链接:https://blog.csdn.net/hardWork_yulu/article/details/102636818

延伸 · 阅读

精彩推荐
  • AndroidAndroid中的JNI数组操作教程

    Android中的JNI数组操作教程

    这篇文章主要给大家介绍了关于Android中JNI数组操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    纸上浅谈3762022-03-10
  • AndroidAndroid简单实现画图功能

    Android简单实现画图功能

    这篇文章主要为大家详细介绍了Android简单实现画图功能的方法,以及实现过程中遇到的问题,感兴趣的小伙伴们可以参考一下...

    Android开发网11272021-06-22
  • AndroidAndroid中GridView插件的使用方法

    Android中GridView插件的使用方法

    今天小编就为大家分享一篇关于Android中GridView插件的使用方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编...

    徐刘根5152022-10-10
  • AndroidAndroid中使用Post请求的方法

    Android中使用Post请求的方法

    这篇文章主要介绍了Android中使用Post请求的方法,实例分析了Android中使用post请求的原理与具体实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    akwolf8422021-03-29
  • AndroidAndroid实现水波纹特效

    Android实现水波纹特效

    这篇文章主要为大家详细介绍了Android实现水波纹特效,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    lou_liang11232022-09-22
  • Androidandroid设置adb自带screenrecord录屏命令

    android设置adb自带screenrecord录屏命令

    这篇文章主要介绍了android设置adb自带screenrecord录屏命令,需要的朋友可以参考下...

    lidx071410792022-08-29
  • AndroidAndroid ExpandableListView单选以及多选实现代码

    Android ExpandableListView单选以及多选实现代码

    这篇文章主要为大家详细介绍了Android ExpandableListView单选以及多选的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    不年少还青春11712022-03-03
  • Android如何使用Flutter实现58同城中的加载动画详解

    如何使用Flutter实现58同城中的加载动画详解

    这篇文章主要给大家介绍了关于如何使用Flutter实现58同城中加载动画详的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Flutter具有一定...

    吴振7212022-11-02