Как программно добавить CardView к LinearLayout в RecyclerView - PullRequest
0 голосов
/ 14 октября 2018

Можно ли программно добавить CardView к LinearLayout внутри RecyclerView.В настоящее время все CardView добавлены к RecyclerView, но я хочу, чтобы те, что на скриншоте, были добавлены к LinearLayout.

класс фрагмента

public class TabFragmentRV extends android.support.v4.app.Fragment {
    RecyclerView mRecyclerView;

    public TabFragmentRV() {}

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_rv, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        View v = getView();
        assert v != null;

        mRecyclerView = v.findViewById(R.id.my_recyclerview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));

        super.onActivityCreated(savedInstanceState);

        initRVAdapter();
    }

    private void initRVAdapter(){
        List<Object> itemsList = new ArrayList<>();

        RVItemsAapter itemsListAdapter = new RVItemsAapter(getContext());
        mRecyclerView.setAdapter(itemsListAdapter);

        itemsList.add(new RVLineSeparator());
        itemsList.add(new SectionHeader("Section E"));
        itemsList.add(new SMSmessage("Item E1","Item E1 description"));
        itemsList.add(new SMSmessage("Item E2","Item E2 description"));
        itemsList.add(new SMSmessage("Item E3","Item E3 description"));
        itemsList.add(new SMSmessage("Item E4","Item E4 description"));
        itemsList.add(new RVLineSeparator());

        itemsListAdapter.setCallSMSFeed(itemsList);
        itemsListAdapter.notifyDataSetChanged();
    }
}

класс адаптера

public class RVItemsAapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private final static int TYPE_MAINHEADER = 1, TYPE_EXPANDABLE = 2, TYPE_NONEXPANDABLE = 3, TYPE_SECTIONHEADER = 4, TYPE_TABLE = 5, TYPE_SEPARATOR = 6;
    private ArrayList callSMSFeed = new ArrayList();

    private Context context;


    public RVItemsAapter(Context context){this.context=context;}

    public void setCallSMSFeed(List<Object> callSMSFeed){
        this.callSMSFeed = (ArrayList) callSMSFeed;
    }

    @Override
    public int getItemViewType(int position) {
        if (callSMSFeed.get(position) instanceof MainHeader) {
            return TYPE_MAINHEADER;
        } else if (callSMSFeed.get(position) instanceof Phonecall) {
            return TYPE_EXPANDABLE;
        } else if (callSMSFeed.get(position) instanceof SMSmessage) {
            return TYPE_NONEXPANDABLE;
        } else if (callSMSFeed.get(position) instanceof SectionHeader) {
            return TYPE_SECTIONHEADER;
        } else if (callSMSFeed.get(position) instanceof MyTable) {
            return TYPE_TABLE;
        } else if (callSMSFeed.get(position) instanceof RVLineSeparator) {
            return TYPE_SEPARATOR;
        }
        throw new IllegalArgumentException("Item at position " + position + " is not an instance of either Phonecall or SMSmessage");
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        int viewType=holder.getItemViewType();
        switch (viewType){
            case TYPE_MAINHEADER:
                MainHeader mainHeader = (MainHeader) callSMSFeed.get(position);
                ((MHeaderViewHolder)holder).showMHeaderDetails(mainHeader);
                break;
            case TYPE_EXPANDABLE:
                Phonecall call = (Phonecall) callSMSFeed.get(position);
                ((CallViewHolder)holder).showCallDetails(call);
                break;
            case TYPE_NONEXPANDABLE:
                SMSmessage sms = (SMSmessage) callSMSFeed.get(position);
                ((SMSViewHolder)holder).showSmsDetails(sms);
                break;
            case TYPE_SECTIONHEADER:
                SectionHeader sectionHeader = (SectionHeader) callSMSFeed.get(position);
                ((SectionViewHolder)holder).showSectionDetails(sectionHeader);
                break;
            case TYPE_TABLE:
                TableToilets tblToilets = (TableToilets) callSMSFeed.get(position);
                ((TblViewHolder)holder).showTblDetails(tblToilets);
                break;
            case TYPE_SEPARATOR:
                ((SeparatorViewHolder)holder).showSeparatorDetails();
                break;
            default:
                throw new IllegalArgumentException("unexpected viewType: " + viewType);
        }
    }

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

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {


        int layout;
        RecyclerView.ViewHolder viewHolder;
        switch (viewType){
            case TYPE_MAINHEADER:
                layout = R.layout.rv_header;
                View mainheaderView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new MHeaderViewHolder(mainheaderView);
                break;
            case TYPE_EXPANDABLE:
                layout = R.layout.cardview_dualline_withexpandability;
                View callsView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new CallViewHolder(callsView);
                break;
            case TYPE_NONEXPANDABLE:
                layout = R.layout.cardview_dualline_sansexpandability;
                View smsView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new SMSViewHolder(smsView);
                break;
            case TYPE_SECTIONHEADER:
                layout = R.layout.sectionheaderforrecyclerview;
                View sectionheaderView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new SectionViewHolder(sectionheaderView);
                break;
            case TYPE_TABLE:
                layout = R.layout.cardview_tableview_withexpandability;
                View tblView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new TblViewHolder(tblView);
                break;
            case TYPE_SEPARATOR:
                layout = R.layout.lineseparatorforrecyclerview;
                View separatorView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new SeparatorViewHolder(separatorView);
                break;
            default:
                throw new IllegalArgumentException("unexpected viewType: " + viewType);
        }
        return viewHolder;
    }

    // First ViewHolder of object type Call
    // Reference to the views for each call items to display desired information
    public class CallViewHolder extends RecyclerView.ViewHolder {
        final Typeface iconFont = FontManager.getTypeface(context, FontManager.FONTAWESOME);

        private TextView arrowexpandcollapseTextView, callerNameTextView, callTimeTextView;
        private LinearLayout llFacilityInformation;

        CallViewHolder(View itemView) {
            super(itemView);
            // Initiate view
            arrowexpandcollapseTextView = itemView.findViewById(R.id.tv_cvwithexpandability_arrowexpandcollapse);
            callerNameTextView = itemView.findViewById(R.id.tv_cvwithexpandability_title);
            callTimeTextView = itemView.findViewById(R.id.tv_cvwithexpandability_subtitle);
            llFacilityInformation = itemView.findViewById(R.id.ll_cvwithexpandability_subtitle);

            arrowexpandcollapseTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (llFacilityInformation.getVisibility() == View.GONE) {
                        expandLL(llFacilityInformation, arrowexpandcollapseTextView);
                    } else {
                        collapseLL(llFacilityInformation, arrowexpandcollapseTextView);
                    }
                }
            });

            callerNameTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (llFacilityInformation.getVisibility() == View.GONE) {
                        expandLL(llFacilityInformation, arrowexpandcollapseTextView);
                    } else {
                        collapseLL(llFacilityInformation, arrowexpandcollapseTextView);
                    }
                }
            });

            llFacilityInformation.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (llFacilityInformation.getVisibility() == View.GONE) {
                        expandLL(llFacilityInformation, arrowexpandcollapseTextView);
                    } else {
                        collapseLL(llFacilityInformation, arrowexpandcollapseTextView);
                    }
                }
            });
        }

        void showCallDetails(Phonecall call){
            // Attach values for each item
            arrowexpandcollapseTextView.setText(R.string.fa_icon_chevron_down);
            arrowexpandcollapseTextView.setTypeface(iconFont);
            llFacilityInformation.setVisibility(View.GONE);

            String callerName = call.getCallerName();
            String callTime = call.getCallTime();

            callerNameTextView.setText(callerName);
            callTimeTextView.setText(callTime);
        }
    }

    // Third ViewHolder of object type SectionHeader
    // Reference to the views for each call items to display desired information
    public class SectionViewHolder extends RecyclerView.ViewHolder {
        final Typeface iconFont = FontManager.getTypeface(context, FontManager.FONTAWESOME);

        private LinearLayout llSectionWithCards;
        private TextView arrowexpandcollapseTextView, sectionNameTextView;

        SectionViewHolder(View itemView) {
            super(itemView);
            // Initiate view
            arrowexpandcollapseTextView = itemView.findViewById(R.id.tv_sectionheaderforrv_expandcollapsearrow);
            sectionNameTextView = itemView.findViewById(R.id.tv_sectionheaderforrv_title);

            arrowexpandcollapseTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (llSectionWithCards.getVisibility() == View.GONE) {
                        expandLL(llSectionWithCards, arrowexpandcollapseTextView);
                    } else {
                        collapseLL(llSectionWithCards, arrowexpandcollapseTextView);
                    }
                }
            });
        }

        void showSectionDetails(SectionHeader section){
            // Attach values for each item
            arrowexpandcollapseTextView.setText(R.string.fa_icon_chevron_down);
            arrowexpandcollapseTextView.setTypeface(iconFont);

            String sectionName = section.getSectionName();

            sectionNameTextView.setText(sectionName);
        }
    }


    // Fifth ViewHolder of object type RVLineSeparator
    // Reference to the views for each call items to display desired information
    public class SeparatorViewHolder extends RecyclerView.ViewHolder {
        private View lSeparator;

        SeparatorViewHolder(View itemView) {
            super(itemView);
            lSeparator = itemView.findViewById(R.id.rv_lineseparator);
        }

        void showSeparatorDetails(){
            TypedValue tValueD = new TypedValue();
            context.getTheme().resolveAttribute(R.attr.dividerColor, tValueD, true);

            lSeparator.setBackgroundResource(tValueD.resourceId);
        }
    }

    private void expandGroup(final TextView arrowexpandcollapseTextView) {
        ?
    }

    private void collapseGroup(final TextView arrowexpandcollapseTextView) {
        ?
    }

    private void expandLL(final LinearLayout llFacilityInformation, final TextView arrowexpandcollapseTextView) {
        llFacilityInformation.setVisibility(View.VISIBLE);
        arrowexpandcollapseTextView.setText(R.string.fa_icon_chevron_up);
    }

    private void collapseLL(final LinearLayout llFacilityInformation, final TextView arrowexpandcollapseTextView) {
        llFacilityInformation.setVisibility(View.GONE);
        arrowexpandcollapseTextView.setText(R.string.fa_icon_chevron_down);
    }
}

макет заголовка раздела

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_sectionwithexpandability_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ll_sectionheader"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp"
        android:weightSum="100">

        <TextView
            android:id="@+id/tv_sectionheader_expandcollapsearrow"
            android:clickable="true"
            android:focusable="true"
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="10dp"
            android:textColor="?android:attr/textColorPrimary"
            style="@android:style/TextAppearance.Large" />

        <TextView
            android:id="@+id/tv_sectionheader_title"
            android:layout_weight="90"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            style="@android:style/TextAppearance.Large" />
    </LinearLayout>

    <!-- I WANT ALL THE CARD VIEWS TO BE ADDED INSIDE THIS LINEARLAYOUT (ll_section_cards) -->
    <LinearLayout
        android:id="@+id/ll_section_cards"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

макет RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout_recyclerView"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/my_recyclerview"
        android:clipToPadding="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical">
    </android.support.v7.widget.RecyclerView>
</LinearLayout>

SMS сообщение класс

public class SMSmessage {
    private String senderName, smsContent;

    public SMSmessage(String senderName, String smsContent) {
        this.senderName = senderName;
        this.smsContent = smsContent;
    }

    public String getSenderName() {
        return senderName;
    }

    public String getSmsContent() {
        return smsContent;
    }
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

РЕДАКТИРОВАТЬ: Ваш вопрос относится к XY-Проблема: введите описание ссылки здесь

Кажется, что вся ваша архитектура / шаблон не подходит.

Возможно, вы сможете настроить свой код так, чтобы в методе «OnBind» вы проверяли, является ли следующий объект n + 1 SMSMessage, и добавляли лот в линейный макет ... и каким-то образомзапись о том, что они уже были «связаны», чтобы избежать двойного связывания ... но тогда вам также нужно будет определить, когда этот видоискатель не связан ... что похоже на борьбу с тем, как фреймворк хочет, чтобы вы что-то делали.

Я бы предложил, чтобы API (или «локальный сервис») преобразовывал данные API (предпочтительно с использованием ObjectMapper, например, JacksonMapper) в класс, который больше похож на:

import java.util.List;

public class SMSMessageCollection {

    private List<SMSMessage> smsMessages;
    private String headerText;
    private boolean hasStartingRVLine;
    private boolean hasEndingRVLine;

    public SMSMessageCollection(String headerText, boolean hasStartingRVLine, boolean hasEndingRVLine) {
        this.headerText = headerText;
        this.hasStartingRVLine = hasStartingRVLine;
        this.hasEndingRVLine = hasEndingRVLine;
    }

    //CUSTOM "ADDER":
    public void addSMSMessagesToCollection(List<SMSMessage> smsMessagesToAdd){
        this.smsMessages.addAll(smsMessagesToAdd);
    }

    //GETTER AND SETTER HERE -> OR USE LOMBOK...

}

Этот класссодержит List<SMSMessages>, поэтому, когда объект привязывается в адаптере утилизатора, вы можете выполнять итерацию по списку и добавлять их в линейный макет.

Итак, вот как будет выглядеть моя активность ...данные API и составление списка SMSMessageCollection (s), а затем это может быть передано в адаптер с одним ViewHolder ...

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.json.JSONArray;

import java.io.IOException;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //This would be fetched using say Volley...and the structure should MATCH the class we have made...
        //Otherwise...make a "service class" to convert the API response to the SMSMessageCollection
        JSONArray apiDataModels = new JSONArray();

        // Jackson ObjectMapper will turn the API data in to a List or POJOs...in like two lines.
        try {
            List<SMSMessageCollection> smsMessageCollections = new ObjectMapper()
                    .readValue(apiDataModels.toString(),new TypeReference<List<SMSMessageCollection>>(){});
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Так в методе OnBindViewHolder в объявленииПатер, вы можете получить список для этого раздела и программно добавить их к LienarLayout внедряемого ViewHolder.

0 голосов
/ 15 октября 2018
  • Сначала используйте один родительский макет, который является линейным макетом, затем при создании дочернего макета, который содержит любой макет, например, линейный или относительный, затем второго модуля вы можете создать второй дочерний макет, а в дочернем макете вы будете использовать вид карты и другие.такой компонент, как просмотр текста или редактирование текста в представлении карты

В противном случае лучше всего использовать макет с ограничениями

Например

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_sectionwithexpandability_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:orientation="vertical">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_weight="1"
    android:layout_height="wrap_content">
<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_sectionheader"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp"
    android:weightSum="100">

    <TextView
        android:id="@+id/tv_sectionheader_expandcollapsearrow"
        android:clickable="true"
        android:focusable="true"
        android:layout_weight="10"
        android:text="Testing"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:textColor="?android:attr/textColorPrimary"
        style="@android:style/TextAppearance.Large" />

    <TextView
        android:id="@+id/tv_sectionheader_title"
        android:layout_weight="90"
        android:layout_width="0dp"
        android:text="testing"
        android:layout_height="wrap_content"
        style="@android:style/TextAppearance.Large" />
   </LinearLayout>
   </android.support.v7.widget.CardView>
  </LinearLayout>
  <!-- I WANT ALL THE CARD VIEWS TO BE ADDED INSIDE THIS LINEARLAYOUT (ll_section_cards) -->
  <LinearLayout
   android:layout_width="match_parent"
    android:layout_weight="1"
   android:layout_height="wrap_content">
   <android.support.v7.widget.CardView
       android:layout_width="match_parent"
       android:layout_height="match_parent">
   <LinearLayout
    android:id="@+id/ll_section_cards"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
  <TextView
           android:id="@+id/te"
           android:layout_weight="90"
           android:layout_width="wrap_content"
           android:text="testing"
           android:layout_height="wrap_content"
           style="@android:style/TextAppearance.Large" />
  </LinearLayout>
   </android.support.v7.widget.CardView>
  </LinearLayout>
</LinearLayout>
...