我有 SparkConf configuration = new SparkConf()
.setAppName("Your Application Name")
.setMaster("local");
val sc = new SparkContext(conf);
的列表。每个CardViews
(代表挑战)都有CardView
来显示""解决方案"的垂直可扫描列表。
"解决方案列表中的数据和图像"来自ViewPager
数据库。
我遇到的问题是您打开的第一个CardView (当您点击它时,它会展开并显示解决方案)正确显示所有解决方案。当你点击第二个时,它会扩展,但没有显示数据,我认为它是这样的,因为我必须使用" final"布局(Firebase
)
以下是自定义final FrameLayout v0 = (FrameLayout) inflater.inflate(R.layout.solutions, null);
适配器的重要部分的片段。
RecyclerView
这是challenge_row.xml:
public class ChallengesAdapter extends
RecyclerView.Adapter<ChallengesAdapter.RecyclerItemViewHolder> {
private ArrayList<ChallengesData> myChallengesList;
int mLastPosition = 0;
//Firebase
String mUID = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference challengeSolutionsRef = rootRef.child("challenges");
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl("firebase-url");
public ChallengesAdapter(ArrayList<ChallengesData> myChallengesList) {
this.myChallengesList = myChallengesList;
}
public RecyclerItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.challenges_row, parent, false);
RecyclerItemViewHolder holder = new RecyclerItemViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(RecyclerItemViewHolder holder, final int position) {
holder.etTitleTextView.setText(myChallengesList.get(position).getTitle());
holder.etDescriptionTextView.setText(myChallengesList.get(position).getDescription());
mLastPosition =position;
}
@Override
public int getItemCount() {
return(null != myChallengesList ? myChallengesList.size():0);
}
public void notifyData(ArrayList<ChallengesData> myList) {
this.myChallengesList = myList;
notifyDataSetChanged();
}
public class RecyclerItemViewHolder extends RecyclerView.ViewHolder {
private final TextView etTitleTextView;
private final TextView etDescriptionTextView;
//private final TextView etContent;
private final ChallengesPagerAdapter myChallengesPagerAdapter;
private final ViewPager myViewPager;
private final FrameLayout myFrameLayout;
private LinearLayout mainLayout;
public RecyclerItemViewHolder(final View parent) {
super(parent);
etTitleTextView = (TextView) parent.findViewById(R.id.txtTitle);
etDescriptionTextView = (TextView) parent.findViewById(R.id.txtDescription);
myViewPager = (ViewPager) parent.findViewById(R.id.view_pager);
myChallengesPagerAdapter = new ChallengesPagerAdapter();
myViewPager.setAdapter(myChallengesPagerAdapter);
myFrameLayout = (FrameLayout) parent.findViewById(R.id.framelayout_view_pager);
mainLayout = (LinearLayout) parent.findViewById(R.id.mainLayout);
mainLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
challengeSolutionsRef = challengeSolutionsRef.child(myChallengesList.get(getAdapterPosition()).getChallengeKey()).child("solutions");
challengeSolutionsRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
final LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DatabaseReference solutionsRef = rootRef.child("solutions").child(dataSnapshot.getKey());
solutionsRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
final FrameLayout v0 = (FrameLayout) inflater.inflate(R.layout.solutions, null);
TextView TVSolutionID = (TextView)v0.findViewById(R.id.txtSolutionID);
TextView TVUserID = (TextView)v0.findViewById(R.id.txtUserID);
TVSolutionID.setText(dataSnapshot.getKey());
String UserID = dataSnapshot.child("userId").getValue(String.class);
TVUserID.setText(UserID);
myChallengesPagerAdapter.notifyDataSetChanged();
//get file from cloud
storageRef.child("solutions/").child(dataSnapshot.child("images").getValue(String.class) + ".jpg").getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
@Override
public void onSuccess(byte[] bytes) {
// Use the bytes to display the image
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
ImageView IVSolution = (ImageView)v0.findViewById(R.id.ivSolutionImage);
IVSolution.setImageBitmap(bitmap);
myChallengesPagerAdapter.notifyDataSetChanged();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
ImageView IVSolution = (ImageView)v0.findViewById(R.id.ivSolutionImage);
IVSolution.setImageResource(R.mipmap.ic_challenger_black);
myChallengesPagerAdapter.notifyDataSetChanged();
}
});
myChallengesPagerAdapter.addView(v0);
myChallengesPagerAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Test","The read failed: " + databaseError.getCode());
}
});
}
....
});
....
}
});
}
}
}
这是solutions.xml:
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_margin="8dp"
android:id="@+id/card_view"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtTitle"
android:padding="12dp"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txtDescription"
android:padding="12dp"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/framelayout_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="300dp">
</android.support.v4.view.ViewPager>
<ImageButton
android:id="@+id/arrow_back"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical|left"
android:src="@drawable/ic_arrow_back" />
<ImageButton
android:id="@+id/arrow_forward"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical|right"
android:src="@drawable/ic_arrow_forward" />
</FrameLayout>
</LinearLayout>
根据马科斯的建议进行编辑:(结果仍然相同)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtSolutionID"
android:padding="12dp"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/txtUserID"
android:padding="12dp"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/ivSolutionImage"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>
答案 0 :(得分:0)
现在您已按照解决方案进行操作,您需要解决此问题:
holder.v0 = (FrameLayout) holder.myInflater.inflate(R.layout.solutions, null);
此语句创建的视图未附加到ViewHolder,结果将为空。
在ViewHolder构造函数中获取viewholder中的viewpager(不是主视图)的引用,并为其分配一个solutionsAdapter。
SolutionsAdapter将保存一个对象列表,您将在我指出的那一行的位置进行修改。
解决方案适配器将在创建视图上提供holder.myInflater.inflate(R.layout.solutions,null,false)的实例,并在onBindViewHolder中设置值。
要点:
您的屏幕上有一个带有一个适配器的RecyclerView,它返回一个具有ViewPager的视图(挑战); 项目视图(挑战)需要一个适配器到它可以修改的ViewPager(解决方案)。
答案 1 :(得分:0)
对Marcus的解释并非100%清楚,但它让我思考并让我更好地理解了viewpager / adapter链接。我删除了cardview pard,我是一个普通的listview,里面有一个viewpager。这是代码的简短版本(缺少某些部分!)。
在片段中,我制作了一个自定义数据类的列表。列表的每个部分代表1行。该列表将添加到自定义适配器(代码如下),此自定义适配器将添加到列表视图(mylistview)。
<强> Fragment.java 强>
List<ChallengesData> rowItems;
ListView mylistview;
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_challenges_overview, container, false);
rowItems = new ArrayList<ChallengesData>();
final SolutionsAdapter adapter = new SolutionsAdapter(getContext(), rowItems);
mylistview = (ListView) rootView.findViewById(R.id.LVChallenges);
mylistview.setAdapter(adapter);
mylistview.setOnItemClickListener(this);
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
final String challengeKey = dataSnapshot.getKey();
DatabaseReference groupKeyRef = rootRef.child(....).child(challengeKey);
groupKeyRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String description = dataSnapshot.child("description").getValue(String.class);
String title = dataSnapshot.child("title").getValue(String.class);
ChallengesData data = new ChallengesData(title,description,challengeKey);
int dataIndex = findDataitem(rowItems,challengeKey);
if(dataIndex == -1){
//group not yet added so add group
rowItems.add(data);
}
else{
rowItems.set(dataIndex,data);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
}
"here were other @override functions"
};
userChallengeRef.addChildEventListener(childEventListener);
return rootView;
}
xml中的listview:
<ListView
android:id="@+id/LVChallenges"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<强> SolutionsAdapter.xml 强>
在构造函数中,获取上下文,以便我们可以在正确的位置充气并获取listview所需的项目。在viewpager中扩展所需的布局,将值分配给布局。然后为viewpager项目(myViewpagerlist)创建列表,将视图(convertview)提供给自定义适配器(vpadapter),以便它可以在正确的位置上充气。创建一个新的viewpager,向其添加layout元素并向其添加自定义适配器(vpadapter)。填写viewpager(myviewpagerlist)的列表并调用notifyDataSetChanged()函数。
Context context;
List<ChallengesData> rowItems;
LayoutInflater mInflater;
SolutionsAdapter(Context context, List<ChallengesData> rowItems) {
this.context = context;
this.rowItems = rowItems;
mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
/* private view holder class */
private class ViewHolder {
TextView title;
TextView description;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
ChallengesData row_pos = rowItems.get(position);
//LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row, null);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.txtTitle);
holder.description = (TextView) convertView.findViewById(R.id.txtDescription);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(row_pos.getTitle());
holder.description.setText(row_pos.getDescription());
//List inside viewpager
final ArrayList<SolutionsData> myViewPagerList = new ArrayList<SolutionsData>();
final VPadapter myVPadapter = new VPadapter(convertView.getContext(),myViewPagerList);
final ViewPager myViewPager;
myViewPager = (ViewPager) convertView.findViewById(R.id.view_pager);
myViewPager.setAdapter(myVPadapter);
DatabaseReference challengeSolRef = rootRef.child("....");
challengeSolRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
DatabaseReference SolutionRef = rootRef.child("...");
SolutionRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
final String solutionsKey = dataSnapshot.getKey();
final String userID = dataSnapshot.child("userId").getValue(String.class);
final String description = dataSnapshot.child("description").getValue(String.class);
//get file from cloud
storageRef.child("....").getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
@Override
public void onSuccess(byte[] bytes) {
// Use the bytes to display the image
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
SolutionsData solData = new SolutionsData(solutionsKey,userID,description,bytes);
int rowItemIndex = findSolutionIitem(myViewPagerList,solutionsKey);
if(rowItemIndex == -1){
//group not yet added so add group
myViewPagerList.add(solData);
}
else{
myViewPagerList.set(rowItemIndex,solData);
}
myVPadapter.notifyDataSetChanged();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) { // Handle any errors
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
<强> VPAdapter.java 强> 创建一个新视图,为其分配正确的数据并完成。
class VPadapter extends PagerAdapter{
// This holds all the currently displayable views, in order from left to right.
private ArrayList<SolutionsData> views;
Context context;
LayoutInflater mInflater;
VPadapter(Context context, ArrayList<SolutionsData> myViewPagerList) {
this.context = context;
this.views = myViewPagerList;
mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
//-----------------------------------------------------------------------------
// Used by ViewPager. "Object" represents the page; tell the ViewPager where the
// page should be displayed, from left-to-right. If the page no longer exists,
// return POSITION_NONE.
@Override
public int getItemPosition (Object object)
{
int index = views.indexOf (object);
if (index == -1)
return POSITION_NONE;
else
return index;
}
//-----------------------------------------------------------------------------
// Used by ViewPager. Called when ViewPager needs a page to display; it is our job
// to add the page to the container, which is normally the ViewPager itself. Since
// all our pages are persistent, we simply retrieve it from our "views" ArrayList.
@Override
public Object instantiateItem (ViewGroup container, int position)
{
SolutionsData row_pos = views.get(position);
View v = mInflater.inflate(R.layout.solutions,null);
TextView SIDview = (TextView) v.findViewById(R.id.txtSolutionID);
SIDview.setText(row_pos.getSolutionKey());
Image.setImageBitmap(row_pos.getSolutionImageBitmap());
container.addView (v);
return v;
}
//-----------------------------------------------------------------------------
// Used by ViewPager. Called when ViewPager no longer needs a page to display; it
// is our job to remove the page from the container, which is normally the
// ViewPager itself. Since all our pages are persistent, we do nothing to the
// contents of our "views" ArrayList.
@Override
public void destroyItem (ViewGroup container, int position, Object object)
{
container.removeView ((View) object);
}
//-----------------------------------------------------------------------------
// Used by ViewPager; can be used by app as well.
// Returns the total number of pages that the ViewPage can display. This must
// never be 0.
@Override
public int getCount ()
{
return views.size();
}
//-----------------------------------------------------------------------------
// Used by ViewPager.
@Override
public boolean isViewFromObject (View view, Object object)
{
return view == object;
}
}