[英]On Click function not behaving as expected; confused as to why? (Android Studio, RecyclerView)
好吧,我整个周末都在思考这个问题,我绕着圈子跑,把自己弄糊涂了; 所以有人请帮忙。 这是独家新闻:我有一个带有 RecyclerView 的应用程序来保存 CardView 项目。 这是布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scene_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="4dp"
app:cardBackgroundColor="#75757A">
<RelativeLayout
android:id="@+id/listItemWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp">
<TextView
android:id="@+id/assetSymbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="SYM"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold">
</TextView>
<TextView
android:id="@+id/assetPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_toEndOf="@+id/assetSymbol"
android:text="$1,000.00"
android:textColor="@android:color/white"
android:textSize="20sp"
android:textStyle="bold"
android:layout_toRightOf="@+id/assetSymbol">
</TextView>
<ImageView
android:id="@+id/imageView"
android:layout_width="30sp"
android:layout_height="30sp"
android:layout_margin="8dp"
android:layout_toEndOf="@+id/assetPrice"
android:padding="2dp"
android:layout_toRightOf="@+id/assetPrice">
</ImageView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/openShort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/assetPrice"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:backgroundTint="@color/bearRed"
android:clickable="true"
android:visibility="gone"
app:fabSize="mini"
app:srcCompat="@drawable/ic_bear_enter" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/openLong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/assetPrice"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toStartOf="@+id/openShort"
android:layout_toLeftOf="@+id/openShort"
android:backgroundTint="@color/bullGreen"
android:clickable="true"
android:visibility="gone"
app:fabSize="mini"
app:srcCompat="@drawable/ic_bull_enter" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/deleteAsset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/assetPrice"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toStartOf="@+id/openLong"
android:layout_toLeftOf="@+id/openLong"
android:backgroundTint="@color/colorPrimary"
android:clickable="true"
android:visibility="gone"
app:fabSize="mini"
app:srcCompat="@drawable/ic_delete_asset" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/editAsset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/assetPrice"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toStartOf="@+id/deleteAsset"
android:layout_toLeftOf="@+id/deleteAsset"
android:backgroundTint="@color/colorPrimary"
android:clickable="true"
android:visibility="gone"
app:fabSize="mini"
app:srcCompat="@drawable/ic_edit_asset" />
</RelativeLayout>
<ImageView
android:id="@+id/showOptions"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_gravity="end"
android:layout_margin="8dp"
app:srcCompat="@drawable/ic_baseline_more_vert" />
</androidx.cardview.widget.CardView>
您会注意到卡片包含四个浮动操作按钮,它们最初是隐藏的。 我想要做的是当用户单击“显示选项”ImageView(android:id="@+id/showOptions")时让按钮动画进入视图。 这是所有相关的代码片段:
主活动.java
public class MainActivity extends AppCompatActivity implements OnClickListener {
private ArrayList<WatchListItem> watchListArray;
private RecyclerView watchList;
private WatchListAdapter listAdapter;
private RecyclerView.LayoutManager listManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
watchListArray = new ArrayList<>();
watchList = (RecyclerView) findViewById(R.id.watchList);
watchList.setHasFixedSize(true);
listManager = new LinearLayoutManager(this);
watchList.setLayoutManager(listManager);
listAdapter = new WatchListAdapter(watchListArray);
watchList.setAdapter(listAdapter);
}
public void engage(Asset asset) {
int position = watchListArray.size();
String ticker = asset.getSymbol();
//Double.toString(asset.getCurrentPrice()) replaced with fixed value for testing
String price = "390.55";
//int indicator set to fixed value for testing
int indicator = R.drawable.ic_bull_indicator;
watchListArray.add(position, new WatchListItem(indicator, price, ticker));
listAdapter.notifyItemInserted(position);
listAdapter.setOnItemClickListener(new WatchListAdapter.OnItemClickListener() {
@Override
public void onShowOptionsClick(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort) {
expandListItem(position, show, edit, delete, oLong, oShort);
}
});
}
public void expandListItem(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort) {
if (edit.getVisibility() == View.GONE) {
show.setImageResource(R.drawable.ic_collapse);
oShort.animate().alpha(1f).setDuration(150);
oLong.animate().alpha(1f).setStartDelay(125).setDuration(150);
delete.animate().alpha(1f).setStartDelay(250).setDuration(150);
edit.animate().alpha(1f).setStartDelay(375).setDuration(150);
} else {
edit.animate().alpha(0f).setDuration(150);
delete.animate().alpha(0f).setStartDelay(125).setDuration(150);
oLong.animate().alpha(0f).setStartDelay(250).setDuration(150);
oShort.animate().alpha(0f).setStartDelay(375).setDuration(150);
show.setImageResource(R.drawable.ic_baseline_more_vert);
}
listAdapter.notifyItemChanged(position);
}
监视列表适配器.java
public class WatchListAdapter extends RecyclerView.Adapter<WatchListAdapter.WatchListViewHolder> {
private ArrayList<WatchListItem> mWatchList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onShowOptionsClick(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class WatchListViewHolder extends RecyclerView.ViewHolder {
public TextView mAssetSymbol;
public TextView mAssetPrice;
public ImageView mImageView;
public ImageView mShowOptions;
public FloatingActionButton mEditAsset;
public FloatingActionButton mDeleteAsset;
public FloatingActionButton mOpenLong;
public FloatingActionButton mOpenShort;
public WatchListViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mAssetSymbol = itemView.findViewById(R.id.assetSymbol);
mAssetPrice = itemView.findViewById(R.id.assetPrice);
mImageView = itemView.findViewById(R.id.imageView);
mShowOptions = itemView.findViewById(R.id.showOptions);
mEditAsset = itemView.findViewById(R.id.editAsset);
mDeleteAsset = itemView.findViewById(R.id.deleteAsset);
mOpenLong = itemView.findViewById(R.id.openLong);
mOpenShort = itemView.findViewById(R.id.openShort);
mShowOptions.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
int position = getAdapterPosition();
ImageView show = mShowOptions;
FloatingActionButton edit = mEditAsset;
FloatingActionButton delete = mDeleteAsset;
FloatingActionButton oLong = mOpenLong;
FloatingActionButton oShort = mOpenShort;
if (position != RecyclerView.NO_POSITION) {
listener.onShowOptionsClick(position, show, edit, delete, oLong, oShort);
}
}
}
});
}
}
public WatchListAdapter(ArrayList<WatchListItem> watchListArray) {
mWatchList = watchListArray;
}
@NonNull
@Override
public WatchListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new WatchListViewHolder(v, mListener);
}
@Override
public void onBindViewHolder(@NonNull WatchListViewHolder holder, int position) {
WatchListItem currentItem = mWatchList.get(position);
holder.mAssetSymbol.setText(currentItem.getAssetSymbol());
holder.mAssetPrice.setText(currentItem.getAssetPrice());
holder.mImageView.setImageResource(currentItem.getImageResource());
}
@Override
public int getItemCount() {
return mWatchList.size();
}
}
监视列表项.java
public class WatchListItem {
private int mImageResource;
private String mAssetPrice;
private String mAssetSymbol;
public WatchListItem(int imageResource, String assetPrice, String assetSymbol) {
mImageResource = imageResource;
mAssetPrice = assetPrice;
mAssetSymbol = assetSymbol;
}
public int getImageResource() {
return mImageResource;
}
public String getAssetPrice() {
return mAssetPrice;
}
public String getAssetSymbol() {
return mAssetSymbol;
}
}
关于在 MainActivity.java 中放置 listAdapter.setOnItemClickListener 的快速说明:最初它包含在 onCreate() 方法中,因为这是构建 RecyclerView 的地方,也是我试图遵循的教程中放置它的地方; 但我将它移到了engage() 方法,因为这是添加列表项的地方,我认为在该项甚至存在之前设置侦听器是没有意义的,对吗? 无论如何让我知道这是否不正确,正如我怀疑的那样,尽管这并没有改变测试中的行为所以问题是:应用程序打开得很好,将项目添加到 RecyclerView,但是当我单击下拉 ImageView 时,没有。 好吧,并非完全没有,我可以说它正在尝试做某事,但最终什么也没发生。 我能描述它的最好方法是 CardView 类型的“闪烁”和 ImageView 图标被短暂更改为新图标但立即变回,就是这样。 没有错误,没有崩溃; 只是没有执行指定的操作,我不知道为什么。 我不知道为什么他们不得不弃用 ListView,因为如果我不必从头开始构建 onClickListener 接口,这一切对我来说就不那么令人困惑了,但我离题了。 非常感谢您花时间阅读所有这些并提供宝贵的意见。
试试下面的代码,看看它是否有帮助。 我已经更改了两个文件中的一些代码。 您现在不会在每次添加项目时都创建一个新的侦听器,这可能会有所帮助。
主活动.java
public class MainActivity extends AppCompatActivity implements OnClickListener {
private ArrayList<WatchListItem> watchListArray;
private RecyclerView watchList;
private WatchListAdapter listAdapter;
private RecyclerView.LayoutManager listManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
watchListArray = new ArrayList<>();
watchList = (RecyclerView) findViewById(R.id.watchList);
watchList.setHasFixedSize(true);
listManager = new LinearLayoutManager(this);
watchList.setLayoutManager(listManager);
listAdapter = new WatchListAdapter(watchListArray);
listAdapter.setOnItemClickListener(new WatchListAdapter.OnItemClickListener() {
@Override
public void onShowOptionsClick(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort) {
expandListItem(position, show, edit, delete, oLong, oShort);
}
});
watchList.setAdapter(listAdapter);
}
public void engage(Asset asset) {
int position = watchListArray.size();
String ticker = asset.getSymbol();
//Double.toString(asset.getCurrentPrice()) replaced with fixed value for testing
String price = "390.55";
//int indicator set to fixed value for testing
int indicator = R.drawable.ic_bull_indicator;
watchListArray.add(position, new WatchListItem(indicator, price, ticker));
listAdapter.notifyItemInserted(position);
}
public void expandListItem(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort) {
if (edit.getVisibility() == View.GONE) {
show.setImageResource(R.drawable.ic_collapse);
oShort.animate().alpha(1f).setDuration(150);
oLong.animate().alpha(1f).setStartDelay(125).setDuration(150);
delete.animate().alpha(1f).setStartDelay(250).setDuration(150);
edit.animate().alpha(1f).setStartDelay(375).setDuration(150);
} else {
edit.animate().alpha(0f).setDuration(150);
delete.animate().alpha(0f).setStartDelay(125).setDuration(150);
oLong.animate().alpha(0f).setStartDelay(250).setDuration(150);
oShort.animate().alpha(0f).setStartDelay(375).setDuration(150);
show.setImageResource(R.drawable.ic_baseline_more_vert);
}
listAdapter.notifyItemChanged(position);
}
}
监视列表适配器.java
public class WatchListAdapter extends RecyclerView.Adapter<WatchListAdapter.WatchListViewHolder> {
private ArrayList<WatchListItem> mWatchList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onShowOptionsClick(int position, ImageView show, FloatingActionButton edit, FloatingActionButton delete, FloatingActionButton oLong, FloatingActionButton oShort);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class WatchListViewHolder extends RecyclerView.ViewHolder {
public TextView mAssetSymbol;
public TextView mAssetPrice;
public ImageView mImageView;
public ImageView mShowOptions;
public FloatingActionButton mEditAsset;
public FloatingActionButton mDeleteAsset;
public FloatingActionButton mOpenLong;
public FloatingActionButton mOpenShort;
public WatchListViewHolder(@NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mAssetSymbol = itemView.findViewById(R.id.assetSymbol);
mAssetPrice = itemView.findViewById(R.id.assetPrice);
mImageView = itemView.findViewById(R.id.imageView);
mShowOptions = itemView.findViewById(R.id.showOptions);
mEditAsset = itemView.findViewById(R.id.editAsset);
mDeleteAsset = itemView.findViewById(R.id.deleteAsset);
mOpenLong = itemView.findViewById(R.id.openLong);
mOpenShort = itemView.findViewById(R.id.openShort);
}
}
public WatchListAdapter(ArrayList<WatchListItem> watchListArray) {
mWatchList = watchListArray;
}
@NonNull
@Override
public WatchListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new WatchListViewHolder(v, mListener);
}
@Override
public void onBindViewHolder(@NonNull WatchListViewHolder holder, int position) {
WatchListItem currentItem = mWatchList.get(position);
holder.mAssetSymbol.setText(currentItem.getAssetSymbol());
holder.mAssetPrice.setText(currentItem.getAssetPrice());
holder.mImageView.setImageResource(currentItem.getImageResource());
holder.mShowOptions.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
ImageView show = holder.mShowOptions;
FloatingActionButton edit = holder.mEditAsset;
FloatingActionButton delete = holder.mDeleteAsset;
FloatingActionButton oLong = holder.mOpenLong;
FloatingActionButton oShort = holder.mOpenShort;
if (position != RecyclerView.NO_POSITION) {
listener.onShowOptionsClick(position, show, edit, delete, oLong, oShort);
}
}
}
});
}
@Override
public int getItemCount() {
return mWatchList.size();
}
}
解决了! 感谢所有花时间回答的人,尤其是 i_A_mok,他的建议最终导致了修复。 我拥有的代码已经足够了; 我只需要在为 alpha 属性设置动画之前将 setVisibilty(View.VISIBLE) 添加到每个 FAB。 出于某种原因,我相信通过从 alpha 0.0 过渡到 alpha 1.0 会自动使视图可见,但可惜事实并非如此:可见性和 alpha 是两个独立的属性,需要独立设置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.