First, you need to implement these libraries :
implementation 'com.blankj:utilcodex:1.30.6'
implementation 'com.waynejo:androidndkgif:0.3.3'
implementation 'com.jiang.android.observablescheduler:schedule:1.0.1'
- The first one is a useful library, which contains all the necessary
classes to help you, such as (
ImageUtils
, PathUtils
...).
- The second one is for the encoding and decoding GIF.
- The Third one is for replacing the
AsyncTask
class with
java.util.concurrent
The XML : I tried to make the same thing you did :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/viewToBeRecorded"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@android:color/holo_green_light"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Background"
android:textStyle="bold" />
<Button
android:id="@+id/startRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Record"
android:textStyle="bold" />
<Button
android:id="@+id/stopRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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();
}
OUTPUT :

Don't forget to add :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and make sure the Storage permission is granted