Android: установка сетки динамических и пользовательских объектов внутри другой сетки динамических и пользовательских объектов
Я работаю над проектом Android, в котором я использую среду SuperSlim для создания сетчатого представления Notes (Custom class) вместе с данными, которые будут отображаться. Заметки в базе данных имеют отношение "много к одному" с разделами (пользовательский класс). И разделы, в свою очередь, имеют отношения "много-к-одному" с Canvas.
Вся информация по разделу, заметкам динамически извлекается с сервера в виде списка.
Теперь я нахожусь в точке, где я могу отобразить представление Grid разделов и помещать текстовую информацию в грид, например, имя раздела и т.д.
Для целей тестирования я также добавил статически извлеченный текст из заметки.
Я новичок в программировании на Android, поэтому, пожалуйста, не против, если код выглядит испорченным.
Теперь это проблемы, с которыми я сталкиваюсь:
1) Как отобразить сетку разделов и в каждом отображаемом разделе, я хотел бы отобразить Grid of Notes. Поскольку существует взаимосвязь "один ко многим", может быть много заметок в каждом разделе. Это моя основная проблема.
2) С отображением вышеуказанного материала я хотел бы сохранить поле SectionName редактируемым, и у меня есть метод REST, с помощью которого я могу редактировать имя раздела, но мне нужен и идентификатор раздела. Он доступен по щелчку, я хотел бы сохранить это.
3) Сетка заметок, отображаемая внутри раздела, должна быть доступна для кликов, поэтому я могу позже открыть что-то похожее на Modal, чтобы пользователь мог прочитать всю заметку и отредактировать ее.
Ниже снимок экрана показывает мою текущую ситуацию:
Левая сторона мобильного телефона была оригинальной, как должен выглядеть список разделов сетки. Я изменил его, чтобы отобразить больше информации, только для тестирования, и с помощью SuperSlim для добавления информации немного более правильно.
Обратите внимание, что в настоящее время в коде я статически вызываю метод NotesList для жестко закодированного раздела. Это нежелательно. Наконец код:
GroupSectionActivity:
public class GroupSectionActivity extends ActionBarActivity {
private SectionServiceImpl sectionService = new SectionServiceImpl();
private static volatile List<RestSection> restSectionList = new ArrayList<>();
private static volatile Long groupAccountId;
private static volatile Integer canvasid;
static final String msectionname = "msectionname";
static final String msectionid = "msectionid";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_section_activity);
Bundle extras = getIntent().getExtras();
if (extras != null) {
groupAccountId = extras.getLong("groupid");
canvasid = extras.getInt("canvasid");
}
if(savedInstanceState == null){
getFragmentManager().beginTransaction().add(R.id.container, new NoteFragments(), "msectionname").commit();
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbar!=null){
setSupportActionBar(toolbar);
}
restSectionList = this.sectionService.getSectionByCanvas(canvasid);
ArrayList<HashMap<String, String>> restSectionArrayList = new ArrayList<HashMap<String, String>>();
for (RestSection restSection : restSectionList) {
HashMap<String, String> sectionDisplay = new HashMap<>();
sectionDisplay.put("msectionid", String.valueOf(restSection.getMsectionid()));
sectionDisplay.put("msectionname", restSection.getMsectionname());
restSectionArrayList.add(sectionDisplay);
}
/* listView = (ListView) findViewById(R.id.seclist);
sectionLazyAdapter = new SectionLazyAdapter(this, restSectionArrayList);
listView.setAdapter(sectionLazyAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
int sectionId = restSectionList.get(position).getMsectionid();
Log.d("Sectionid is ", String.valueOf(sectionId));
*//*Intent intent = new Intent(GroupSectionActivity.this, GroupSectionActivity.class);
intent.putExtra("groupid", groupAccountId);
intent.putExtra("sectionid", sectionId);
startActivity(intent);
finish();*//*
}
});
addSectionButton = (Button) findViewById(R.id.sectionAddButton);
addSectionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int val = addGroupSection();
if (val == 0) {
sectionName.setError("Section Name cannot be null");
} else {
sectionName.clearComposingText();
sectionName.clearAnimation();
sectionName.setText("");
Toast.makeText(getApplicationContext(), "Section added", Toast.LENGTH_LONG).show();
}
}
});*/
}
public Integer addGroupSection(){
/* sectionName = (EditText) findViewById(R.id.sectionNameTextField);
if (!(sectionName.getText().toString().isEmpty())) {
RestSection restSection = new RestSection();
restSection.setMsectionname(sectionName.getText().toString());
return this.sectionService.addGroupSection(restSection,canvasid);
}
*/
return 0;
}
@Override
public void onBackPressed() {
Intent intent = new Intent(GroupSectionActivity.this, GroupCanvasActivity.class);
intent.putExtra("groupid", groupAccountId);
startActivity(intent);
finish();
}
private NoteFragments getSectionsFragment() {
return (NoteFragments) getFragmentManager().findFragmentByTag(msectionname);
}
}
РазделLazyAdapter:
public class SectionLazyAdapter extends BaseAdapter{
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public SectionLazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.activity_group_section, null);
TextView sectionName = (TextView)vi.findViewById(R.id.sectionname); // title
HashMap<String, String> sectionList = new HashMap<String, String>();
sectionList = data.get(position);
sectionName.setText(sectionList.get(GroupSectionActivity.msectionname));
return vi;
}
}
NoteAdapters:
public class NoteAdapters extends RecyclerView.Adapter<NoteViewHolder> {
private NoteServiceImpl noteService = new NoteServiceImpl();
private static final int LINEAR = 0;
private final Context mContext;
private SectionServiceImpl sectionService = new SectionServiceImpl();
List<RestSection> restSectionList = new ArrayList<>();
private final ArrayList<LineItem> mItems;
public NoteAdapters(Context context, int headermode) {
mContext = context;
int sectionManager = -1;
int sectionFirstPosition = 0;
mItems = new ArrayList<>();
restSectionList = this.sectionService.getSectionByCanvas(2500);
for (int i = 0; i < restSectionList.size(); i++) {
String header = restSectionList.get(i).getMsectionname();
RestNote restNote = this.noteService.getFirstNoteForSection(restSectionList.get(i).getMsectionid());
mItems.add(new LineItem(header, true, sectionManager, sectionFirstPosition, restNote.getMnotetext()));
}
}
@Override
public NoteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_group_section, parent, false);
return new NoteViewHolder(view);
}
@Override
public void onBindViewHolder(NoteViewHolder holder, int position) {
final LineItem item = mItems.get(position);
final View itemView = holder.itemView;
holder.bindText(item.text);
holder.bindNoteData(item.otherText);
final GridSLM.LayoutParams lp = GridSLM.LayoutParams.from(itemView.getLayoutParams());
lp.setSlm(item.sectionManager == LINEAR ? LinearSLM.ID : GridSLM.ID);
lp.setColumnWidth(mContext.getResources().getDimensionPixelSize(R.dimen.grid_column_width));
lp.setFirstPosition(item.sectionFirstPosition);
itemView.setLayoutParams(lp);
}
@Override
public int getItemCount() {
return mItems.size();
}
/* @Override
public void onClick(View v) {
if(v instanceof ImageView){
Log.d("Image","Clicked");
} else {
Log.d("Text","Clicked");
}
}*/
private static class LineItem {
public int sectionManager;
public int sectionFirstPosition;
public boolean isHeader;
public String text;
public String otherText;
public LineItem(String text, boolean isHeader, int sectionManager,
int sectionFirstPosition, String otherText) {
this.isHeader = isHeader;
this.text = text;
this.sectionManager = sectionManager;
this.sectionFirstPosition = sectionFirstPosition;
this.otherText = otherText;
}
}
}
Примечание:
public class NoteFragments extends Fragment {
private ViewHolder mViews;
private NoteAdapters noteAdapters;
private int mHeaderDisplay;
private boolean mAreMarginsFixed;
private Random mRng = new Random();
private Toast mToast = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.section_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mViews = new ViewHolder(view);
mViews.initViews(new LayoutManager(getActivity()));
noteAdapters = new NoteAdapters(getActivity(), mHeaderDisplay);
mViews.setAdapter(noteAdapters);
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
}
private static class ViewHolder {
private final RecyclerView mRecyclerView;
public ViewHolder(View view) {
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
}
public void initViews(LayoutManager lm) {
mRecyclerView.setLayoutManager(lm);
}
public void scrollToPosition(int position) {
mRecyclerView.scrollToPosition(position);
}
public void setAdapter(RecyclerView.Adapter<?> adapter) {
mRecyclerView.setAdapter(adapter);
}
public void smoothScrollToPosition(int position) {
mRecyclerView.smoothScrollToPosition(position);
}
}
}
NoteViewHolder:
public class NoteViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
private TextView noteData;
private ImageView imageView;
public NoteViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.sectionname);
imageView = (ImageView) itemView.findViewById(R.id.sectionimage);
noteData = (TextView) itemView.findViewById(R.id.noteText);
}
public void bindText(String text){
textView.setText(text);
}
public void bindImage(Bitmap bitmap){
imageView.setImageBitmap(bitmap);
}
public void bindNoteData(String data){
noteData.setText(data);
}
}
Файлы XML: activity_group_section.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:orientation="vertical">
<ImageView
android:id="@+id/sectionimage"
android:layout_width="140dp"
android:layout_height="200dp"
android:scaleType="fitXY"
android:padding="5dp"
android:src="@drawable/sectionbackground"
/>
<TextView
android:id="@+id/sectionname"
android:layout_width="90dp"
android:layout_height="match_parent"
android:text="@string/textView"
android:visibility="visible"
android:gravity="center"
android:layout_gravity="center_horizontal|top"
android:maxLines="1"
android:ellipsize="end"
android:scrollHorizontally="true"
android:layout_marginTop="10dp" />
<TextView
android:layout_width="97dp"
android:layout_height="160dp"
android:id="@+id/noteText"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="10dp"
android:layout_marginTop="30dp" />
</FrameLayout>
</RelativeLayout>
SectionFragment:
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:clipToPadding="false"
android:layout_height="wrap_content" />
Модели классов для раздела и примечаний:
public class RestSection {
private int msectionid;
private String msectionname;
private int mxposition;
private int myposition;
private int msectionwidth;
private int msectionheight;
}
public class RestNote {
private int mnoticesid;
private String mnotetext;
private String mnotetag;
private String mnotecolor;
private double mnoteorder;
}
Надеюсь, мой вопрос ясен, если есть что-то требуемое, любезно сообщите мне.
Ответы
Ответ 1
Вы на самом деле очень близки к вашей реализации, но есть несколько замечаний. Ваша сетка верхнего уровня настроена для использования адаптеров ListView/GridView, а ваша сетка второго уровня настроена для RecyclerView.Adapters. Все это хорошо и хорошо, когда вы знаете, что делаете. Тем не менее, я бы рекомендовал использовать один или другой на всем пути (желательно RecyclerView.Adapters, поскольку они более масштабируемы). Чтобы все было просто, я дам решение, используя вашу текущую настройку:
Верхний уровень (BaseAdapter/ListAdapter + GridView)
Вам необходимо передать весь набор данных в адаптер верхнего уровня, например. ArrayList из RestSection вместо ArrayList из HashMap. HashMap может быть членом RestSection, если эти данные необходимы, но кажется, что это может быть заменено простой строкой. Структура данных RestSection также должна иметь член, который является списком RestNotes. Элемент-представление для этого адаптера должен иметь RecyclerView, который находится внутри NoteFragment в вашем случае. Это потенциально заменит noteText в файле activity_group_section.xml. В getView() вашего адаптера вы должны установить адаптер этого RecyclerView с примечаниями, относящимися к разделу. Подробнее см. В следующих фрагментах кода.
Структуры данных:
public class RestSection {
private int msectionid;
private String msectionname;
private int mxposition;
private int myposition;
private int msectionwidth;
private int msectionheight;
private List<RestNote> mnotes;
}
public class RestNote {
private int mnoticesid;
private String mnotetext;
private String mnotetag;
private String mnotecolor;
private double mnoteorder;
}
SectionLazyAdapter:
public class SectionLazyAdapter extends BaseAdapter{
private List<RestSection> data;
//...
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.activity_group_section, null);
RestSection mySection = data.get(position);
TextView sectionName = (TextView)vi.findViewById(R.id.sectionname); // title
sectionName.setText(mySection.getSectionName());
NoteFragments noteGridView = (NoteFragments) vi.findViewById(R.id.notegridfragment);
noteGridView.setRecyclerViewAdapter(new NoteAdapter(mySection.getNotes()));
return vi;
}
}
activity_group_section.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:orientation="vertical">
<ImageView
android:id="@+id/sectionimage"
android:layout_width="140dp"
android:layout_height="200dp"
android:scaleType="fitXY"
android:padding="5dp"
android:src="@drawable/sectionbackground"
/>
<TextView
android:id="@+id/sectionname"
android:layout_width="90dp"
android:layout_height="match_parent"
android:text="@string/textView"
android:visibility="visible"
android:gravity="center"
android:layout_gravity="center_horizontal|top"
android:maxLines="1"
android:ellipsize="end"
android:scrollHorizontally="true"
android:layout_marginTop="10dp" />
<fragment android:name="com.mypackagename.NoteFragments"
android:layout_width="97dp"
android:layout_height="160dp"
android:id="@+id/notegridfragment"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="10dp"
android:layout_marginTop="30dp" />
</FrameLayout>
</RelativeLayout>
2-й уровень (RecyclerView.Adapter + RecyclerView)
Этот адаптер должен взять список Notes в качестве набора данных (как показано в разделе SectionLazyAdapter выше). Используйте данные Note для заполнения пользовательского интерфейса, как и раньше. См. Фрагменты кода ниже.
NoteFragments:
public class NoteFragments extends Fragment {
private RecyclerView noteGridView;
// ...
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// as before
noteGridView = (RecyclerView) view;
}
public void setRecyclerViewAdapter(NoteAdapter adapter){
noteGridView.setAdapter(adapter);
}
}
NoteAdapter:
public class NoteAdapters extends RecyclerView.Adapter<NoteViewHolder> {
private List<RestNote> mItems;
public NoteAdapters(List<RestNote> notes) {
super();
mItems = notes;
}
@Override
public void onBindViewHolder(NoteViewHolder holder, int position) {
// populate as before... make sure that RestNote has all of the data required
}
}
Конечно, вам придется переупорядочить ваши данные до требуемого формата, но я думаю, что будет легче отображать данные таким образом.
Я надеюсь, что это поможет.