Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Java программирование > Java Мобильная разработка (Android)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.02.2016, 02:54   #1
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию Список с разными и сложными элементами Android

Здравствуйте, дорогие форумчане.
Задумал я тут создать клиент под Android для VK, и у меня появились проблемы.
Мне нужно отобразить список новостей. Так как их много, логично выводить их как-то в виде списка.
Однако новости могут быть разными, на них должно быть несколько разных кнопок.
В общем, как мне сделать список, у которого каждый элемент будет содержать несколько других компонент?
Думал попробовать сделать fragment и выводить их, но как-то не получилось, да и по результатам гугления понял, что это скорее неправильный подход.
Вот на toster есть предложение создать adapter свой, но не хотелось бы переписывать стандартный класс, так как мне кажется, что кто-то эту проблему уже решал (создатели официального приложения, например).
https://toster.ru/q/219276

Заранее спасибо за помощь.
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 19.02.2016, 15:00   #2
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию Решение

Разобрался.
Вот годные ссылки на stackoverflow и developer.android. com
https://stackoverflow.com/questions/...nt-cardlayouts
https://developer.android.com/intl/r...sts-cards.html

Обсуждение на cyberforum:

В общем, смог реализовать список со сложными элементами и разной логикой. Привожу код, так как это может оказаться кому-нибудь полезным.

Так как RecyclerView и CardView - нестандартные, надо в dependencies в файле build.gradle (Module app) добавить
Код:
    compile 'com.android.support:cardview-v7:23.0.+'
    compile 'com.android.support:recyclerview-v7:23.0.+'
Вот код элементов, которые нужно представить:
Код:
public abstract class Item {
    public abstract String toString();
}

public class Item0 extends Item {
    private String value;
    public Item0(String v){value=v;}
    @Override
    public String toString() {return value;}
}

public class Item1 extends Item {
    public boolean checked = false;
    public String caption;
    public Item1(String v){caption = v;}
    @Override
    public String toString() {return caption+": "+checked;}
}
Вот код xml файлов:

Код activity
Код:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.user.tmp.MainActivity">
    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/mainRecyclerView"
        android:scrollbars="vertical"
        ></android.support.v7.widget.RecyclerView>
</RelativeLayout>
Код item0.xml:
Код:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/activity_vertical_margin"
    android:layout_width="match_parent">
    <!-- A CardView that contains a TextView -->
    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        card_view:cardCornerRadius="4dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="New Text"
                android:id="@+id/textView" />
        </RelativeLayout>
    </android.support.v7.widget.CardView>

</LinearLayout>
Код item1.xml:
Код:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/activity_vertical_margin"
    android:layout_width="match_parent">
    <!-- A CardView that contains a TextView -->
    <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        card_view:cardCornerRadius="4dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:text="New Text"
                android:id="@+id/textView" />

            <CheckBox
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/textView"
                android:text="New CheckBox"
                android:id="@+id/checkBox" />
        </RelativeLayout>
    </android.support.v7.widget.CardView>

</LinearLayout>
Продолжение следует...
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 19.02.2016, 15:02   #3
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию Вторая часть.

Мой переопределенный Adapter. Именно здесь определяется, какой именно View будет в качестве элемента + связываются обработчики нажатий и всё такое.
Код:
/**
 * Created by Angelicos Phosphoros on 19.02.2016.
 */
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Item> data;

    public MyAdapter(List<Item> strs){
        data = strs;
    }

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

    //Переопределяем метод, так как именно результат этого метода отправляется в onCreateViewHolder
    @Override
    public int getItemViewType(int position) throws IllegalArgumentException{
        Item item = data.get(position);
        if (Item0.class.isInstance(item)) return 0;
        if (Item1.class.isInstance(item)) return 1;
        throw  new IllegalArgumentException("Unknown element");
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        RecyclerView.ViewHolder vh;
        //Чтобы понять, откуда мы знаем viewType, см. getItemViewType выше
        switch (viewType){
            case 0: view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item0,parent,false);
                vh = new ViewHolderZero(view);
                break;
            case 1: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item1,parent,false);
                vh = new ViewHolderOne(view);
                break;
            default: vh = null;
        }
        return vh;
    }

    //Заполняем всё данными
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (Item0.class.isInstance(data.get(position))){
            Item0 item = (Item0)data.get(position);
            ((ViewHolderZero)holder).tv.setText(item.toString());
        }
        else{
            Item1 item = (Item1)data.get(position);
            ViewHolderOne vh1 = ((ViewHolderOne) holder);
            vh1.cb.setChecked(item.checked);
            vh1.tv.setText(item.caption);
            //В тэги закидываем наш объект из-за того, что в обработчике надо получить этот объект из кнопки
            vh1.cb.setTag(item);
            vh1.cb.setOnCheckedChangeListener(onCheckedChangeListener);
        }
    }

    //Два класса ViewHolder

    public class ViewHolderZero extends RecyclerView.ViewHolder{
        TextView tv;
        public ViewHolderZero(View v){
            super(v);
            tv = (TextView)v.findViewById(R.id.textView);
        }
    }

    public class ViewHolderOne extends RecyclerView.ViewHolder{
        TextView tv;
        CheckBox cb;
        public ViewHolderOne(View v){
            super(v);
            tv =(TextView)v.findViewById(R.id.textView);
            cb = (CheckBox)v.findViewById(R.id.checkBox);
        }
    }

    //Обработчик клика на чекбокс
    CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            ((Item1)buttonView.getTag()).checked = buttonView.isChecked();
        }
    };
}
Вот описание MainActivity.
Код:
public class MainActivity extends AppCompatActivity {
    private Random random = new Random();
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView)findViewById(R.id.mainRecyclerView);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new MyAdapter(createData(50));
        recyclerView.setAdapter(adapter);
    }

    private List<Item> createData(int length){
        LinkedList<Item> ll = new LinkedList<>();
        for (int i = 0;i<length;i++){
            StringBuilder str = new StringBuilder(i);
            for (int j = 0;j<=i;j+=10)
                str.append('\n').append(j);
            if (random.nextBoolean()){
                ll.add(new Item0("ZeroType\n"+str.toString()));
            }
            else {
                ll.add(new Item1("FirstType\n"+str.toString()));
            }
        }
        return ll;
    }
}
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Android: Список запущеных приложений mc13 Общие вопросы C/C++ 11 16.01.2015 22:18
Delphi XE5 получить список контактов android saragosa Общие вопросы Delphi 1 07.10.2013 15:31
Паскаль. Список с различными элементами ProofAlex Помощь студентам 10 25.01.2011 13:33
Компоновка со сложными условиями A-ton Microsoft Office Excel 2 28.08.2009 07:02
Имеется список,элементами которого являются вещественные числа.Создать консольное приложение,описывающее Smart Помощь студентам 1 06.05.2008 08:09