Dynamic Replacement of the Bottom Navigation Bar of Android
- 2021-10-25 07:55:18
- OfStack
The dynamic replacement scheme of the navigation bar at the bottom of Android is for your reference, and the specific contents are as follows
1. Generally speaking, under 1 general circumstances, the BottomTab of our app will have the following implementation methods.
1), customize view, and then write your own logic to achieve mutual exclusion.
2) Use RadioGroup + RadioButton to implement the bottom Tab.
The degree of freedom ratio is extremely high, so you can rewrite RadioButton if you want to achieve complexity.
3), using TabLayout in google design package.
It can go up, down and slide
If you are lazy, you can set up some resources according to the existing api, or you can use setCustomView ()
4), using BottomNavigationView in google design package.
(1) Use menu to set up resources
(2) There is a default animation effect
2. This article introduces the similar method of dynamically replacing the bottom navigation resource picture according to the background distribution in JD.COM and Taobao (based on TabLayout)
Since it is mentioned that dynamic replacement definitely means downloading resources, let's talk about IntentService first
onHandlerIntent (Intent intent) is the most important method
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_FOO.equals(action)) {
// In which time-consuming tasks are processed, and when all time-consuming tasks are finished, IntentService It will be automatic finish Drop, don't need developers to care.
}
}
}
The reason for choosing IntentService is that the following operations are time-consuming operations, so we simply encapsulate them into service, and we only need to start this Service at the right time to be ok
Need to download resource compression package Because it is dynamic replacement, it must involve pre-download, so the data format should be set first (the following is the data format).
{
"currentInfo":{// Current style
"id":"111",
"imageZipUrl": Your download address ,
"tabNamesList":[
" Home page 1"," Nearby 1"," Discover 1"," Mine 1"
],
"tabColorNormal":"B0C4DE",
"tabColorHighlight":"F7B62D",
"startTime": Start time ,
"deadLineTime": End time
},
"nextInfo":{// Under 1 Style of secondary display
"id":"111",
"imageZipUrl": Your download address ,
"tabNamesList":[
" Home page 2"," Nearby 2"," Discover 2"," Mine 2"
],
"tabColorNormal":"B0C4DE",
"tabColorHighlight":"FE6246",
"startTime": Start time ,
"deadLineTime": End time
}
}
Need to store resource compression package
Code for downloading and storing files (Retrofit is used here for downloading)
// Download a file
Response<ResponseBody> zipFile = ServiceGenerator.createService(HomeService.class)
.downloadFileRetrofit(getFileDownLoadUrl(homeTabImageInfoBean, type))
.execute();
// Get the file stream
ResponseBody zipBody = zipFile.body();
LogUtils.d("DownLoad", " Download complete ");
// Create 1 Files
File zipDirectory = new File(FilePathUtil.getHuaShengHomeTabZipDirectory(getApplicationContext())
+ createZipFileName(homeTabImageInfoBean, type));
// If the file does not exist, create a folder
if (!zipDirectory.exists()) {
zipDirectory.createNewFile();
}
// Save a file
FileUtils.writeFile2Disk(zipBody, zipDirectory);
Extract the resource and delete the file (the extraction method is written at the bottom of the article because it is too long)
// Extract a file And delete the file
if (ZipUtils.unzipFile(zipDirectory.getAbsolutePath(),
CURRENT.equals(type) ? FilePathUtil.getHuaShengHomeTabImgCurrentDirectory(getApplicationContext())
: FilePathUtil.getHuaShengHomeTabImgNextDirectory(getApplicationContext()))) {
// Save the unzipped address of the file
saveFileDirPath(homeTabImageInfoBean, type,
CURRENT.equals(type) ? FilePathUtil.getHuaShengHomeTabImgCurrentDirectory(getApplicationContext())
: FilePathUtil.getHuaShengHomeTabImgNextDirectory(getApplicationContext()));
LogUtils.d("HomeTabImageDownLoadInt", " Decompression complete ---");
}
In fact, the most important thing is how to create and obtain our file resources
It is important to switch between the two states of the resource (or is selected but not selected). Usually, we use drawable to write
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/home_tab_financing_selected" android:state_selected="true" />
<item android:drawable="@mipmap/home_tab_financing_normal" />
</selector>
Now we need to dynamically create drawable based on the downloaded images (stored in sdcard) so that we can have the mutual exclusion of system controls inside
The following three method codes are important
// Build Drawable Selector
private StateListDrawable createDrawableSelector(Drawable checked, Drawable unchecked) {
StateListDrawable stateList = new StateListDrawable();
int state_selected = android.R.attr.state_selected;
stateList.addState(new int[]{state_selected}, checked);
stateList.addState(new int[]{-state_selected}, unchecked);
return stateList;
}
// Build a color picker
private ColorStateList createColorSelector(int checkedColor, int uncheckedColor) {
return new ColorStateList(
new int[][]{new int[]{android.R.attr.state_selected},
new int[]{-android.R.attr.state_selected}},
new int[]{checkedColor, uncheckedColor});
// Convert a file to Drawable
// pathName It is the absolute path where pictures are stored
private Drawable getDrawableByFile(String pathName) {
return Drawable.createFromPath(pathName);
}
Finally, set up resources on tab of TabLayout
Take out all Tab of TabLayout, traverse, and then set the corresponding drawable according to specific conditions
Finally, at the end of this article, we attach the above compression related tool class
import com.blankj.utilcode.util.CloseUtils;
import com.blankj.utilcode.util.StringUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* <pre>
* author: Cheng Long
* time : 2018/12/14
* desc : Compression related tool classes
* </pre>
*/
public final class ZipUtils {
private static final int KB = 1024;
private ZipUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* Batch compressed files
*
* @param resFiles Collection of files to be compressed
* @param zipFilePath Compressed file path
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFiles(Collection<File> resFiles, String zipFilePath)
throws IOException {
return zipFiles(resFiles, zipFilePath, null);
}
/**
* Batch compressed files
*
* @param resFiles Collection of files to be compressed
* @param zipFilePath Compressed file path
* @param comment Comments on compressed files
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFiles(Collection<File> resFiles, String zipFilePath, String comment)
throws IOException {
return zipFiles(resFiles, FileUtils.getFileByPath(zipFilePath), comment);
}
/**
* Batch compressed files
*
* @param resFiles Collection of files to be compressed
* @param zipFile Zip file
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFiles(Collection<File> resFiles, File zipFile)
throws IOException {
return zipFiles(resFiles, zipFile, null);
}
/**
* Batch compressed files
*
* @param resFiles Collection of files to be compressed
* @param zipFile Zip file
* @param comment Comments on compressed files
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFiles(Collection<File> resFiles, File zipFile, String comment)
throws IOException {
if (resFiles == null || zipFile == null) return false;
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(new FileOutputStream(zipFile));
for (File resFile : resFiles) {
if (!zipFile(resFile, "", zos, comment)) return false;
}
return true;
} finally {
if (zos != null) {
zos.finish();
CloseUtils.closeIO(zos);
}
}
}
/**
* Zip file
*
* @param resFilePath Path of file to be compressed
* @param zipFilePath Compressed file path
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFile(String resFilePath, String zipFilePath)
throws IOException {
return zipFile(resFilePath, zipFilePath, null);
}
/**
* Zip file
*
* @param resFilePath Path of file to be compressed
* @param zipFilePath Compressed file path
* @param comment Comments on compressed files
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFile(String resFilePath, String zipFilePath, String comment)
throws IOException {
return zipFile(FileUtils.getFileByPath(resFilePath), FileUtils.getFileByPath(zipFilePath), comment);
}
/**
* Zip file
*
* @param resFile File to be compressed
* @param zipFile Zip file
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFile(File resFile, File zipFile)
throws IOException {
return zipFile(resFile, zipFile, null);
}
/**
* Zip file
*
* @param resFile File to be compressed
* @param zipFile Zip file
* @param comment Comments on compressed files
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean zipFile(File resFile, File zipFile, String comment)
throws IOException {
if (resFile == null || zipFile == null) return false;
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(new FileOutputStream(zipFile));
return zipFile(resFile, "", zos, comment);
} finally {
if (zos != null) {
CloseUtils.closeIO(zos);
}
}
}
/**
* Zip file
*
* @param resFile File to be compressed
* @param rootPath Path relative to compressed file
* @param zos Compressed file output stream
* @param comment Comments on compressed files
* @return {@code true}: Compression succeeded <br>{@code false}: Compression failed
* @throws IOException IO Thrown when an error occurs
*/
private static boolean zipFile(File resFile, String rootPath, ZipOutputStream zos, String comment)
throws IOException {
rootPath = rootPath + (isSpace(rootPath) ? "" : File.separator) + resFile.getName();
if (resFile.isDirectory()) {
File[] fileList = resFile.listFiles();
// If it is an empty folder, then create it, and I put '/' For File.separator The test is unsuccessful, eggPain
if (fileList == null || fileList.length <= 0) {
ZipEntry entry = new ZipEntry(rootPath + '/');
if (!StringUtils.isEmpty(comment)) entry.setComment(comment);
zos.putNextEntry(entry);
zos.closeEntry();
} else {
for (File file : fileList) {
// If the recursion returns false Returns the false
if (!zipFile(file, rootPath, zos, comment)) return false;
}
}
} else {
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(resFile));
ZipEntry entry = new ZipEntry(rootPath);
if (!StringUtils.isEmpty(comment)) entry.setComment(comment);
zos.putNextEntry(entry);
byte buffer[] = new byte[KB];
int len;
while ((len = is.read(buffer, 0, KB)) != -1) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
} finally {
CloseUtils.closeIO(is);
}
}
return true;
}
/**
* Batch unzip file
*
* @param zipFiles Compressed file collection
* @param destDirPath Destination directory path
* @return {@code true}: Successful decompression <br>{@code false}: Decompression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean unzipFiles(Collection<File> zipFiles, String destDirPath)
throws IOException {
return unzipFiles(zipFiles, FileUtils.getFileByPath(destDirPath));
}
/**
* Batch unzip file
*
* @param zipFiles Compressed file collection
* @param destDir Target directory
* @return {@code true}: Successful decompression <br>{@code false}: Decompression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean unzipFiles(Collection<File> zipFiles, File destDir)
throws IOException {
if (zipFiles == null || destDir == null) return false;
for (File zipFile : zipFiles) {
if (!unzipFile(zipFile, destDir)) return false;
}
return true;
}
/**
* Extract a file
*
* @param zipFilePath Path of file to be unzipped
* @param destDirPath Destination directory path
* @return {@code true}: Successful decompression <br>{@code false}: Decompression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean unzipFile(String zipFilePath, String destDirPath) throws IOException {
// Determine whether this path exists , If not, create this path
File tempDir = new File(destDirPath);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
return unzipFile(FileUtils.getFileByPath(zipFilePath), FileUtils.getFileByPath(destDirPath));
}
/**
* Extract a file
*
* @param zipFile File to be unzipped
* @param destDir Target directory
* @return {@code true}: Successful decompression <br>{@code false}: Decompression failed
* @throws IOException IO Thrown when an error occurs
*/
public static boolean unzipFile(File zipFile, File destDir)
throws IOException {
return unzipFileByKeyword(zipFile, destDir, null) != null;
}
/**
* Unzip a file with a keyword
*
* @param zipFilePath Path of file to be unzipped
* @param destDirPath Destination directory path
* @param keyword Keyword
* @return Returns a linked list of files with keywords
* @throws IOException IO Thrown when an error occurs
*/
public static List<File> unzipFileByKeyword(String zipFilePath, String destDirPath, String keyword)
throws IOException {
return unzipFileByKeyword(FileUtils.getFileByPath(zipFilePath),
FileUtils.getFileByPath(destDirPath), keyword);
}
/**
* Unzip a file with a keyword
*
* @param zipFile File to be unzipped
* @param destDir Target directory
* @param keyword Keyword
* @return Returns a linked list of files with keywords
* @throws IOException IO Thrown when an error occurs
*/
public static List<File> unzipFileByKeyword(File zipFile, File destDir, String keyword)
throws IOException {
if (zipFile == null || destDir == null) return null;
List<File> files = new ArrayList<>();
ZipFile zf = new ZipFile(zipFile);
Enumeration<?> entries = zf.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
if (StringUtils.isEmpty(keyword) || FileUtils.getFileName(entryName).toLowerCase().contains(keyword.toLowerCase())) {
String filePath = destDir + File.separator + entryName;
File file = new File(filePath);
files.add(file);
if (entry.isDirectory()) {
if (!FileUtils.createOrExistsDir(file)) return null;
} else {
if (!FileUtils.createOrExistsFile(file)) return null;
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(zf.getInputStream(entry));
out = new BufferedOutputStream(new FileOutputStream(file));
byte buffer[] = new byte[KB];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} finally {
CloseUtils.closeIO(in, out);
}
}
}
}
return files;
}
/**
* Gets a linked list of file paths in a compressed file
*
* @param zipFilePath Compressed file path
* @return Linked list of file paths in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static List<String> getFilesPath(String zipFilePath)
throws IOException {
return getFilesPath(FileUtils.getFileByPath(zipFilePath));
}
/**
* Gets a linked list of file paths in a compressed file
*
* @param zipFile Zip file
* @return Linked list of file paths in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static List<String> getFilesPath(File zipFile)
throws IOException {
if (zipFile == null) return null;
List<String> paths = new ArrayList<>();
Enumeration<?> entries = getEntries(zipFile);
while (entries.hasMoreElements()) {
paths.add(((ZipEntry) entries.nextElement()).getName());
}
return paths;
}
/**
* Get a linked list of comments in a compressed file
*
* @param zipFilePath Compressed file path
* @return Linked list of comments in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static List<String> getComments(String zipFilePath)
throws IOException {
return getComments(FileUtils.getFileByPath(zipFilePath));
}
/**
* Get a linked list of comments in a compressed file
*
* @param zipFile Zip file
* @return Linked list of comments in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static List<String> getComments(File zipFile)
throws IOException {
if (zipFile == null) return null;
List<String> comments = new ArrayList<>();
Enumeration<?> entries = getEntries(zipFile);
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
comments.add(entry.getComment());
}
return comments;
}
/**
* Get the file object in the zip file
*
* @param zipFilePath Compressed file path
* @return File objects in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static Enumeration<?> getEntries(String zipFilePath)
throws IOException {
return getEntries(FileUtils.getFileByPath(zipFilePath));
}
/**
* Get the file object in the zip file
*
* @param zipFile Zip file
* @return File objects in compressed files
* @throws IOException IO Thrown when an error occurs
*/
public static Enumeration<?> getEntries(File zipFile)
throws IOException {
if (zipFile == null) return null;
return new ZipFile(zipFile).entries();
}
private static boolean isSpace(String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i < len; ++i) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
}