Commit a64a3da5 by zhengnw@sobot.com

widget 1.2.6

parent b943125c
......@@ -35,13 +35,12 @@ dependencies {
implementation 'com.google.android.material:material:1.4.+'
implementation project(':sobot_common')
implementation project(':sobot_widget')
implementation project(':sobot_album')
// implementation project(':sobot_album')
// implementation 'com.sobot.library:widget:0.3'
// api 'com.sobot.library:sobotcommon:1.0'
// api 'com.sobot.library:sobotcommon_x:1.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.sobot.chat:sobotsupport-glidev4:2.3'
// implementation 'com.facebook.fresco:fresco:1.13.0'
//android x 可以用这个 ,普通版不能用这个
// implementation 'com.facebook.fresco:fresco:2.6.0'
......
......@@ -20,6 +20,7 @@
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/sobot_activity_def_theme"
android:configChanges="orientation|keyboardHidden|screenSize|touchscreen|navigation|locale|fontScale|uiMode|screenLayout|smallestScreenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
......@@ -9,14 +9,6 @@ import android.net.Uri;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.sobot.album.Action;
import com.sobot.album.AlbumConfig;
import com.sobot.album.AlbumFile;
import com.sobot.album.SobotAlbum;
import com.sobot.album.SobotMediaLoader;
import com.sobot.album.api.widget.Widget;
import com.sobot.common.login.SobotLoginTools;
import com.sobot.common.login.callback.SobotResultBlock;
import com.sobot.common.login.callback.SobotResultCode;
......@@ -32,14 +24,11 @@ import com.sobot.widget.refresh.layout.footer.ClassicsFooter;
import com.sobot.widget.refresh.layout.header.ClassicsHeader;
import com.sobot.widget.ui.SobotMarkConfig;
import com.sobot.widget.ui.base.SobotBaseActivity;
import com.sobot.widget.ui.permission.SobotPermissionListenerImpl;
import com.sobot.widget.ui.rich.HtmlToolUtils;
import com.sobot.widget.ui.toast.SobotToastUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class MainActivity extends SobotBaseActivity {
......@@ -285,42 +274,43 @@ public class MainActivity extends SobotBaseActivity {
// }
// openAlbum();
// selectPicFromLocal();
}
private void openAlbum() {
SobotAlbum.album(MainActivity.this)
.multipleChoice()
.columnCount(4)
.selectCount(4)
.camera(false)
.cameraVideoQuality(1)
.cameraVideoLimitDuration(Integer.MAX_VALUE)
.cameraVideoLimitBytes(Integer.MAX_VALUE)
.checkedList(mAlbumFiles)
.widget(
Widget.newDarkBuilder(MainActivity.this)
.title("")
.build()
)
.onResult(new Action<ArrayList<AlbumFile>>() {
@Override
public void onAction(@NonNull ArrayList<AlbumFile> result) {
if (result.size() > 0) {
}
}
})
.onCancel(new Action<String>() {
@Override
public void onAction(@NonNull String result) {
//取消选择
}
})
.start();
}
private ArrayList<AlbumFile> mAlbumFiles = new ArrayList<>();//编辑的图片地址
// private void openAlbum() {
// SobotAlbum.album(MainActivity.this)
// .multipleChoice()
// .columnCount(4)
// .selectCount(4)
// .camera(false)
// .cameraVideoQuality(1)
// .cameraVideoLimitDuration(Integer.MAX_VALUE)
// .cameraVideoLimitBytes(Integer.MAX_VALUE)
// .checkedList(mAlbumFiles)
// .widget(
// Widget.newDarkBuilder(MainActivity.this)
// .title("")
// .build()
// )
// .onResult(new Action<ArrayList<AlbumFile>>() {
// @Override
// public void onAction(@NonNull ArrayList<AlbumFile> result) {
// if (result.size() > 0) {
//
//
// }
// }
// })
// .onCancel(new Action<String>() {
// @Override
// public void onAction(@NonNull String result) {
// //取消选择
// }
// })
// .start();
// }
//
// private ArrayList<AlbumFile> mAlbumFiles = new ArrayList<>();//编辑的图片地址
@Override
protected void initData() {
......
......@@ -23,6 +23,7 @@ public class MyApp extends MultiDexApplication {
SobotCommonApi.setShowLogDebug(true);
SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.LANDSCAPE_SCREEN, false);
SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.DISPLAY_INNOTCH, false);
SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.SHOW_PERMISSION_TIPS_POP, false);
}
}
\ No newline at end of file
......@@ -22,7 +22,8 @@ dependencies {
compileOnly 'com.google.android.material:material:1.4.+'
compileOnly 'androidx.appcompat:appcompat:1.0.0'
compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
api 'com.sobot.library:widget_x:1.2.3'
api 'com.sobot.library:widget_x:1.2.6'
// implementation project(':sobot_widget')
api 'com.sobot.library:picture_x:1.2.0'
}
......
......@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) {
ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'album' //项目名
PUBLISH_VERSION = '1.0.3' //版本号
PUBLISH_VERSION = '1.0.4' //版本号
}
......
......@@ -60,7 +60,7 @@ public class SobotAlbumActivity extends SobotBaseActivity {
}
@Override
protected void initView() throws InterruptedException {
protected void initView() {
mTvMessage = findViewById(R.id.tv_message);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
......
package com.sobot.album.app.album;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.widget.CompoundButton;
......@@ -14,7 +11,6 @@ import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.content.ContextCompat;
import com.sobot.album.Action;
import com.sobot.album.AlbumFile;
......@@ -100,7 +96,7 @@ public class AlbumActivity extends SobotBaseActivity implements
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
setTitle(R.string.sobot_album_select_images);
getLeftMenu().setOnClickListener(new View.OnClickListener() {
@Override
......
......@@ -62,7 +62,7 @@ public class GalleryActivity extends SobotBaseActivity implements Contract.Galle
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(),this);
Bundle argument = getIntent().getExtras();
assert argument != null;
......
......@@ -35,7 +35,7 @@ public class NullActivity extends SobotAlbumBaseActivity implements Contract.Nul
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
mView = new NullView(this, this);
Bundle argument = getIntent().getExtras();
......
......@@ -104,7 +104,7 @@ public class CameraActivity extends SobotAlbumBaseActivity {
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
}
......
......@@ -38,7 +38,7 @@ public class GalleryActivity extends SobotAlbumBaseActivity implements Contract.
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(), this);
Bundle argument = getIntent().getExtras();
......
......@@ -51,7 +51,7 @@ public class GalleryAlbumActivity extends SobotAlbumBaseActivity implements Cont
}
@Override
protected void initView() throws InterruptedException {
protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(), this);
Bundle argument = getIntent().getExtras();
......
......@@ -25,9 +25,10 @@ android {
dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
compileOnly 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.appcompat:appcompat:1.0.0'
compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
api 'com.sobot.library:utils:1.1.3'
api 'com.sobot.library:picture_x:1.2.0'
}
......
......@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) {
ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'widget_x' //项目名
PUBLISH_VERSION = '1.2.4' //版本号
PUBLISH_VERSION = '1.2.6' //版本号
}
......
......@@ -32,5 +32,10 @@
android:screenOrientation="behind"
android:theme="@style/sobot_activity_def_theme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".ui.base.picandroidvideo.SobotSelectPicAndVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize|touchscreen|navigation|locale|fontScale|uiMode|screenLayout|smallestScreenSize"
android:launchMode="singleTask"
android:theme="@style/sobot_activity_def_theme" />
</application>
</manifest>
\ No newline at end of file
package com.sobot.widget.refresh.layout.callback;
import android.view.View;
/**
* 回调处理
*/
public interface SobotRecyclerCallBack {
/**
* 点击事件
*
* @param view 点击的view
* @param position view的位置
*/
void onItemClickListener(View view, int position);
/**
* 长按事件
*
* @param view 长按的view
* @param position view的位置
*/
void onItemLongClickListener(View view, int position);
}
......@@ -2,6 +2,7 @@ package com.sobot.widget.ui.base;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
......@@ -12,12 +13,6 @@ import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.View;
......@@ -28,13 +23,20 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.sobot.utils.SobotLogUtils;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.sobot.utils.SobotSharedPreferencesUtil;
import com.sobot.utils.SobotSystemUtils;
import com.sobot.widget.R;
import com.sobot.widget.SobotWidgetApi;
import com.sobot.widget.ui.SobotBaseConstant;
import com.sobot.widget.ui.SobotMarkConfig;
import com.sobot.widget.ui.base.picandroidvideo.SobotSelectPicAndVideoActivity;
import com.sobot.widget.ui.image.SobotRCImageView;
import com.sobot.widget.ui.notchlib.SobotINotchScreen;
import com.sobot.widget.ui.notchlib.SobotNotchScreenManager;
......@@ -47,6 +49,7 @@ import com.sobot.widget.ui.utils.SobotResourceUtils;
import com.sobot.widget.ui.utils.SobotWidgetUtils;
import java.io.File;
import java.util.Arrays;
import java.util.Locale;
/**
......@@ -93,7 +96,7 @@ public abstract class SobotBaseActivity extends FragmentActivity {
}
setUpToolBar();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
View toolBar = findViewById(getResId("sobot_layout_titlebar"));
View toolBar = findViewById(R.id.sobot_layout_titlebar);
if (toolBar != null) {
setUpToolBarLeftMenu();
......@@ -516,16 +519,29 @@ public abstract class SobotBaseActivity extends FragmentActivity {
switch (requestCode) {
case SobotBaseConstant.REQUEST_CODE_PICTURE:
try {
//判断是否选择部分的权限
// SobotLogUtils.d("=====判断是否选择部分的权限=======");
for (int i = 0; i < grantResults.length; i++) {
if (permissions[i] != null && permissions[i].equals(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)) {
// SobotLogUtils.d("=====android 14权限===="+permissions[i].equals(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)+"====="+grantResults[i]);
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
if (permissionListener != null) {
permissionListener.onPermissionSuccessListener();
//单独处理android 14 部分权限,如果允许是部分权限,跳转到回显界面
if (grantResults.length > 1 && permissions.length > 0) {
//是否有全部权限
boolean isAllGranted = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
isAllGranted = false;
}
}
if (!isAllGranted) {
for (int i = 0; i < grantResults.length; i++) {
if (permissions[i] != null && permissions[i].equals(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
int selectType;
if (Arrays.asList(permissions).contains(Manifest.permission.READ_MEDIA_IMAGES) && Arrays.asList(permissions).contains(Manifest.permission.READ_MEDIA_VIDEO)) {
selectType = 3;//部分视频和图片
} else if (Arrays.asList(permissions).contains(Manifest.permission.READ_MEDIA_VIDEO)) {
selectType = 2;//部分视频
} else {
selectType = 1;//部分图片
}
openSelectPic(selectType);
return;
}
return;
}
}
}
......@@ -608,51 +624,97 @@ public abstract class SobotBaseActivity extends FragmentActivity {
}
/**
* android 14 部分权限情况下,回显照片或者视频
*
* @param selectType 1:部分图片 2:部分视频 3:部分视频和图片
*/
private void openSelectPic(int selectType) {
Intent intent = new Intent(getSobotBaseActivity(), SobotSelectPicAndVideoActivity.class);
intent.putExtra("selectType", selectType);
startActivityForResult(intent, SobotBaseConstant.REQUEST_CODE_PICTURE);
}
/**
* 检查存储权限
*
* @param checkType 0:图片权限 1:视频权限,2:音频权限,3:选文件,图片、视频、录音所有细分的权限 4:图片和视频权限,读取相册图片和视频
* @param checkType 0:图片权限 1:视频权限,3,所有细分的权限, android 13 使用
* @return true, 已经获取权限;false,没有权限,尝试获取
*/
protected boolean checkStoragePermission(int checkType) {
//如果是升级Android13之前就已经具有读写SDK的权限,那么升级到13之后,自己具有上述三个权限。
//如果是升级Android13之后新装的应用,并且targetSDK小于33,则申请READ_EXTERNAL_STORAGE权限时,会自动转化为对上述三个权限的申请,权限申请框只一个
//如果是升级Android13之后新装的应用,并且targetSDK大于等于33,则申请READ_EXTERNAL_STORAGE权限时会自动拒绝。
//如果是升级Android13之后新装的应用,并且targetSDK大于等于33,则申请READ_EXTERNAL_STORAGE权限时会自动拒绝(同理WRITE_EXTERNAL_STORAGE也是一样)。
//如果是android14 没有图片或者视频权限,还需要判断是否有部分权限,如果有部分权限,跳转允许图片视频界面,选择可以访问的上传,或者打开设置申请永久权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (checkType == 0) {
return true;
} else if (checkType == 1) {
return true;
} else if (checkType == 2) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO)
//检测是否有图片权限
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED) {
//申请音频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_AUDIO}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
!= PackageManager.PERMISSION_GRANTED) {
//有部分图片权限,直接打开允许访问图片视频列表界面
openSelectPic(1);//照片
return false;
} else {
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
} else {
//申请图片权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
}
} else if (checkType == 3) {
//为适配Android 14
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
//申请:图片权限 视频权限 音频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
} else if (checkType == 1) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED) {
//有部分视频权限,直接打开允许访问图片视频列表界面
openSelectPic(2);//视频
return false;
} else {
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
} else {
//申请视频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_VIDEO}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
}
return true;
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//申请:图片权限 视频权限 音频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
//有图片和视频但是 没有音频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_AUDIO}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED) {
//有部分视频权限,直接打开允许访问图片视频列表界面
openSelectPic(3);//视频
return false;
} else {
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
} else {
//申请:图片权限 视频权限 音频权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO}, SobotBaseConstant.REQUEST_CODE_PICTURE);
//申请图片、视频、语音三个权限
this.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_AUDIO,}, SobotBaseConstant.REQUEST_CODE_PICTURE);
return false;
}
return false;
}
}
} else if (Build.VERSION.SDK_INT >= 23 && SobotSystemUtils.getTargetSdkVersion(getSobotBaseActivity().getApplicationContext()) >= 23) {
......@@ -667,39 +729,49 @@ public abstract class SobotBaseActivity extends FragmentActivity {
}
/**
* 判断是否有存储卡权限
* 判断是否有存储卡权限,android 14 部分权限有的话也返回true
*
* @param checkPermissionType 0:图片权限 1:视频权限,2:音频权限,3:选文件,图片、视频、录音所有细分的权限 4:图片和视频权限,读取相册图片和视频
* @param checkPermissionType 0:图片权限 1:视频权限,2:音频权限,3,所有细分的权限, android 13 使用
* @return true, 已经获取权限;false,没有权限
*/
protected boolean isHasStoragePermission(int checkPermissionType) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (checkPermissionType == 0) {
return true;
} else if (checkPermissionType == 1) {
return true;
} else if (checkPermissionType == 2) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO)
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14 有部分权限就不弹权限提示框了
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
} else if (checkPermissionType == 3) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
} else if (checkPermissionType == 1) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14 有部分权限就不弹权限提示框了
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
//android 14 有部分权限就不弹权限提示框了
if (ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
}
return false;
}
}
......
/*
* Copyright 2017 Yan Zhenjie.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sobot.widget.ui.base.picandroidvideo;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class SobotAlbumFile implements Parcelable, Comparable<SobotAlbumFile> {
public static final int TYPE_IMAGE = 1;
public static final int TYPE_VIDEO = 2;
public static final int TYPE_ADD = 3;
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_IMAGE, TYPE_VIDEO,TYPE_ADD})
public @interface MediaType {
}
/**
* 本地文件路径.
*/
private String mPath;
/**
* 本地的uri
*/
private Uri uri;
private String fileNumKey;
/**
* 远程的地址
*/
private String fileUrl;
/**
* 文件名字.
*/
private String fileName;
/**
* 文件夹名字.
*/
private String mBucketName;
/**
* 文件扩展类型.
*/
private String mMimeType;
/**
* 添加日期.
*/
private long mAddDate;
/**
* Latitude
*/
private float mLatitude;
/**
* Longitude.
*/
private float mLongitude;
/**
* 大小.
*/
private long mSize;
/**
* Duration.
*/
private long mDuration;
/**
* Thumb path.
*/
private String mThumbPath;
/**
* MediaType.
*/
private int mMediaType;
/**
* Checked.
*/
private boolean isChecked;
/**
* Enabled.
*/
private boolean isDisable;
public SobotAlbumFile() {
}
public Uri getUri() {
return uri;
}
public void setUri(Uri uri) {
this.uri = uri;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
@Override
public int compareTo(SobotAlbumFile o) {
long time = o.getAddDate() - getAddDate();
if (time > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
else if (time < -Integer.MAX_VALUE)
return -Integer.MAX_VALUE;
return (int) time;
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof SobotAlbumFile) {
SobotAlbumFile o = (SobotAlbumFile) obj;
String inPath = o.getPath();
if (mPath != null && inPath != null) {
return mPath.equals(inPath);
}
}
return super.equals(obj);
}
@Override
public int hashCode() {
return mPath != null ? mPath.hashCode() : super.hashCode();
}
public String getPath() {
return mPath;
}
public void setPath(String path) {
mPath = path;
}
public String getBucketName() {
return mBucketName;
}
public void setBucketName(String bucketName) {
mBucketName = bucketName;
}
public String getMimeType() {
return mMimeType;
}
public void setMimeType(String mimeType) {
mMimeType = mimeType;
}
public long getAddDate() {
return mAddDate;
}
public void setAddDate(long addDate) {
mAddDate = addDate;
}
public float getLatitude() {
return mLatitude;
}
public void setLatitude(float latitude) {
mLatitude = latitude;
}
public float getLongitude() {
return mLongitude;
}
public void setLongitude(float longitude) {
mLongitude = longitude;
}
public long getSize() {
return mSize;
}
public void setSize(long size) {
mSize = size;
}
public long getDuration() {
return mDuration;
}
public void setDuration(long duration) {
mDuration = duration;
}
public String getThumbPath() {
return mThumbPath;
}
public void setThumbPath(String thumbPath) {
mThumbPath = thumbPath;
}
@MediaType
public int getMediaType() {
return mMediaType;
}
public void setMediaType(@MediaType int mediaType) {
mMediaType = mediaType;
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
public boolean isDisable() {
return isDisable;
}
public void setDisable(boolean disable) {
this.isDisable = disable;
}
public String getFileNumKey() {
return fileNumKey;
}
public void setFileNumKey(String fileNumKey) {
this.fileNumKey = fileNumKey;
}
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
protected SobotAlbumFile(Parcel in) {
mPath = in.readString();
mBucketName = in.readString();
mMimeType = in.readString();
mAddDate = in.readLong();
mLatitude = in.readFloat();
mLongitude = in.readFloat();
mSize = in.readLong();
mDuration = in.readLong();
mThumbPath = in.readString();
mMediaType = in.readInt();
isChecked = in.readByte() != 0;
isDisable = in.readByte() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mPath);
dest.writeString(mBucketName);
dest.writeString(mMimeType);
dest.writeLong(mAddDate);
dest.writeFloat(mLatitude);
dest.writeFloat(mLongitude);
dest.writeLong(mSize);
dest.writeLong(mDuration);
dest.writeString(mThumbPath);
dest.writeInt(mMediaType);
dest.writeByte((byte) (isChecked ? 1 : 0));
dest.writeByte((byte) (isDisable ? 1 : 0));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<SobotAlbumFile> CREATOR = new Creator<SobotAlbumFile>() {
@Override
public SobotAlbumFile createFromParcel(Parcel in) {
return new SobotAlbumFile(in);
}
@Override
public SobotAlbumFile[] newArray(int size) {
return new SobotAlbumFile[size];
}
};
}
\ No newline at end of file
package com.sobot.widget.ui.base.picandroidvideo;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import androidx.annotation.WorkerThread;
import com.sobot.utils.SobotLogUtils;
import java.util.ArrayList;
import java.util.List;
//android 14 用于部分权限的 图片、视频扫描
public class SobotMediaReaderScanUtils {
/**
* Image attribute.
*/
private static final String[] IMAGES = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.LATITUDE,
MediaStore.Images.Media.LONGITUDE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media._ID
};
/**
* Scan for image files.
*/
@WorkerThread
public static List<SobotAlbumFile> scanImageFile(Context mContext) {
List<SobotAlbumFile> albumFileList = new ArrayList<>();
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(collection,
IMAGES,
null,
null,
null);
if (cursor != null) {
SobotLogUtils.d("======图片总数=======" + cursor.getCount());
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String bucketName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
long id = cursor.getLong(7);
SobotAlbumFile imageFile = new SobotAlbumFile();
imageFile.setMediaType(SobotAlbumFile.TYPE_IMAGE);
imageFile.setPath(path);
imageFile.setBucketName(bucketName);
imageFile.setMimeType(mimeType);
imageFile.setAddDate(addDate);
imageFile.setLatitude(latitude);
imageFile.setLongitude(longitude);
imageFile.setSize(size);
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
imageFile.setUri(contentUri);
albumFileList.add(imageFile);
}
cursor.close();
}
return albumFileList;
}
/**
* Video attribute.
*/
private static final String[] VIDEOS = {
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.MIME_TYPE,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.LATITUDE,
MediaStore.Video.Media.LONGITUDE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media._ID
};
/**
* Scan for image files.
*/
@WorkerThread
public static List<SobotAlbumFile> scanVideoFile(Context mContext) {
List<SobotAlbumFile> albumFileList = new ArrayList<>();
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
collection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(collection,
VIDEOS,
null,
null,
null);
SobotLogUtils.d("======scanVideoFile=======" + (cursor == null));
if (cursor != null) {
SobotLogUtils.d("======视频总数=======" + cursor.getCount());
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String bucketName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
long duration = cursor.getLong(7);
long id = cursor.getLong(8);
SobotAlbumFile videoFile = new SobotAlbumFile();
videoFile.setMediaType(SobotAlbumFile.TYPE_VIDEO);
videoFile.setPath(path);
videoFile.setBucketName(bucketName);
videoFile.setMimeType(mimeType);
videoFile.setAddDate(addDate);
videoFile.setLatitude(latitude);
videoFile.setLongitude(longitude);
videoFile.setSize(size);
videoFile.setDuration(duration);
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
videoFile.setUri(contentUri);
albumFileList.add(videoFile);
}
cursor.close();
}
return albumFileList;
}
@WorkerThread
public static List<SobotAlbumFile> getAllMedia(Context mContext, int type) {
List<SobotAlbumFile> list = new ArrayList<>();
if (type == 3) {
//图片和视频
List<SobotAlbumFile> scannedImageFileList = scanImageFile(mContext);
if (scannedImageFileList != null) {
list.addAll(scannedImageFileList);
}
List<SobotAlbumFile> scannedVideoFileList = scanVideoFile(mContext);
if (scannedVideoFileList != null) {
list.addAll(scannedVideoFileList);
}
} else if (type == 2) {
//视频
List<SobotAlbumFile> scannedVideoFileList = scanVideoFile(mContext);
if (scannedVideoFileList != null) {
list.addAll(scannedVideoFileList);
}
} else {
//图片
List<SobotAlbumFile> scannedImageFileList = scanImageFile(mContext);
if (scannedImageFileList != null) {
list.addAll(scannedImageFileList);
}
}
return list;
}
}
\ No newline at end of file
package com.sobot.widget.ui.base.picandroidvideo;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.sobot.utils.SobotDensityUtil;
import com.sobot.widget.R;
import com.sobot.widget.refresh.layout.callback.SobotRecyclerCallBack;
import com.sobot.widget.ui.SobotBaseConstant;
import com.sobot.widget.ui.base.SobotBaseActivity;
import java.util.ArrayList;
import java.util.List;
/**
* android 14 部分权限 允许后的回显界面
*/
public class SobotSelectPicAndVideoActivity extends SobotBaseActivity {
private TextView tv_go_to_settring;
private RecyclerView sobot_rcy;
private Button sobot_btn_submit;
private SobotSelectPicAndVideoAdapter picAdapter;
private List<SobotAlbumFile> albumFileList;
private int selectType = 1;
@Override
protected int getContentViewResId() {
return R.layout.sobot_activity_select_pic_and_video;
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (albumFileList == null) {
albumFileList = new ArrayList<>();
}
albumFileList.clear();
albumFileList = SobotMediaReaderScanUtils.getAllMedia(getSobotBaseActivity(), selectType);
if (albumFileList == null) {
albumFileList = new ArrayList<>();
}
albumFileList.add(new SobotAlbumFile());
if (picAdapter != null) {
picAdapter.setmSelectedPos(-1);
picAdapter.updateList(albumFileList);
} else {
finish();
}
}
@Override
protected void onResume() {
super.onResume();
if(selectType == 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_IMAGES)
== PackageManager.PERMISSION_GRANTED) {
//如果android 14 手机有永久权限 直接关闭当前界面
finish();
}
}else if(selectType == 2){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && ContextCompat.checkSelfPermission(getSobotBaseActivity(), Manifest.permission.READ_MEDIA_VIDEO)
== PackageManager.PERMISSION_GRANTED) {
//如果android 14 手机有永久权限 直接关闭当前界面
finish();
}
}
}
@Override
protected void initView() {
tv_go_to_settring = findViewById(R.id.tv_go_to_settring);
sobot_rcy = findViewById(R.id.sobot_rcy);
sobot_btn_submit = findViewById(R.id.sobot_btn_submit);
sobot_btn_submit.setAlpha(0.5f);
sobot_btn_submit.setClickable(false);
setTitle(getString(R.string.sobot_str_select_pic_video));
displayInNotch(sobot_rcy);
tv_go_to_settring.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//去设置打开权限
Uri packageURI = Uri.parse("package:" + getPackageName());
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
startActivity(intent);
}
});
}
protected void initData() {
selectType = getIntent().getIntExtra("selectType", 1);
albumFileList = SobotMediaReaderScanUtils.getAllMedia(getSobotBaseActivity(), selectType);
if (albumFileList == null) {
albumFileList = new ArrayList<>();
}
albumFileList.add(new SobotAlbumFile());
picAdapter = new SobotSelectPicAndVideoAdapter(this, albumFileList, new SobotRecyclerCallBack() {
@Override
public void onItemClickListener(View view, int position) {
}
@Override
public void onItemLongClickListener(View view, int position) {
}
});
picAdapter.setClickListener(new SobotSelectPicAndVideoAdapter.myClickListener() {
@Override
public void onClickOtherListener() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (selectType == 3) {
requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
} else if (selectType == 2) {
requestPermissions(new String[]{Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
} else {
requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}, SobotBaseConstant.REQUEST_CODE_PICTURE);
}
}
}
@Override
public void onCheckListener() {
if (picAdapter.getmSelectedPos() > -1) {
sobot_btn_submit.setAlpha(1f);
sobot_btn_submit.setClickable(true);
} else {
sobot_btn_submit.setAlpha(0.5f);
sobot_btn_submit.setClickable(false);
}
}
});
sobot_rcy.setAdapter(picAdapter);
GridLayoutManager gridlayoutmanager = new GridLayoutManager(SobotSelectPicAndVideoActivity.this, 4);
sobot_rcy.addItemDecoration(new SpaceItemDecoration(SobotDensityUtil.dp2px(SobotSelectPicAndVideoActivity.this, 3), SobotDensityUtil.dp2px(SobotSelectPicAndVideoActivity.this, 1.5f), 0, SpaceItemDecoration.GRIDLAYOUT));
sobot_rcy.setLayoutManager(gridlayoutmanager);
sobot_btn_submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (albumFileList != null && albumFileList.size() > 0 && picAdapter != null && picAdapter.getmSelectedPos() > -1) {
SobotAlbumFile albumFile = albumFileList.get(picAdapter.getmSelectedPos());
Intent intent = new Intent();
intent.setData(albumFile.getUri());
setResult(RESULT_OK, intent);
finish();
}
}
});
}
}
\ No newline at end of file
package com.sobot.widget.ui.base.picandroidvideo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.sobot.pictureframe.SobotBitmapUtil;
import com.sobot.widget.R;
import com.sobot.widget.refresh.layout.callback.SobotRecyclerCallBack;
import java.util.List;
/**
* android 14 部分权限 允许后的回显界面
*/
public class SobotSelectPicAndVideoAdapter extends RecyclerView.Adapter<SobotSelectPicAndVideoAdapter.ViewHolder> {
private Context mContext;
private List<SobotAlbumFile> list;
private SobotRecyclerCallBack callBack;
private int mSelectedPos = -1;//保存当前选中的position 重点!
private myClickListener clickListener;
public SobotSelectPicAndVideoAdapter(Context context, List<SobotAlbumFile> list, SobotRecyclerCallBack callBack) {
mContext = context;
this.list = list;
this.callBack = callBack;
}
//得到当前选中的位置
public int getmSelectedPos() {
return mSelectedPos;
}
public void setmSelectedPos(int mSelectedPos) {
this.mSelectedPos = mSelectedPos;
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
/**
* 设置监听
*
* @param holder 监听对象
*/
public void setListener(RecyclerView.ViewHolder holder) {
// 设置监听
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callBack.onItemClickListener(v, (Integer) v.getTag());
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
callBack.onItemLongClickListener(v, (Integer) v.getTag());
return true;
}
});
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.sobot_select_pic_and_video_item, parent, false);
ViewHolder viewHolder = new ViewHolder(mContext, itemView);
setListener(viewHolder);//设置监听
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, int position) {
final ViewHolder contact = (ViewHolder) viewHolder;
final int finalPosition = position;
SobotAlbumFile albumFile = (SobotAlbumFile) list.get(position);
if (albumFile != null) {
if (position == (list.size() - 1)) {
contact.ll_open_other.setVisibility(View.VISIBLE);
contact.sobot_iv_img.setVisibility(View.GONE);
contact.check_box.setVisibility(View.GONE);
contact.tv_duration.setVisibility(View.GONE);
contact.ll_open_other.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (clickListener != null) {
clickListener.onClickOtherListener();
}
}
});
} else {
contact.ll_open_other.setOnClickListener(null);
contact.ll_open_other.setVisibility(View.GONE);
contact.sobot_iv_img.setVisibility(View.VISIBLE);
contact.check_box.setVisibility(View.VISIBLE);
contact.tv_duration.setVisibility(View.VISIBLE);
if (albumFile.getUri() != null) {
SobotBitmapUtil.display(mContext, albumFile.getUri(), contact.sobot_iv_img);
}
if (albumFile.getMediaType() == SobotAlbumFile.TYPE_VIDEO) {
contact.tv_duration.setVisibility(View.VISIBLE);
contact.tv_duration.setText(convertDuration(albumFile.getDuration()));
} else {
contact.tv_duration.setVisibility(View.GONE);
}
}
if (mSelectedPos == position) {
contact.check_box.setChecked(true);
contact.view_masking_select.setVisibility(View.VISIBLE);
} else {
contact.check_box.setChecked(false);
contact.view_masking_select.setVisibility(View.GONE);
}
contact.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSelectedPos != finalPosition) {//当前选中的position和上次选中不是同一个position 执行
contact.check_box.setChecked(true);
contact.view_masking_select.setVisibility(View.VISIBLE);
if (mSelectedPos != -1) {//判断是否有效 -1是初始值 即无效 第二个参数是Object 随便传个int 这里只是起个标志位
notifyItemChanged(mSelectedPos, 0);
}
mSelectedPos = finalPosition;
} else {
//点击是选中的本身,取消选中
mSelectedPos = -1;
contact.check_box.setChecked(false);
contact.view_masking_select.setVisibility(View.VISIBLE);
}
if (clickListener != null) {
clickListener.onCheckListener();
}
}
});
}
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
//payloads即有效负载,当首次加载或调用notifyDatasetChanged() ,notifyItemChange(int position)进行刷新时,payloads为empty 即空
if (payloads.isEmpty()) {
//如果payloads没数据,说明不是局部刷新,下面这句是关键,通过源码看 会执行不带payloads参数的onBindViewHolder
onBindViewHolder(holder, position);
} else {
//当调用notifyItemChange(int position, Object payload)进行布局刷新时,payloads不会empty ,所以真正的布局刷新应该在这里实现 重点!
if (mSelectedPos == position) {
holder.check_box.setChecked(true);
holder.view_masking_select.setVisibility(View.VISIBLE);
} else {
holder.check_box.setChecked(false);
holder.view_masking_select.setVisibility(View.GONE);
}
}
}
class ViewHolder extends RecyclerView.ViewHolder {
private ImageView sobot_iv_img;
private TextView tv_duration;
private CheckBox check_box;
private LinearLayout ll_open_other;
private View view_masking_select;
public ViewHolder(Context context, View itemView) {
super(itemView);
this.sobot_iv_img = itemView.findViewById(R.id.sobot_iv_img);
this.tv_duration = itemView.findViewById(R.id.tv_duration);
check_box = itemView.findViewById(R.id.check_box);
ll_open_other = itemView.findViewById(R.id.ll_open_other);
view_masking_select = itemView.findViewById(R.id.view_masking_select);
}
}
public List<SobotAlbumFile> getList() {
return list;
}
public void updateList(List<SobotAlbumFile> albumFileList) {
list.clear();
list.addAll(albumFileList);
notifyDataSetChanged();
}
public interface myClickListener {
void onClickOtherListener();
void onCheckListener();
}
public myClickListener getClickListener() {
return clickListener;
}
public void setClickListener(myClickListener clickListener) {
this.clickListener = clickListener;
}
public String convertDuration(@IntRange(from = 1) long duration) {
duration /= 1000;
int hour = (int) (duration / 3600);
int minute = (int) ((duration - hour * 3600) / 60);
int second = (int) (duration - hour * 3600 - minute * 60);
String hourValue = "";
String minuteValue;
String secondValue;
if (hour > 0) {
if (hour >= 10) {
hourValue = Integer.toString(hour);
} else {
hourValue = "0" + hour;
}
hourValue += ":";
}
if (minute > 0) {
if (minute >= 10) {
minuteValue = Integer.toString(minute);
} else {
minuteValue = "0" + minute;
}
} else {
minuteValue = "00";
}
minuteValue += ":";
if (second > 0) {
if (second >= 10) {
secondValue = Integer.toString(second);
} else {
secondValue = "0" + second;
}
} else {
secondValue = "00";
}
return hourValue + minuteValue + secondValue;
}
}
\ No newline at end of file
package com.sobot.widget.ui.base.picandroidvideo;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.IntDef;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
public static final int LINEARLAYOUT = 0;
public static final int GRIDLAYOUT = 1;
public static final int STAGGEREDGRIDLAYOUT = 2;
//限定为LINEARLAYOUT,GRIDLAYOUT,STAGGEREDGRIDLAYOUT
@IntDef({LINEARLAYOUT, GRIDLAYOUT, STAGGEREDGRIDLAYOUT})
//表示注解所存活的时间,在运行时,而不会存在. class 文件.
@Retention(RetentionPolicy.SOURCE)
public @interface LayoutManager {
public int type() default LINEARLAYOUT;
}
private int leftRight;
private int topBottom;
/**
* 头布局个数
*/
private int headItemCount;
/**
* 边距
*/
private int space;
/**
* 是否包含边距
*/
private boolean includeEdge;
/**
* 列数
*/
private int spanCount;
private @LayoutManager
int layoutManager;
/**
* GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param leftRight
* @param topBottom
* @param headItemCount
* @param layoutManager
*/
public SpaceItemDecoration(int leftRight, int topBottom, int headItemCount, @LayoutManager int layoutManager) {
this.leftRight = leftRight;
this.topBottom = topBottom;
this.headItemCount = headItemCount;
this.layoutManager = layoutManager;
}
/**
* GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param space
* @param includeEdge
* @param layoutManager
*/
public SpaceItemDecoration(int space, boolean includeEdge, @LayoutManager int layoutManager) {
this(space, 0, includeEdge, layoutManager);
}
/**
* GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param space
* @param headItemCount
* @param includeEdge
* @param layoutManager
*/
public SpaceItemDecoration(int space, int headItemCount, boolean includeEdge, @LayoutManager int layoutManager) {
this.space = space;
this.headItemCount = headItemCount;
this.includeEdge = includeEdge;
this.layoutManager = layoutManager;
}
/**
* GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param space
* @param headItemCount
* @param layoutManager
*/
public SpaceItemDecoration(int space, int headItemCount, @LayoutManager int layoutManager) {
this(space, headItemCount, true, layoutManager);
}
/**
* LinearLayoutManager or GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param space
* @param layoutManager
*/
public SpaceItemDecoration(int space, @LayoutManager int layoutManager) {
this(space, 0, true, layoutManager);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
switch (layoutManager) {
case LINEARLAYOUT:
setLinearLayoutSpaceItemDecoration(outRect, view, parent, state);
break;
case GRIDLAYOUT:
GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
//列数
spanCount = gridLayoutManager.getSpanCount();
// setNGridLayoutSpaceItemDecoration(outRect, view, parent, state);
setGridlayoutSpaceItemDecorition2(outRect, view, parent, state);
break;
case STAGGEREDGRIDLAYOUT:
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager();
//列数
spanCount = staggeredGridLayoutManager.getSpanCount();
setNGridLayoutSpaceItemDecoration(outRect, view, parent, state);
break;
default:
break;
}
}
/**
* LinearLayoutManager spacing
*
* @param outRect
* @param view
* @param parent
* @param state
*/
private void setLinearLayoutSpaceItemDecoration(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = space;
} else {
outRect.top = 0;
}
}
/**
* GridLayoutManager or StaggeredGridLayoutManager spacing
*
* @param outRect
* @param view
* @param parent
* @param state
*/
private void setNGridLayoutSpaceItemDecoration(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view) - headItemCount;
if (headItemCount != 0 && position == -headItemCount) {
return;
}
int column = position % spanCount;
if (includeEdge) {
outRect.left = space - column * space / spanCount;
outRect.right = (column + 1) * space / spanCount;
if (position < spanCount) {
outRect.top = space;
}
outRect.bottom = space;
} else {
outRect.left = column * space / spanCount;
outRect.right = space - (column + 1) * space / spanCount;
if (position >= spanCount) {
outRect.top = space;
}
}
}
/**
* GridLayoutManager设置间距(此方法最左边和最右边间距为设置的一半)
*
* @param outRect
* @param view
* @param parent
* @param state
*/
private void setGridLayoutSpaceItemDecoration(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
//判断总的数量是否可以整除
int totalCount = layoutManager.getItemCount();
int surplusCount = totalCount % layoutManager.getSpanCount();
int childPosition = parent.getChildAdapterPosition(view);
//竖直方向的
if (layoutManager.getOrientation() == GridLayoutManager.VERTICAL) {
if (surplusCount == 0 && childPosition > totalCount - layoutManager.getSpanCount() - 1) {
//后面几项需要bottom
outRect.bottom = topBottom;
} else if (surplusCount != 0 && childPosition > totalCount - surplusCount - 1) {
outRect.bottom = topBottom;
}
//被整除的需要右边
if ((childPosition + 1 - headItemCount) % layoutManager.getSpanCount() == 0) {
//加了右边后最后一列的图就非宽度少一个右边距
//outRect.right = leftRight;
}
outRect.top = topBottom;
outRect.left = leftRight / 2;
outRect.right = leftRight / 2;
} else {
if (surplusCount == 0 && childPosition > totalCount - layoutManager.getSpanCount() - 1) {
//后面几项需要右边
outRect.right = leftRight;
} else if (surplusCount != 0 && childPosition > totalCount - surplusCount - 1) {
outRect.right = leftRight;
}
//被整除的需要下边
if ((childPosition + 1) % layoutManager.getSpanCount() == 0) {
outRect.bottom = topBottom;
}
outRect.top = topBottom;
outRect.left = leftRight;
}
}
/**
* 紧挨四条边的item 不设置边距
*
* @param outRect
* @param view
* @param parent
* @param state
*/
private void setGridlayoutSpaceItemDecorition2(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
//判断总的数量是否可以整除
int totalCount = layoutManager.getItemCount();
int surplusCount = totalCount % layoutManager.getSpanCount();
int childPosition = parent.getChildAdapterPosition(view);
if (childPosition < spanCount) {//第一行
outRect.top = 0;
} else {
outRect.top = topBottom / 2;
}
if (childPosition % spanCount == 0) {//第一列
outRect.left = 0;
} else {
outRect.left = leftRight / 2;
}
if ((childPosition + 1) % spanCount == 0) {//最后一列
outRect.right = 0;
} else {
outRect.right = leftRight / 2;
}
if (childPosition>=totalCount-surplusCount) {//最后一行
outRect.bottom = 0;
} else {
outRect.bottom = topBottom;
}
}
}
\ No newline at end of file
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/sobot_common_gray7" />
<corners android:radius="22dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- checkbox 样式-->
<item android:drawable="@drawable/sobot_photo_selected" android:state_checked="true" />
<item android:drawable="@drawable/sobot_photo_unselected" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--自定义滚动条样式-->
<gradient
android:angle="45"
android:centerColor="#E1E7F0"
android:endColor="#E1E7F0"
android:startColor="#E1E7F0" />
<corners android:radius="2dp" />
<size android:width="4dp" />
</shape>
\ No newline at end of file
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/sobot_color" />
<corners android:radius="22dp" />
</shape>
\ No newline at end of file
<?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:background="@color/sobot_common_gray6"
android:orientation="vertical">
<include layout="@layout/sobot_common_layout_titlebar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/sobot_common_gray7"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/sobot_str_goto_setting_info"
android:textColor="@color/sobot_common_gray1"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_go_to_settring"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:text="@string/sobot_str_goto_setting_allow"
android:textColor="@color/sobot_color"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/sobot_rcy"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="3dp"
android:layout_weight="1"
android:horizontalSpacing="3dp"
android:scrollbarSize="10dp"
android:scrollbarThumbVertical="@drawable/sobot_custom_scroll_style"
android:verticalSpacing="3dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/sobot_btn_submit"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_margin="20dp"
android:background="@drawable/sobot_normal_btn_bg"
android:gravity="center"
android:stateListAnimator="@null"
android:text="@string/sobot_button_send"
android:textAllCaps="false"
android:textColor="@color/sobot_common_wenzi_white_gray"
android:textSize="17sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sobot_ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/sobot_common_gray7">
<ImageView
android:id="@+id/sobot_iv_img"
android:layout_width="match_parent"
android:layout_height="90dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_marginBottom="6dp"
android:drawableStart="@drawable/sobot_album_tag_video_white"
android:drawableLeft="@drawable/sobot_album_tag_video_white"
android:drawablePadding="6dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/sobot_common_wenzi_white_gray"
android:textSize="12sp"
android:visibility="gone" />
<View
android:id="@+id/view_masking_select"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/sobot_half_transparent"
android:visibility="gone" />
<LinearLayout
android:id="@+id/ll_open_other"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="26dp"
android:layout_height="26dp"
android:scaleType="centerCrop"
android:src="@drawable/sobot_icon_add" />
</LinearLayout>
<CheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="3dp"
android:background="@drawable/sobot_bg_checkbox"
android:button="@null"
android:clickable="false"
android:enabled="false" />
</FrameLayout>
\ No newline at end of file
......@@ -187,4 +187,9 @@
<string name="sobot_srl_try_again">Network error. Please check the network and try again</string>
<string name="sobot_srl_no_support_call">The device does not support making calls</string>
<string name="sobot_str_select_pic_video">Select photos and videos</string>
<string name="sobot_str_goto_setting_info">Currently, only partial access to photos or videos is allowed</string>
<string name="sobot_str_goto_setting_allow">Allow all></string>
<string name="sobot_button_send">Send</string>
</resources>
......@@ -40,11 +40,17 @@
<!--二级背景色-->
<color name="sobot_common_gray7">#262628</color>
<!--透明-->
<color name="sobot_transparent">#00000000</color>
<!--半透明-->
<color name="sobot_half_transparent">#73000000</color>
<!-- 主题色 默认绿色 -->
<color name="sobot_color">@color/sobot_common_green</color>
<!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_green_white">@color/sobot_color</color>
<!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_white_gray">@color/sobot_common_gray3</color>
<!--线条分割线颜色-->
<color name="sobot_common_line_gray">#272729</color>
......
......@@ -46,11 +46,17 @@
<!--二级背景色-->
<color name="sobot_common_gray7">#FFF2F5F7</color>
<!--透明-->
<color name="sobot_transparent">#00000000</color>
<!--半透明-->
<color name="sobot_half_transparent">#73000000</color>
<!-- 主题色 默认绿色 -->
<color name="sobot_color">@color/sobot_common_green</color>
<!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_green_white">@color/sobot_color</color>
<!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_white_gray">#FFFFFF</color>
<!--线条分割线颜色-->
<color name="sobot_common_line_gray">#EDEEF0</color>
......
......@@ -189,4 +189,9 @@
<string name="sobot_srl_ctrl_v_success">复制成功!</string>
<string name="sobot_srl_try_again">网络错误,请检查网络后重试</string>
<string name="sobot_srl_no_support_call">该设备不支持拨打电话</string>
<string name="sobot_str_select_pic_video">选择照片和视频</string>
<string name="sobot_str_goto_setting_info">当前仅允许访问部分照片或视频</string>
<string name="sobot_str_goto_setting_allow">允许全部 ></string>
<string name="sobot_button_send">发送</string>
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment