Commit a64a3da5 by zhengnw@sobot.com

widget 1.2.6

parent b943125c
...@@ -35,13 +35,12 @@ dependencies { ...@@ -35,13 +35,12 @@ dependencies {
implementation 'com.google.android.material:material:1.4.+' implementation 'com.google.android.material:material:1.4.+'
implementation project(':sobot_common') implementation project(':sobot_common')
implementation project(':sobot_widget') implementation project(':sobot_widget')
implementation project(':sobot_album') // implementation project(':sobot_album')
// implementation 'com.sobot.library:widget:0.3' // implementation 'com.sobot.library:widget:0.3'
// api 'com.sobot.library:sobotcommon:1.0' // api 'com.sobot.library:sobotcommon:1.0'
// api 'com.sobot.library:sobotcommon_x:1.0' // api 'com.sobot.library:sobotcommon_x:1.0'
implementation 'com.github.bumptech.glide:glide:4.9.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' // implementation 'com.facebook.fresco:fresco:1.13.0'
//android x 可以用这个 ,普通版不能用这个 //android x 可以用这个 ,普通版不能用这个
// implementation 'com.facebook.fresco:fresco:2.6.0' // implementation 'com.facebook.fresco:fresco:2.6.0'
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:theme="@style/sobot_activity_def_theme"
android:configChanges="orientation|keyboardHidden|screenSize|touchscreen|navigation|locale|fontScale|uiMode|screenLayout|smallestScreenSize"> android:configChanges="orientation|keyboardHidden|screenSize|touchscreen|navigation|locale|fontScale|uiMode|screenLayout|smallestScreenSize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
......
...@@ -9,14 +9,6 @@ import android.net.Uri; ...@@ -9,14 +9,6 @@ import android.net.Uri;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; 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.SobotLoginTools;
import com.sobot.common.login.callback.SobotResultBlock; import com.sobot.common.login.callback.SobotResultBlock;
import com.sobot.common.login.callback.SobotResultCode; import com.sobot.common.login.callback.SobotResultCode;
...@@ -32,14 +24,11 @@ import com.sobot.widget.refresh.layout.footer.ClassicsFooter; ...@@ -32,14 +24,11 @@ import com.sobot.widget.refresh.layout.footer.ClassicsFooter;
import com.sobot.widget.refresh.layout.header.ClassicsHeader; import com.sobot.widget.refresh.layout.header.ClassicsHeader;
import com.sobot.widget.ui.SobotMarkConfig; import com.sobot.widget.ui.SobotMarkConfig;
import com.sobot.widget.ui.base.SobotBaseActivity; 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.rich.HtmlToolUtils;
import com.sobot.widget.ui.toast.SobotToastUtil; import com.sobot.widget.ui.toast.SobotToastUtil;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
public class MainActivity extends SobotBaseActivity { public class MainActivity extends SobotBaseActivity {
...@@ -285,42 +274,43 @@ public class MainActivity extends SobotBaseActivity { ...@@ -285,42 +274,43 @@ public class MainActivity extends SobotBaseActivity {
// } // }
// openAlbum(); // openAlbum();
// selectPicFromLocal();
} }
private void openAlbum() { // private void openAlbum() {
SobotAlbum.album(MainActivity.this) // SobotAlbum.album(MainActivity.this)
.multipleChoice() // .multipleChoice()
.columnCount(4) // .columnCount(4)
.selectCount(4) // .selectCount(4)
.camera(false) // .camera(false)
.cameraVideoQuality(1) // .cameraVideoQuality(1)
.cameraVideoLimitDuration(Integer.MAX_VALUE) // .cameraVideoLimitDuration(Integer.MAX_VALUE)
.cameraVideoLimitBytes(Integer.MAX_VALUE) // .cameraVideoLimitBytes(Integer.MAX_VALUE)
.checkedList(mAlbumFiles) // .checkedList(mAlbumFiles)
.widget( // .widget(
Widget.newDarkBuilder(MainActivity.this) // Widget.newDarkBuilder(MainActivity.this)
.title("") // .title("")
.build() // .build()
) // )
.onResult(new Action<ArrayList<AlbumFile>>() { // .onResult(new Action<ArrayList<AlbumFile>>() {
@Override // @Override
public void onAction(@NonNull ArrayList<AlbumFile> result) { // public void onAction(@NonNull ArrayList<AlbumFile> result) {
if (result.size() > 0) { // if (result.size() > 0) {
//
//
} // }
} // }
}) // })
.onCancel(new Action<String>() { // .onCancel(new Action<String>() {
@Override // @Override
public void onAction(@NonNull String result) { // public void onAction(@NonNull String result) {
//取消选择 // //取消选择
} // }
}) // })
.start(); // .start();
} // }
//
private ArrayList<AlbumFile> mAlbumFiles = new ArrayList<>();//编辑的图片地址 // private ArrayList<AlbumFile> mAlbumFiles = new ArrayList<>();//编辑的图片地址
@Override @Override
protected void initData() { protected void initData() {
......
...@@ -23,6 +23,7 @@ public class MyApp extends MultiDexApplication { ...@@ -23,6 +23,7 @@ public class MyApp extends MultiDexApplication {
SobotCommonApi.setShowLogDebug(true); SobotCommonApi.setShowLogDebug(true);
SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.LANDSCAPE_SCREEN, false); SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.LANDSCAPE_SCREEN, false);
SobotWidgetApi.setSwitchMarkStatus(SobotMarkConfig.DISPLAY_INNOTCH, 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 { ...@@ -22,7 +22,8 @@ dependencies {
compileOnly 'com.google.android.material:material:1.4.+' compileOnly 'com.google.android.material:material:1.4.+'
compileOnly 'androidx.appcompat:appcompat:1.0.0' compileOnly 'androidx.appcompat:appcompat:1.0.0'
compileOnly 'androidx.recyclerview:recyclerview: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' api 'com.sobot.library:picture_x:1.2.0'
} }
......
...@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) { ...@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) {
ext { ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名 PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'album' //项目名 PUBLISH_ARTIFACT_ID = 'album' //项目名
PUBLISH_VERSION = '1.0.3' //版本号 PUBLISH_VERSION = '1.0.4' //版本号
} }
......
...@@ -60,7 +60,7 @@ public class SobotAlbumActivity extends SobotBaseActivity { ...@@ -60,7 +60,7 @@ public class SobotAlbumActivity extends SobotBaseActivity {
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView() {
mTvMessage = findViewById(R.id.tv_message); mTvMessage = findViewById(R.id.tv_message);
recyclerView = findViewById(R.id.recycler_view); recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
......
package com.sobot.album.app.album; package com.sobot.album.app.album;
import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.CompoundButton; import android.widget.CompoundButton;
...@@ -14,7 +11,6 @@ import android.widget.CompoundButton; ...@@ -14,7 +11,6 @@ import android.widget.CompoundButton;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.core.content.ContextCompat;
import com.sobot.album.Action; import com.sobot.album.Action;
import com.sobot.album.AlbumFile; import com.sobot.album.AlbumFile;
...@@ -100,7 +96,7 @@ public class AlbumActivity extends SobotBaseActivity implements ...@@ -100,7 +96,7 @@ public class AlbumActivity extends SobotBaseActivity implements
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
setTitle(R.string.sobot_album_select_images); setTitle(R.string.sobot_album_select_images);
getLeftMenu().setOnClickListener(new View.OnClickListener() { getLeftMenu().setOnClickListener(new View.OnClickListener() {
@Override @Override
......
...@@ -62,7 +62,7 @@ public class GalleryActivity extends SobotBaseActivity implements Contract.Galle ...@@ -62,7 +62,7 @@ public class GalleryActivity extends SobotBaseActivity implements Contract.Galle
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(),this); mView = new GalleryView<>(this, getSupportFragmentManager(),this);
Bundle argument = getIntent().getExtras(); Bundle argument = getIntent().getExtras();
assert argument != null; assert argument != null;
......
...@@ -35,7 +35,7 @@ public class NullActivity extends SobotAlbumBaseActivity implements Contract.Nul ...@@ -35,7 +35,7 @@ public class NullActivity extends SobotAlbumBaseActivity implements Contract.Nul
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
mView = new NullView(this, this); mView = new NullView(this, this);
Bundle argument = getIntent().getExtras(); Bundle argument = getIntent().getExtras();
......
...@@ -104,7 +104,7 @@ public class CameraActivity extends SobotAlbumBaseActivity { ...@@ -104,7 +104,7 @@ public class CameraActivity extends SobotAlbumBaseActivity {
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
} }
......
...@@ -38,7 +38,7 @@ public class GalleryActivity extends SobotAlbumBaseActivity implements Contract. ...@@ -38,7 +38,7 @@ public class GalleryActivity extends SobotAlbumBaseActivity implements Contract.
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(), this); mView = new GalleryView<>(this, getSupportFragmentManager(), this);
Bundle argument = getIntent().getExtras(); Bundle argument = getIntent().getExtras();
......
...@@ -51,7 +51,7 @@ public class GalleryAlbumActivity extends SobotAlbumBaseActivity implements Cont ...@@ -51,7 +51,7 @@ public class GalleryAlbumActivity extends SobotAlbumBaseActivity implements Cont
} }
@Override @Override
protected void initView() throws InterruptedException { protected void initView(){
mView = new GalleryView<>(this, getSupportFragmentManager(), this); mView = new GalleryView<>(this, getSupportFragmentManager(), this);
Bundle argument = getIntent().getExtras(); Bundle argument = getIntent().getExtras();
......
...@@ -25,9 +25,10 @@ android { ...@@ -25,9 +25,10 @@ android {
dependencies { dependencies {
api fileTree(include: ['*.jar'], dir: 'libs') 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' compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
api 'com.sobot.library:utils:1.1.3' 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) { ...@@ -12,7 +12,7 @@ task androidSourcesJar(type: Jar) {
ext { ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名 PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'widget_x' //项目名 PUBLISH_ARTIFACT_ID = 'widget_x' //项目名
PUBLISH_VERSION = '1.2.4' //版本号 PUBLISH_VERSION = '1.2.6' //版本号
} }
......
...@@ -32,5 +32,10 @@ ...@@ -32,5 +32,10 @@
android:screenOrientation="behind" android:screenOrientation="behind"
android:theme="@style/sobot_activity_def_theme" android:theme="@style/sobot_activity_def_theme"
android:windowSoftInputMode="adjustResize" /> 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> </application>
</manifest> </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);
}
/*
* 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 @@ ...@@ -187,4 +187,9 @@
<string name="sobot_srl_try_again">Network error. Please check the network and try again</string> <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_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> </resources>
...@@ -40,11 +40,17 @@ ...@@ -40,11 +40,17 @@
<!--二级背景色--> <!--二级背景色-->
<color name="sobot_common_gray7">#262628</color> <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_color">@color/sobot_common_green</color>
<!--文字颜色 绿色变白色--> <!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_green_white">@color/sobot_color</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> <color name="sobot_common_line_gray">#272729</color>
......
...@@ -46,11 +46,17 @@ ...@@ -46,11 +46,17 @@
<!--二级背景色--> <!--二级背景色-->
<color name="sobot_common_gray7">#FFF2F5F7</color> <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_color">@color/sobot_common_green</color>
<!--文字颜色 绿色变白色--> <!--文字颜色 绿色变白色-->
<color name="sobot_common_wenzi_green_white">@color/sobot_color</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> <color name="sobot_common_line_gray">#EDEEF0</color>
......
...@@ -189,4 +189,9 @@ ...@@ -189,4 +189,9 @@
<string name="sobot_srl_ctrl_v_success">复制成功!</string> <string name="sobot_srl_ctrl_v_success">复制成功!</string>
<string name="sobot_srl_try_again">网络错误,请检查网络后重试</string> <string name="sobot_srl_try_again">网络错误,请检查网络后重试</string>
<string name="sobot_srl_no_support_call">该设备不支持拨打电话</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> </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