This is the 7th day of my participation in the November Gwen Challenge. Check out the details: 2021 Last Gwen Challenge

Results show

Note that dialogue is a sentence out, and, the bottom of the new dialogue, scrolling up when, can set the speed of scrolling, this is to rewrite the RecyclerView of the scrolling method.

Video presentation

This is a composite video effect of multiple images, changing the image once a second, ffMPEG can adjust the display time of the image

Video presentation

Section video steps

  1. Find a joke, preferably in a conversational format
  2. Turn the conversation into pictures
  3. Combine the pictures into a video

Note: All operations are carried out on mobile phones, FFMPEG uses autoJS FFMPEG plug-in.

The environment

Mi 11 Pro Android version: 11 Autojs version: 9.0.11 FFMPEG version: v4.4-dev-416

Here’s what you’ll learn

  • Use FFMPEG to combine images into video
  • Basic use of RecyclerView
  • A chat interface template
  • Immersive notification bar
  • RecyclerView updates data
  • RecyclerView control rolling speed
  • Rewrite some methods of layoutManager
  • RecyclerView items of a variety of layout methods
  • GradientDrawable usage

The code on

1. Stop other scripts

Debugging is a must, because we will debug the script many times, so you need to stop the previous script, otherwise the autoJS will hang soon, or other bugs will appear

engines.all().map((ScriptEngine) = > {
  if (engines.myEngine().toString() !== ScriptEngine.toString()) {
    ScriptEngine.forceStop();
  }
});
Copy the code
2. Import the classes

Note that some classes begin with Packages.

importClass(android.graphics.drawable.GradientDrawable);
importClass(android.view.WindowManager);
importClass(android.view.View);
importClass(Packages.androidx.recyclerview.widget.LinearSmoothScroller);
importClass(android.graphics.Color);
importClass(Packages.androidx.recyclerview.widget.LinearLayoutManager);
importClass(Packages.androidx.recyclerview.widget.RecyclerView);
Copy the code
3. Calculate the height of the notification bar
const resources = context.getResources();
const status_bar_height = resources.getDimensionPixelSize(
  resources.getIdentifier("status_bar_height"."dimen"."android"));Copy the code
4. The UI interface

Notice the format of comments in XML

ui.layout(
  <vertical>The title * /} {/ *<horizontal>
      <img></img>
      <text>Video clips</text>
      <img></img>
    </horizontal>
    <View></View>{/* Chat content */}<androidx.recyclerview.widget.RecyclerView
    ></androidx.recyclerview.widget.RecyclerView>{/ * * / bottom bar}<horizontal>
      <img></img>
      <View></View>
      <img></img>
      <img></img>
    </horizontal>
  </vertical>
);
Copy the code
5. Read the profile picture

Note that in the exit event, image collection is added to avoid memory leaks

let leftAvatarPath = files.path("./leftAvatar.jpg");
let rightAvatarPath = files.path("./rightAvatar.jpg");

let leftAvatar = images.read(leftAvatarPath);
let rightAvatar = images.read(rightAvatarPath);

let leftAvatarBitmap = leftAvatar.bitmap;
let rightAvatarBitmap = rightAvatar.bitmap;
events.on("exit".function () {
  leftAvatar.recycle();
  rightAvatar.recycle();
});
Copy the code
6. Format your jokes

Format for

Left: I'm going to tell that girl I love her, right Left: If you have to put a time limit on this love, LEFT: I hope it is 10,000 years...Copy the code

~ line.indexof (“left:”)

! ~ line.indexof (“left:”)

It’s easy to remember. An exclamation mark means no, no exclamation mark means yes.

let jokeContent = files.read("/sdcard/joke.js");
jokeContent = jokeContent.trim();
let lines = jokeContent.split("\n");
var len = lines.length;
let dataList = [];
for (var i = 0; i < len; i++) {
  let line = lines[i];
  if (~line.indexOf("left:")) {
    dataList.push({
      avatar: leftAvatarBitmap,
      content: line.replace("left:".""),
      direction: "left"}); }else if (~line.indexOf("right:")) {
    dataList.push({
      avatar: rightAvatarBitmap,
      content: line.replace("right:".""),
      direction: "right"}); }}Copy the code

The dataList element has three attributes: avatar, conversation, direction,

7. Click Start Now

This is because when you take a screenshot, the system will have a popup, so you have to use a multi-thread to click on the popup

threads.start(function () {
  let view = text("Begin immediately.").visibleToUser(true).boundsInside(0.0, device.width, device.height).findOne();
  view.click();
});
Copy the code
8. Generate dialogue and take screenshots

Conversations occur sentence by sentence. It is impossible to present all conversations at once. Otherwise, it would be called chat records, not conversations. RecyclerView to refresh data after a dialog sentence appears,

If the dialog reaches the bottom of the UI, it will need to scroll into line of sight, preferably slowly, rather than all at once, so you need to rewrite the smoothScrollToPosition method to control the scrolling speed.


setInterval(() = > {
  let position = newDataList.length;
  ui.run(function () {
    recyclerView.adapter.notifyItemInserted(position - 1);
    recyclerView.smoothScrollToPosition(position - 1);
  });
  if (imgNum < 10) {
    imgNum = "0" + imgNum;
  }
  log(imgNum); / / 00-28
  images.captureScreen("/sdcard/" + imgNum + ".png");
  imgNum++;
}, 1000);
Copy the code
9. RecyclerView Setting Adapter
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
let recycleAdapter = createRecyclerViewAdapter(newDataList);
recyclerView.setAdapter(recycleAdapter);
Copy the code
10. Talk about different layouts
let leftBoxXml = (
  <horizontal margin="0 15 0 0">
    <img id="img" marginRight="8" w="45dp" h="45dp" circle="true"></img>
    <text id="content" textColor="#cc000000" textSize="17sp" padding="11" layout_height="wrap_content"></text>
  </horizontal>
);
let rightBoxXml = (
  <horizontal margin="0 15 0 0" layout_width="match_parent" layout_height="wrap_content" gravity="right">
    <text id="content" textColor="#cc000000" textSize="17sp" padding="11" marginRight="8"></text>
    <img id="img" w="45dp" h="45dp" circle="true"></img>
  </horizontal>
);
Copy the code
11. Create RecyclerView. Adapter

For those who do not know RecyclerView, it is a little difficult, for those who often use RV, the most important sentence is view.content.setMaxWidth(maxWidth);

This controls the maximum width of the view, so that if the conversation is too long, you can avoid overwriting the avatar;

ViewType, the left and right layout is defined by that;

OnCreateViewHolder: Generates the layout;

OnBindViewHolder: Bind data to the layout

GetItemCountr: Number of data;

GetItemViewType: Layout type, currently left and right, usually head and foot

return RecyclerView.Adapter({ onCreateViewHolder: function (parent, viewType) { let view; let holder; if (viewType === 0) { view = ui.inflate(leftBoxXml, parent, false); view.content.setMaxWidth(maxWidth); setBackgroundRoundRounded(view.content); holder = JavaAdapter(RecyclerView.ViewHolder, {}, view); } else { view = ui.inflate(rightBoxXml, parent, false); view.content.setMaxWidth(maxWidth); setBackgroundRoundRounded(view.content, "#96ec69"); holder = JavaAdapter(RecyclerView.ViewHolder, {}, view); } return holder; }, onBindViewHolder: function (holder, position) { let data = dataList[position]; holder.itemView.img.setImageBitmap(data.avatar); holder.itemView.content.setText(data.content); }, getItemCount: function () { return dataList.length; }, getItemViewType: function (position) { return dataList[position].direction === "left" ? 0:1; }});Copy the code
12. Composite video from multiple images
let cmd = " -f concat -safe 0 -i /sdcard/input.txt -vsync vfr -pix_fmt yuv420p /sdcard/output1.mp4";
log(ffmpeg.inProcess.exec(cmd));
app.viewFile("/sdcard/output1.mp4");
Copy the code

Quotes.

Ideas are the most important, other Baidu, Bing, StackOverflow, Github, Android docs, AutoJS docs, and last but not least, ask in the group

The statement

This tutorial is intended for learning purposes only and is not intended for any other use

Wechat official account tooth Uncle tutorial