Skip to content

Commit

Permalink
refactor: make SimpleAdapter faster
Browse files Browse the repository at this point in the history
Add multiple views to a horizontal `LinearLayout` and make it
as a view for one item in `RecyclerView`, so that total number
of items in `RecyclerView` can be reduced and scrolling can
be faster.

Refs #940
  • Loading branch information
goofyz committed Jan 16, 2024
1 parent b7e5413 commit 78b519f
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 46 deletions.
44 changes: 30 additions & 14 deletions app/src/main/java/com/osfans/trime/ime/symbol/LiquidKeyboard.kt
Expand Up @@ -5,12 +5,15 @@ import android.content.Context
import android.content.Intent
import androidx.core.view.setPadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.blankj.utilcode.util.ScreenUtils
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import com.osfans.trime.R
import com.osfans.trime.core.CandidateListItem
import com.osfans.trime.core.Rime
import com.osfans.trime.data.SymbolHistory
Expand Down Expand Up @@ -99,22 +102,31 @@ class LiquidKeyboard(private val context: Context) : ClipboardHelper.OnClipboard
private fun initFixData(i: Int) {
val tabTag = TabManager.getTag(i)

val itemWidth = context.resources.getDimensionPixelSize(R.dimen.simple_item_size)
val itemMargin = context.resources.getDimensionPixelSize(R.dimen.simple_key_margin_x)
val columnCount = ScreenUtils.getScreenWidth() / (itemWidth + itemMargin)
val simpleAdapter =
SimpleAdapter(theme).apply {
SimpleAdapter(theme, columnCount).apply {
// 列表适配器的点击监听事件
setListener { position ->
val bean = beans[position]
if (tabTag.type === SymbolKeyboardType.SYMBOL) {
service.inputSymbol(bean.text)
} else if (tabTag.type !== SymbolKeyboardType.TABS) {
service.commitText(bean.text)
if (tabTag.type !== SymbolKeyboardType.HISTORY) {
symbolHistory.insert(bean.text)
symbolHistory.save()
if (position < beans.size) {
val bean = beans[position]
if (tabTag.type === SymbolKeyboardType.SYMBOL) {
service.inputSymbol(bean.text)
return@setListener
} else if (tabTag.type !== SymbolKeyboardType.TABS) {
service.commitText(bean.text)
if (tabTag.type !== SymbolKeyboardType.HISTORY) {
symbolHistory.insert(bean.text)
symbolHistory.save()
}
return@setListener
}
} else {
val tag = TabManager.get().getTabSwitchTabTag(position)
val truePosition = TabManager.get().getTabSwitchPosition(position)
}

val tag = TabManager.get().getTabSwitchTabTag(position)
val truePosition = TabManager.get().getTabSwitchPosition(position)
if (tag != null) {
Timber.v(
"TABS click: " +
"position = $position, truePosition = $truePosition, tag.text = ${tag.text}",
Expand All @@ -135,8 +147,12 @@ class LiquidKeyboard(private val context: Context) : ClipboardHelper.OnClipboard
}
}
keyboardView.apply {
layoutManager = getFlexbox()
adapter = simpleAdapter
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
adapter =
simpleAdapter.apply {
setHasStableIds(true)
setHasFixedSize(true)
}
// 添加分割线
// 设置添加删除动画
// 调用ListView的setSelected(!ListView.isSelected())方法,这样就能及时刷新布局
Expand Down
120 changes: 90 additions & 30 deletions app/src/main/java/com/osfans/trime/ime/symbol/SimpleAdapter.java
Expand Up @@ -8,77 +8,137 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.osfans.trime.R;
import com.osfans.trime.data.theme.FontManager;
import com.osfans.trime.data.theme.Theme;
import com.osfans.trime.databinding.SimpleKeyItemBinding;
import com.osfans.trime.databinding.SimpleItemOneBinding;
import com.osfans.trime.databinding.SimpleItemRowBinding;
import java.util.ArrayList;
import java.util.List;

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {
private final @NonNull List<SimpleKeyBean> mBeans = new ArrayList<>();
private final @NonNull List<List<SimpleKeyBean>> mBeansByRows = new ArrayList<>();

@NonNull
public final List<SimpleKeyBean> getBeans() {
return mBeans;
}

private final Theme theme;
private final int columnSize;

public SimpleAdapter(@NonNull Theme theme) {
public SimpleAdapter(@NonNull Theme theme, int columnSize) {
this.theme = theme;
this.columnSize = columnSize;
}

public void updateBeans(List<SimpleKeyBean> beans) {
mBeans.clear();
mBeans.addAll(beans);
mBeansByRows.clear();

ArrayList<SimpleKeyBean> t = new ArrayList<>();
for (int i = 0; i < mBeans.size(); i++) {
t.add(mBeans.get(i));
if ((i + 1) % columnSize == 0) {
mBeansByRows.add(t);
t = new ArrayList<>();
}
}
if (!t.isEmpty()) {
mBeansByRows.add(t);
}
}

@Override
public int getItemCount() {
return mBeans.size();
return mBeansByRows.size();
}

@Override
public long getItemId(int position) {
return position * 1000L;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final SimpleKeyItemBinding binding =
SimpleKeyItemBinding.inflate(LayoutInflater.from(parent.getContext()));
binding.simpleKeyPin.setVisibility(View.INVISIBLE);
return new ViewHolder(binding);
final SimpleItemRowBinding binding =
SimpleItemRowBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
int size = parent.getResources().getDimensionPixelSize(R.dimen.simple_item_size);
ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(size, size);

List<SimpleItemOneBinding> bindings = new ArrayList<>();
for (int i = 0; i < columnSize; i++) {
SimpleItemOneBinding view =
SimpleItemOneBinding.inflate(LayoutInflater.from(parent.getContext()), null, false);
bindings.add(view);
binding.wrapper.addView(view.getRoot(), p);
}
ViewHolder holder = new ViewHolder(binding, bindings);

for (int i = 0; i < holder.simpleKeyTexts.size(); i++) {
holder.wrappers.get(i).setTag((Integer) i);

TextView textView = holder.simpleKeyTexts.get(i);

textView.setTextColor(theme.colors.getColor("key_text_color"));
textView.setTypeface(FontManager.getTypeface(theme.style.getString("key_font")));
textView.setGravity(Gravity.CENTER);
textView.setEllipsize(TextUtils.TruncateAt.MARQUEE);

final float labelTextSize = theme.style.getFloat("label_text_size");
if (labelTextSize > 0) textView.setTextSize(labelTextSize);

textView.setBackground(
theme.colors.getDrawable(
"key_back_color", "key_border", "key_border_color", "round_corner", null));
}
return holder;
}

public static class ViewHolder extends RecyclerView.ViewHolder {
final TextView simpleKeyText;
List<TextView> simpleKeyTexts;
List<ViewGroup> wrappers;

public ViewHolder(@NonNull SimpleKeyItemBinding binding) {
public ViewHolder(@NonNull SimpleItemRowBinding binding, List<SimpleItemOneBinding> views) {
super(binding.getRoot());

simpleKeyText = binding.simpleKey;
simpleKeyTexts = new ArrayList<>();
wrappers = new ArrayList<>();
for (int i = 0; i < views.size(); i++) {
simpleKeyTexts.add((TextView) (views.get(i).getRoot().getChildAt(0)));
((ViewGroup) views.get(i).getRoot()).getChildAt(1).setVisibility(View.GONE);
wrappers.add(views.get(i).getRoot());
}
}
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
final SimpleKeyBean bean = mBeans.get(position);

holder.simpleKeyText.setText(bean.getLabel());
holder.simpleKeyText.setTextColor(theme.colors.getColor("key_text_color"));
holder.simpleKeyText.setTypeface(FontManager.getTypeface(theme.style.getString("key_font")));
holder.simpleKeyText.setGravity(Gravity.CENTER);
holder.simpleKeyText.setEllipsize(TextUtils.TruncateAt.MARQUEE);

final float labelTextSize = theme.style.getFloat("label_text_size");
if (labelTextSize > 0) holder.simpleKeyText.setTextSize(labelTextSize);

holder.itemView.setBackground(
theme.colors.getDrawable(
"key_back_color", "key_border", "key_border_color", "round_corner", null));

if (listener != null) {
holder.itemView.setOnClickListener(
view -> {
listener.onSimpleKeyClick(position);
});
final List<SimpleKeyBean> bean = mBeansByRows.get(position);

for (int i = 0; i < holder.simpleKeyTexts.size(); i++) {
holder.simpleKeyTexts.get(i).setText("");
if (i < bean.size()) {
holder.wrappers.get(i).setVisibility(View.VISIBLE);
holder.simpleKeyTexts.get(i).setText(bean.get(i).getLabel());
} else {
holder.wrappers.get(i).setVisibility(View.INVISIBLE);
}

if (listener != null) {
holder
.wrappers
.get(i)
.setOnClickListener(
view -> {
if (view.getTag() != null) {
listener.onSimpleKeyClick(position * columnSize + (int) view.getTag());
}
});
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions app/src/main/res/layout/simple_item_one.xml
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
>

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ellipsize="end"
android:maxLines="4"
android:padding="4dp"
android:textColor="#333333"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>

<ImageView
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="end"
android:layout_marginEnd="2dp"
android:layout_marginBottom="2dp"
android:alpha="0.4"
android:contentDescription="simple_key_pin"
android:src="@drawable/ic_baseline_push_pin_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>

</FrameLayout>

11 changes: 11 additions & 0 deletions app/src/main/res/layout/simple_item_row.xml
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>


<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:justifyContent="space_between"

/>
4 changes: 2 additions & 2 deletions app/src/main/res/values/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="simple_key_margin_x">2dp</dimen>
<dimen name="simple_key_single_width">50dp</dimen>
<dimen name="simple_key_margin_x">4dp</dimen>
<dimen name="simple_item_size">44dp</dimen>
</resources>

0 comments on commit 78b519f

Please sign in to comment.