动态cardviews与firebase结合使用

DeG*_*seZ 8 android firebase android-cardview firebase-realtime-database firebase-storage

我有一份清单CardViews.每个CardView(代表挑战)都有一个ViewPager显示"解决方案"的垂直可扫描列表.

"解决方案列表"中的数据和图像来自Firebase数据库. 我遇到的问题是您打开的第一个CardView(当您单击它时,它会展开并显示解决方案)会正确显示所有解决方案.当你点击第二个时,它会扩展但没有显示数据,我认为它是这样的,因为我必须使用"最终"布局(final FrameLayout v0 = (FrameLayout) inflater.inflate(R.layout.solutions, null);)

在此输入图像描述

以下是自定义RecyclerView适配器的重要部分的片段.

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());
                            }

                        });
                    }

                        ....

                });

                ....
            }
        });
    }
}
}
Run Code Online (Sandbox Code Playgroud)

这是challenge_row.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>
Run Code Online (Sandbox Code Playgroud)

这是solutions.xml:

<?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>
Run Code Online (Sandbox Code Playgroud)

根据马科斯的建议编辑:(仍然是相同的结果)

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(final RecyclerItemViewHolder holder, final int position) {
    holder.etTitleTextView.setText(myChallengesList.get(position).getTitle());
    holder.etDescriptionTextView.setText(myChallengesList.get(position).getDescription());
    mLastPosition =position;

    holder.mainLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(holder.itemView.getContext(), "Position:" + myChallengesList.get(holder.getAdapterPosition()).getDescription(), Toast.LENGTH_SHORT).show();
            //create reference to solutions inside challenges data
            challengeSolutionsRef = challengeSolutionsRef.child(myChallengesList.get(holder.getAdapterPosition()).getChallengeKey()).child("solutions");
            challengeSolutionsRef.addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {

                    DatabaseReference solutionsRef = rootRef.child("solutions").child(dataSnapshot.getKey());
                    solutionsRef.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            holder.v0 = (FrameLayout) holder.myInflater.inflate(R.layout.solutions, null);
                            TextView TVSolutionID = (TextView)holder.v0.findViewById(R.id.txtSolutionID);
                            TextView TVUserID = (TextView)holder.v0.findViewById(R.id.txtUserID);
                            TVSolutionID.setText(dataSnapshot.getKey());
                            String UserID = dataSnapshot.child("userId").getValue(String.class);
                            TVUserID.setText(UserID);

                            holder.myChallengesPagerAdapter.notifyDataSetChanged();

                            storageRef.child("Solutions/").child(dataSnapshot.child("picture").getValue("filename").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)holder.v0.findViewById(R.id.ivSolutionImage);
                                    IVSolution.setImageBitmap(bitmap);
                                    holder.myChallengesPagerAdapter.notifyDataSetChanged();
                                }
                            }).addOnFailureListener(new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception exception) {
                                    // Handle any errors
                                    //Create new item in the rowItems arraylist to add to the listview
                                    ImageView IVSolution = (ImageView)holder.v0.findViewById(R.id.ivSolutionImage);
                                    IVSolution.setImageResource(R.mipmap.ic_challenger_black);
                                    holder.myChallengesPagerAdapter.notifyDataSetChanged();
                                }
                            });
                            holder.myChallengesPagerAdapter.addView(holder.v0);
                            holder.myChallengesPagerAdapter.notifyDataSetChanged();
                        }
                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Log.d("Test","The read failed: " + databaseError.getCode());
                        }

                    });
                }
 ...

            });

    });

}
@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 TextView etTitleTextView;
    private TextView etDescriptionTextView;
    //private final TextView etContent;
    private ChallengesPagerAdapter myChallengesPagerAdapter;
    private ViewPager myViewPager;
    private FrameLayout myFrameLayout;
    private LinearLayout mainLayout;
    private View myParent;
    private LayoutInflater myInflater;
    private FrameLayout v0;
    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);
        myParent = parent;
        myInflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }
}
}
Run Code Online (Sandbox Code Playgroud)

DeG*_*seZ 0

Marcus 的解释对我来说并不是 100% 清楚,但它让我思考并让我更好地理解了 viewpager/adapter 链接。我删除了cardview pard,并使用了一个普通的列表视图,里面有一个viewpager。这是代码的简短版本(缺少某些部分!)。

在片段中,我列出了自定义数据类的列表。列表的每个部分代表 1 行。该列表将添加到自定义适配器(代码如下),并且此自定义适配器将添加到列表视图(mylistview)。

片段.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;
}
Run Code Online (Sandbox Code Playgroud)

xml中的列表视图:

    <ListView
    android:id="@+id/LVChallenges"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</ListView>
Run Code Online (Sandbox Code Playgroud)

解决方案适配器.xml

在构造函数中,获取上下文,以便我们可以在正确的位置进行膨胀并获取列表视图所需的项目。在 viewpager 中膨胀您想要的布局,并将值分配给布局。然后为 viewpager 项目创建列表 (myViewpagerlist),将视图 (convertview) 提供给自定义适配器 (vpadapter),以便它可以在正确的位置膨胀。创建一个新的 viewpager,向其中添加布局元素并向其中添加自定义适配器 (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) {

                }
            });
        }
    });
Run Code Online (Sandbox Code Playgroud)

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;
}

}
Run Code Online (Sandbox Code Playgroud)