Browse Source

首页增加ai声音列表显示

zk 1 year ago
parent
commit
98f9eccee1

+ 10 - 0
app/src/main/java/com/atmob/voiceai/data/api/bean/VoiceListBean.java

@@ -20,6 +20,16 @@ public class VoiceListBean {
 
     private boolean isAddIcon;
 
+    private int viewType;
+
+    public int getViewType() {
+        return viewType;
+    }
+
+    public void setViewType(int viewType) {
+        this.viewType = viewType;
+    }
+
     public void setAddIcon(boolean addIcon) {
         isAddIcon = addIcon;
     }

+ 15 - 23
app/src/main/java/com/atmob/voiceai/module/voiceai/VoiceAIFragment.java

@@ -39,7 +39,8 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
     }
 
     private void initObserver() {
-        voiceViewModel.getVoiceDetailList().observe(getViewLifecycleOwner(), list -> voiceAIListAdapter.submit(list));
+        voiceViewModel.getVoiceDetailList().observe(getViewLifecycleOwner(), list -> voiceAIListAdapter.submit(list)
+        );
         voiceViewModel.getVoiceTypeList().observe(getViewLifecycleOwner(), list -> {
             if (list == null || list.isEmpty()) {
                 return;
@@ -71,29 +72,20 @@ public class VoiceAIFragment extends BaseFragment<FragmentVoiceAiBinding> {
 
     private void initVoiceList() {
         voiceAIListAdapter = new VoiceAIListAdapter(getViewLifecycleOwner());
-        binding.ryVoiceModel.setAdapter(voiceAIListAdapter);
+        binding.ryVoiceView.setAdapter(voiceAIListAdapter);
         GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 4);
-        binding.ryVoiceModel.setLayoutManager(gridLayoutManager);
-        GridLayoutItemDecoration gridLayoutItemDecoration = new GridLayoutItemDecoration(4, 0.0222222222222222f, 0.0222222222222222f, true);
-        binding.vGenerate.post(() -> gridLayoutItemDecoration.setLastBottomGap(binding.vGenerate.getMeasuredHeight()));
-        binding.ryVoiceModel.addItemDecoration(gridLayoutItemDecoration);
-
-//        binding.ryVoiceModel.addItemDecoration(new RecyclerView.ItemDecoration() {
-//            @Override
-//            public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
-//                super.getItemOffsets(outRect, view, parent, state);
-//                int childAdapterPosition = parent.getChildAdapterPosition(view);
-//                if (childAdapterPosition == -1) {
-//                    outRect.bottom = 0;
-//                    return;
-//                }
-//                if (childAdapterPosition == voiceAIListAdapter.getItemCount() - 1) {
-//                    outRect.bottom = 300;
-//                } else {
-//                    outRect.bottom = 0;
-//                }
-//            }
-//        });
+        binding.ryVoiceView.setLayoutManager(gridLayoutManager);
+        GridLayoutItemDecoration gridLayoutItemDecoration = new GridLayoutItemDecoration(4, 0.0222222222222222f, 0.0222222222222222f, false);
+        binding.ryVoiceView.addItemDecoration(gridLayoutItemDecoration);
+        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
+            @Override
+            public int getSpanSize(int position) {
+                if (voiceAIListAdapter.getItemViewType(position) == VoiceAIListAdapter.TYPE_FOOT) {
+                    return 4;
+                }
+                return 1;
+            }
+        });
     }
 
     private void initTabLayout() {

+ 43 - 7
app/src/main/java/com/atmob/voiceai/module/voiceai/VoiceAIListAdapter.java

@@ -13,23 +13,29 @@ import androidx.recyclerview.widget.RecyclerView;
 import com.atmob.common.logging.AtmobLog;
 import com.atmob.voiceai.data.api.bean.VoiceListBean;
 import com.atmob.voiceai.databinding.ItemVoiceAiListBinding;
+import com.atmob.voiceai.databinding.ItemVoiceListFootBinding;
 
 import java.util.List;
 import java.util.Objects;
 
-public class VoiceAIListAdapter extends RecyclerView.Adapter<VoiceAIListAdapter.ViewHolder> {
+public class VoiceAIListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
 
     private final AsyncListDiffer<VoiceListBean> listDiffer;
 
     private final LifecycleOwner lifecycleOwner;
 
+    public static final int TYPE_FOOT = 3;
+
     public VoiceAIListAdapter(@NonNull LifecycleOwner lifecycleOwner) {
         this.lifecycleOwner = lifecycleOwner;
         this.listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<VoiceListBean>() {
             @Override
             public boolean areItemsTheSame(@NonNull VoiceListBean oldItem, @NonNull VoiceListBean newItem) {
-                if (oldItem.isAddIcon() == newItem.isAddIcon()) {
-                    return true;
+                if (oldItem.getViewType() != newItem.getViewType()) {
+                    return false;
+                }
+                if (oldItem.isAddIcon() != newItem.isAddIcon()) {
+                    return false;
                 }
                 return oldItem.getId() == newItem.getId();
             }
@@ -55,28 +61,58 @@ public class VoiceAIListAdapter extends RecyclerView.Adapter<VoiceAIListAdapter.
 
     @NonNull
     @Override
-    public VoiceAIListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         Context context = parent.getContext();
         LayoutInflater layoutInflater = LayoutInflater.from(context);
-        return new ViewHolder(ItemVoiceAiListBinding.inflate(layoutInflater));
+        if (viewType == TYPE_FOOT) {
+            return new ViewFootHolder(ItemVoiceListFootBinding.inflate(layoutInflater));
+        } else {
+            return new ViewHolder(ItemVoiceAiListBinding.inflate(layoutInflater));
+        }
     }
 
 
     @Override
-    public void onBindViewHolder(@NonNull VoiceAIListAdapter.ViewHolder holder, int position) {
-        holder.bind(listDiffer.getCurrentList().get(position));
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+        VoiceListBean voiceListBean = listDiffer.getCurrentList().get(position);
+        if (voiceListBean.getViewType() != TYPE_FOOT) {
+            ((ViewHolder) holder).bind(voiceListBean);
+        }
     }
 
     public void submit(List<VoiceListBean> itemBeanList) {
+        VoiceListBean voiceListBean = new VoiceListBean();
+        voiceListBean.setViewType(TYPE_FOOT);
+        itemBeanList.add(voiceListBean);
         listDiffer.submitList(itemBeanList);
     }
 
+    @Override
+    public int getItemViewType(int position) {
+        VoiceListBean voiceListBean = listDiffer.getCurrentList().get(position);
+        if (voiceListBean.getViewType() == TYPE_FOOT) {
+            return TYPE_FOOT;
+        }
+        return super.getItemViewType(position);
+    }
 
     @Override
     public int getItemCount() {
         return listDiffer.getCurrentList().size();
     }
 
+
+    public class ViewFootHolder extends RecyclerView.ViewHolder {
+
+        private final ItemVoiceListFootBinding binding;
+
+        public ViewFootHolder(@NonNull ItemVoiceListFootBinding binding) {
+            super(binding.getRoot());
+            this.binding = binding;
+        }
+
+    }
+
     public class ViewHolder extends RecyclerView.ViewHolder {
 
         private final ItemVoiceAiListBinding binding;

+ 1 - 13
app/src/main/java/com/atmob/voiceai/utils/GridLayoutItemDecoration.java

@@ -17,25 +17,19 @@ public class GridLayoutItemDecoration extends RecyclerView.ItemDecoration {
 
     private boolean showLastVertical = true;
 
-    private int lastBottomGap;
-
 
     public GridLayoutItemDecoration(int spanCount, float horizontalGapPercent, float verticalGapPercent) {
         this(spanCount, horizontalGapPercent, verticalGapPercent, true);
     }
 
     public GridLayoutItemDecoration(int spanCount, float horizontalGapPercent, float verticalGapPercent, boolean showLastVertical) {
-        this(spanCount, horizontalGapPercent, verticalGapPercent, showLastVertical, 0);
-    }
-
-    public GridLayoutItemDecoration(int spanCount, float horizontalGapPercent, float verticalGapPercent, boolean showLastVertical, int lastBottomGap) {
         this.spanCount = spanCount;
         this.horizontalGapPercent = horizontalGapPercent;
         this.verticalGapPercent = verticalGapPercent;
         this.showLastVertical = showLastVertical;
-        this.lastBottomGap = lastBottomGap;
     }
 
+
     @Override
     public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
         super.getItemOffsets(outRect, view, parent, state);
@@ -50,8 +44,6 @@ public class GridLayoutItemDecoration extends RecyclerView.ItemDecoration {
         boolean isScope = parent.getAdapter() != null && parent.getAdapter().getItemCount() - spanSize <= childAdapterPosition;
         if (!showLastVertical && isScope) {
             outRect.bottom = 0;
-        } else if (lastBottomGap > 0 && isScope) {
-            outRect.bottom = lastBottomGap;
         } else {
             outRect.bottom = verticalGap;
         }
@@ -65,10 +57,6 @@ public class GridLayoutItemDecoration extends RecyclerView.ItemDecoration {
             outRect.left = singleGap / 2;
             outRect.right = singleGap / 2;
         }
-        AtmobLog.d("TAG", view.toString() + " getItemOffsets: " + outRect.bottom + " childAdapterPosition:" + childAdapterPosition);
     }
 
-    public void setLastBottomGap(int lastBottomGap) {
-        this.lastBottomGap = lastBottomGap;
-    }
 }

BIN
app/src/main/res/drawable-xxhdpi/icon_voice_vip_use.webp


+ 7 - 0
app/src/main/res/drawable/bg_voice_new.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners
+        android:bottomLeftRadius="7dp"
+        android:topRightRadius="7dp" />
+    <solid android:color="#FF5656" />
+</shape>

+ 3 - 4
app/src/main/res/layout/fragment_voice_ai.xml

@@ -307,7 +307,7 @@
             android:layout_weight="1">
 
             <androidx.recyclerview.widget.RecyclerView
-                android:id="@+id/ry_voice_model"
+                android:id="@+id/ry_voice_view"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_marginTop="16dp"
@@ -328,10 +328,9 @@
                 <View
                     android:id="@+id/v_generate"
                     android:layout_width="match_parent"
-                    android:layout_height="0dp"
+                    android:layout_height="76dp"
                     android:background="@drawable/bg_voice_generate"
-                    app:layout_constraintBottom_toBottomOf="parent"
-                    app:layout_constraintDimensionRatio="360:76" />
+                    app:layout_constraintBottom_toBottomOf="parent" />
 
                 <View
                     android:id="@+id/v_generate_btn"

+ 27 - 0
app/src/main/res/layout/item_voice_ai_list.xml

@@ -33,6 +33,7 @@
         <ImageView
             imageUrl="@{bean.avatarUrl}"
             isGone="@{bean.isAddIcon}"
+            radius="@{12}"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:src="@drawable/icon_voice_ai_add"
@@ -40,6 +41,32 @@
             app:layout_constraintTop_toTopOf="parent" />
 
         <TextView
+            isGone="@{!bean.hasNew}"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:background="@drawable/bg_voice_new"
+            android:gravity="center"
+            android:lines="1"
+            android:text="@string/voice_new"
+            android:textColor="@color/white"
+            android:textSize="10dp"
+            app:layout_constraintDimensionRatio="29:15"
+            app:layout_constraintEnd_toEndOf="@+id/space_content"
+            app:layout_constraintTop_toTopOf="@id/space_content"
+            app:layout_constraintWidth_percent="0.3717948717948718" />
+
+        <ImageView
+            isGone="@{!bean.hasPro}"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_margin="4dp"
+            android:src="@drawable/icon_voice_vip_use"
+            app:layout_constraintBottom_toBottomOf="@+id/space_content"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintEnd_toEndOf="@+id/space_content"
+            app:layout_constraintWidth_percent="0.2564102564102564" />
+
+        <TextView
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_marginTop="4dp"

+ 11 - 0
app/src/main/res/layout/item_voice_list_foot.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="76dp"
+        app:layout_constraintTop_toTopOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -14,4 +14,5 @@
     <string name="voice_ai_get_free_number">You have %d chances today.</string>
     <string name="net_error_message">network timeout</string>
     <string name="add_voice">Add Voice</string>
+    <string name="voice_new">New</string>
 </resources>