从 FrameLayout 生成 GIF
Posted
技术标签:
【中文标题】从 FrameLayout 生成 GIF【英文标题】:Generating GIF from FrameLayout 【发布时间】:2021-10-08 09:37:08 【问题描述】:您好,我正在尝试从动画视图生成 gif
简而言之,我在 FrameLayout 中有 ImageView 和动画视图,现在我想生成主 FrameLayout 的 gif,最低 sdk 级别为 19。getDrawingCache 位图并将它们按 gif 顺序排列可能会导致内存溢出问题。
当我点击“开始录制”时,我想要该特定视图的 gif 或视频。
【问题讨论】:
能否请您分享您现在的代码,以便我更好地理解并回答? 我不确定我是否理解您想要实现的目标。 嘿@AkshatTiwari 请检查附件图片 嘿@CristianHoldunu,请立即查看 如果我正确理解了您的要求,那么这个问题的答案可能超出了 SO 问题的范围。您将需要一个位图处理管道,可以将位图转换为 gif,您的实现以您想要的速率提供位图。可能是这个? github.com/nbadal/android-gif-encoder 【参考方案1】:首先,您需要实现这些库:
implementation 'com.blankj:utilcodex:1.30.6'
implementation 'com.waynejo:androidndkgif:0.3.3'
implementation 'com.jiang.android.observablescheduler:schedule:1.0.1'
-
第一个是一个有用的库,它包含所有必要的
帮助您的课程,例如 (
ImageUtils
, PathUtils
...)。
第二个是GIF的编解码。
第三个用于替换 AsyncTask
类
java.util.concurrent
XML :我试着做和你一样的事情:
<LinearLayout
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/viewToBeRecorded"
android:layout_
android:layout_
android:layout_gravity="center"
android:background="@android:color/holo_green_light"
android:gravity="center">
<TextView
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="View To Be Recorded"
android:textStyle="bold" />
</RelativeLayout>
<Button
android:id="@+id/changeBg"
android:layout_
android:layout_
android:text="Change Background"
android:textStyle="bold" />
<Button
android:id="@+id/startRecord"
android:layout_
android:layout_
android:text="Start Record"
android:textStyle="bold" />
<Button
android:id="@+id/stopRecord"
android:layout_
android:layout_
android:enabled="false"
android:text="Stop Record"
android:textStyle="bold" />
</LinearLayout>
Java:
public class MainActivity extends AppCompatActivity
private Button changeBg, startRecord, stopRecord;
private RelativeLayout viewToBeRecorded;
private boolean isRecording = false;
private GifEncoder mGifEncoder;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
startRecord.setOnClickListener(v ->
isRecording = true;
ToastUtils.showShort("Start recording...");
startRecord.setEnabled(false);
stopRecord.setEnabled(true);
generateGIF();
);
stopRecord.setOnClickListener(v ->
isRecording = false;
ToastUtils.showShort("Stop recording...");
startRecord.setEnabled(true);
stopRecord.setEnabled(false);
);
changeBg.setOnClickListener(v ->
Random rnd = new Random();
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewToBeRecorded.setBackgroundColor(color);
);
private void generateGIF()
JObservable.create((JObservable.OnSubscribe<String>) mSubscriber ->
try
File storageDir = new File(PathUtils.getExternalPicturesPath() + "/GIFs");
FileUtils.createOrExistsDir(storageDir);
File gifFile = new File(storageDir, "GIF" + System.currentTimeMillis() + ".gif");
String outputPath = gifFile.getAbsolutePath();
Bitmap firstFrame = ImageUtils.view2Bitmap(viewToBeRecorded);
try
mGifEncoder.init(firstFrame.getWidth(), firstFrame.getHeight(), outputPath, GifEncoder.EncodingType.ENCODING_TYPE_SIMPLE_FAST);
while (isRecording)
Bitmap frame = ImageUtils.view2Bitmap(viewToBeRecorded);
mGifEncoder.encodeFrame(frame, 100);
Thread.sleep(20);
mGifEncoder.close();
mSubscriber.notifyData(outputPath);
catch (FileNotFoundException e)
e.printStackTrace();
catch (Exception e)
mSubscriber.error(e);
).workedOn(Schedules.background())
.subscribeOn(Schedules.mainThread())
.subscribe(new Subscriber<String>()
@Override
public void notifyData(String outputPath)
FileUtils.notifySystemToScan(outputPath);
ToastUtils.showShort("GIF saved!");
@Override
public void error(Throwable t)
Log.e("View2GIF", "generateGIF throw error : " + t.getMessage());
);
private void initializeViews()
viewToBeRecorded = findViewById(R.id.viewToBeRecorded);
changeBg = findViewById(R.id.changeBg);
stopRecord = findViewById(R.id.stopRecord);
startRecord = findViewById(R.id.startRecord);
mGifEncoder = new GifEncoder();
输出:
别忘了补充:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
并确保存储权限已授予
【讨论】:
您好@Mouaad Abdelghafour AITALI 我感谢您的努力,但这对我没有帮助。我在捕获两个位图之间跳过的帧数的位图时导致 gif 滞后问题 @MahendraGohil 您可以更改 sleep 的值,例如Thread.sleep(20);
这将使您的应用每 20ms 捕获一帧
你好@Mouaad Abdelghafour AITALI 我已经试过了
@MahendraGohil 你没有在你的问题中添加你的动画代码,添加它以便我可以用我的代码测试它
对不起@Mouaad Abdelghafour AITALI,但我已经告诉过我生成位图序列对我不起作用以上是关于从 FrameLayout 生成 GIF的主要内容,如果未能解决你的问题,请参考以下文章
FrameLayout to RelativeLayout ClassCastException 即使没有使用 FrameLayout