我已将我targetSdkVersion
的 28更新到 30,我注意到它getAdapterPosition()
已被弃用(我不确定何时发生这种情况)。
在文档中,他们说:
此方法已弃用。
当适配器嵌套其他适配器时,此方法会造成混淆。如果您在 Adapter 的上下文中调用它,您可能想要调用getBindingAdapterPosition()或者如果您想要 RecyclerView 看到的位置,您应该调用getAbsoluteAdapterPosition()。
该文档还说明了以下内容:
请注意,如果您正在查询 RecyclerView 看到的位置,则应使用getAbsoluteAdapterPosition()(例如,您想使用它来保存滚动状态)。如果您要查询访问 RecyclerView.Adapter 内容的位置,则应使用getBindingAdapterPosition()。
我的理解是:
getBindingAdapterPosition
当您想要获取适配器位置时应该使用它(如果它仍然存在于适配器中)。如果它不再存在于适配器中,它将返回-1
( NO_POSITION )。getAbsoluteAdapterPosition
应该用于获取位置,如RecyclerView
所见。例如,如果某个项目已被删除,但尚未从ViewHolder
.换句话说,如果我的 中有4
项目Adapter
,我删除位置0
和查询,getAbsoluteAdapterPosition
并且getBindingAdapterPosition
在项目从 中删除之前ViewHolder
,然后getAbsoluteAdapterPosition
将返回0
(因为视图仍在 中ViewHolder
)并getBindingAdapterPosition
返回-1
(因为它不再存在于适配器中)。
我通过记录以下内容测试了差异:
Log.e("difference", "getAdapterPosition = "+myHolder.getAdapterPosition()+" getBindingAdapterPosition = "+myHolder.getBindingAdapterPosition()+" getAbsoluteAdapterPosition = "+myHolder.getAbsoluteAdapterPosition()); …
Run Code Online (Sandbox Code Playgroud) 这是一个很长的问题,但我必须解释我正在经历的问题才能正确地解决问题.希望我能找到像@fadden或@mstorsjo这样的人来看看这个问题.
有关此问题的最新更新,请参阅编辑3.
我目前正在快速精确地寻求使用MediaCodec
.我目前要逐帧跳过的是,我首先得到总帧数:
mediaInfo.totalFrames = videoTrack.getSamples().size();
Run Code Online (Sandbox Code Playgroud)
然后我得到视频文件的长度:
mediaInfo.durationUs = videoTrack.getDuration() * 1000 *1000 / timeScale;
//then calling:
public long getDuration() {
if (mMediaInfo != null) {
return (int) mMediaInfo.durationUs / 1000; // to millisecond
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
现在,当我想要获得下一帧时,我会调用以下内容:
mNextFrame.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int frames = Integer.parseInt(String.valueOf(getTotalFrames));
int intervals = Integer.parseInt(String.valueOf(mPlayer.getDuration() / frames));
if (mPlayer.isPlaying()) {
mPlayer.pause();
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
} else {
mPlayer.seekTo(mPlayer.getCurrentPosition() + intervals);
}
}
}); …
Run Code Online (Sandbox Code Playgroud) 根据docs,您可以CamcorderProfile
用来获取设备的默认视频编解码器格式,然后将其设置为MediaRecorder
,如下所示:
CamcorderProfile mProfile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
//
mMediaRecorder.setVideoEncoder(mProfile.videoCodec);
Run Code Online (Sandbox Code Playgroud)
但是由于某种原因,它返回了错误的格式。
我正在使用CameraView库,并在FullVideoRecorder类中定义了以下内容:
switch (mResult.getVideoCodec()) {
case H_263: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); break;
case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break;
case DEVICE_DEFAULT: mMediaRecorder.setVideoEncoder(mProfile.videoCodec); break;
}
Run Code Online (Sandbox Code Playgroud)
当我将视频编码器设置为时,遇到问题的设备可以很好地工作H_263
,但是由于某种原因,当我将其设置为默认时,它会崩溃-在这种情况下,默认意味着CamcorderProfile
应选择设备默认的视频编解码器格式。
我的问题:
有什么原因CamcorderProfile.videoCodec
会返回错误的值,如何解决?
编辑 -添加更多信息
我实现了以下内容,以确保是否CamcoderProfile
返回了错误的值:
//In onCreate
CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
//getVideoCodec method below
String profileCodec = getVideoCodec(camcorderProfile.videoCodec);
//Log the result I get
Log.e("Video Codec =", profileCodec);
private String getVideoCodec(int videoCodec){
switch(videoCodec){
case MediaRecorder.VideoEncoder.H263:
return …
Run Code Online (Sandbox Code Playgroud) 请看编辑1
我正在忙于将FFmpegMediaMetadataRetriever
预构建.aar
文件添加到我的项目中以减少每个体系结构的Apk文件大小.
这篇帖子为他增加了以下内容Gradle
:
android {
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86, armeabi-v7a, and mips.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
// Specifies that we want …
Run Code Online (Sandbox Code Playgroud) 请阅读编辑3 ..
我正试图在a上实现捏缩放SurfaceView
.我已经做了很多关于此的研究,我发现这个类实现了捏缩放.这是我如何修改它:
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {
private SurfaceView mSurfaceView;
private enum Mode {
NONE,
DRAG,
ZOOM
}
private static final String TAG = "ZoomLayout";
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 4.0f;
private Mode mode;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
// Where the finger first touches the screen
private float startX = 0f;
private float startY = 0f;
// How …
Run Code Online (Sandbox Code Playgroud) 我正在使用MediaMetadataRetriever
视频中特定时间检索缩略图.这就是我实现这个目标的方法:
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
try {
metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time = Long.valueOf(duration)/3;
Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
imgone.setImageBitmap(bitmap1);
}catch (Exception ex) {
Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
这会返回一个预期的位图/缩略图,问题是如果我想在视频中的不同时间获得多个缩略图,如下所示:
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
try {
metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time = Long.valueOf(duration)/3;
long time2 = time+time;
long time3 = time+time+time;
Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
Bitmap bitmap2 = metadataRetriever.getFrameAtTime(time2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
Bitmap bitmap3 = metadataRetriever.getFrameAtTime(time3,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
imgone.setImageBitmap(bitmap1);
imgtwo.setImageBitmap(bitmap2);
imgthree.setImageBitmap(bitmap3);
}catch (Exception ex) {
Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
然后它仍然只返回相同的缩略图,我不确定它是否是因为只有一个缩略图可用于视频或什么,但我尝试了不同的视频文件具有相同的结果.
我已尝试更改 …
我想确认一下,我所做的确实是正确的方法,因为某些元素的行为异常。
首先,据我了解,我有一个横向和纵向布局,这样做会自动检测手机是否处于纵向/横向模式:
- layout
- activity_video_player.xml
- layout-land
- activity_video_player.xml
Run Code Online (Sandbox Code Playgroud)
然后,当用户从图库中选择一个视频时,我通过执行以下操作(在中OnCreate
)来检查该视频是横向拍摄还是纵向拍摄:
int w;
int h;
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(this, videoURI);
String height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
w = Integer.parseInt(width);
h = Integer.parseInt(height);
if (w > h) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Run Code Online (Sandbox Code Playgroud)
我已经对此进行了测试,并且工作正常,但是我注意到我的某些xml元素(播放按钮)放置不正确。
所以我的应用程序流程是:
MainActivity --> SelectvidButton --> Gallery Intent --> VideoPlayActivity
Run Code Online (Sandbox Code Playgroud)
我的问题
这是这样做的正确方法吗?如果是,是否有某些原因导致某些xml元素放置不正确?
编辑1:
我注意到,只有在首次启动活动时才会发生这种情况,如果我按“后退”按钮并再次选择相同的视频,则布局完全像我想要的那样。
编辑2:
我还注意到,只有在上一个活动(MainActivity)与所选视频的方向相同时,才会发生这种情况。
我的应用程序在Play商店上发布,我注意到在调用时我没有询问权限:
File savedImagesDirectory = getBaseContext.getExternalFilesDir("SavedImages");
if(savedImagesDirectory != null) {
if (!savedImagesDirectory.exists()) {
if (savedImagesDirectory.mkdir()) ; //directory is created;
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,在没有运行时权限的情况下调用它时我没有遇到任何崩溃.我在运行Nougat的设备上进行了测试,文件已经创建,我没有遇到任何崩溃.
我只有我的清单中的权限,但我不问运行时权限.
我已经看到很多关于SO的答案,说在外部文件目录中创建文件夹/文件时应该询问运行时权限.
我的问题:
在调用上述内容时我应该询问运行时权限吗?如果是的话,为什么我没有遇到任何崩溃?
如果有人可以提供我可以阅读的链接,也会有所帮助.
目前
我打开与画廊Intent
,用户可以接着从后将该文件复制到指定文件夹的画廊视频.一切正常.
我希望ProgressBar
在用户选择视频(在图库中)之后显示一个权限,然后progresbar.dismiss
在文件完成复制后显示.
这是类似的问题,但没有答案(没有任何效果):
这就是我称之为画廊的方式:
public void selectVideoFromGallery()
{
Intent intent;
if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
{
intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
}
else
{
intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.INTERNAL_CONTENT_URI);
}
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.putExtra("return-data", true);
startActivityForResult(intent,SELECT_VIDEO_REQUEST);
}
Run Code Online (Sandbox Code Playgroud)
我在progressbar.show();
这里试过(上图),但显然它会在选择视频之前开始显示.
这是我的OnActivityResult
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(requestCode == SELECT_VIDEO_REQUEST && resultCode == RESULT_OK)
{
if(data.getData()!=null)
{
//copy file to new folder
Uri selectedImageUri = data.getData();
String sourcePath = getRealPathFromURI(selectedImageUri); …
Run Code Online (Sandbox Code Playgroud) 我有这个方法 RecyclerView.Adapter
public void filter(String text) {
mDataSet.clear();
if(text.isEmpty()){
mDataSet.addAll(mDataSet);
} else{
text = text.toLowerCase();
for(AppInfo item: mDataSet){
if(item.getAppName().toLowerCase().contains(text)){
mDataSet.add(item);
}
}
}
notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)
我试图Activity
通过调用来访问它:
search_view.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//Here is where I'm trying to call the method
mAdapter.filter(query);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,我无法访问该方法.有人可以向我解释为什么会这样吗?