如何在GridView中按日期、起止时间定位单元格?(附适配器代码)
Hey there! Let's work through getting those colored course blocks perfectly positioned in your schedule GridView app. Here's a step-by-step approach tailored to your existing code:
1. Expand Your Data Structure
Right now your GridViewItem only holds a title, but we need extra info to map courses to specific cells. Let's create a separate Course class for your schedule entries (or extend your existing item class):
public class Course { private String subjectTitle; private int dayIndex; // e.g., 0 = Monday, 1 = Tuesday—matches your GridView columns private int startRow; // Which row your course starts on (e.g., row 3 = 9:00 AM) private int endRow; // Which row your course ends on private int color; // Background color for the course block // Constructor, getters, and setters public Course(String subjectTitle, int dayIndex, int startRow, int endRow, int color) { this.subjectTitle = subjectTitle; this.dayIndex = dayIndex; this.startRow = startRow; this.endRow = endRow; this.color = color; } // Getters for all fields public String getSubjectTitle() { return subjectTitle; } public int getDayIndex() { return dayIndex; } public int getStartRow() { return startRow; } public int getEndRow() { return endRow; } public int getColor() { return color; } }
Keep your original GridViewItem for base cell content (like time labels on the left or day names at the top), and add a separate list of Course objects to store your schedule data.
2. Update Your Grid Item Layout
Modify gridview_item.xml to support overlaying course blocks on top of the base cell content using a FrameLayout to stack views:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="2dp"> <!-- Base cell text (time/day labels) --> <TextView android:id="@+id/item_title" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="12sp"/> <!-- Colored course block --> <View android:id="@+id/course_block" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" android:background="@drawable/course_block_rounded"/> <!-- Course title (only visible on the first row of the course) --> <TextView android:id="@+id/course_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="4dp" android:textColor="@android:color/white" android:textSize="10sp" android:visibility="gone"/> </FrameLayout>
Create a drawable course_block_rounded.xml for adjustable rounded corners:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="8dp"/> </shape>
3. Modify the Adapter to Handle Course Positioning
Update your GridviewAdapter to calculate each cell's row/column, then match it to your course data:
public class GridviewAdapter extends BaseAdapter { private ArrayList<GridViewItem> gridCellData; private ArrayList<Course> courseList; // Add this list of courses private LayoutInflater layoutInflater; private static final int COLUMN_COUNT = 7; // Adjust to your number of days/columns public GridviewAdapter(Context context, ArrayList<GridViewItem> gridCellData, ArrayList<Course> courseList){ this.gridCellData = gridCellData; this.courseList = courseList; layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return gridCellData.size(); } @Override public Object getItem(int position) { return gridCellData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { GridViewHolder gridViewHolder; if(convertView == null){ convertView = layoutInflater.inflate(R.layout.gridview_item, parent, false); gridViewHolder = new GridViewHolder(); gridViewHolder.itemTitle = convertView.findViewById(R.id.item_title); gridViewHolder.courseBlock = convertView.findViewById(R.id.course_block); gridViewHolder.courseTitle = convertView.findViewById(R.id.course_title); convertView.setTag(gridViewHolder); } else { gridViewHolder = (GridViewHolder) convertView.getTag(); } // Calculate current cell's row and column int currentRow = position / COLUMN_COUNT; int currentCol = position % COLUMN_COUNT; // Set base cell text (time/day labels) gridViewHolder.itemTitle.setText(gridCellData.get(position).getSub_title()); // Reset course views to hidden by default gridViewHolder.courseBlock.setVisibility(View.GONE); gridViewHolder.courseTitle.setVisibility(View.GONE); // Check if any course should appear in this cell for(Course course : courseList){ if(course.getDayIndex() == currentCol && currentRow >= course.getStartRow() && currentRow <= course.getEndRow()){ // Show the colored course block gridViewHolder.courseBlock.setBackgroundColor(course.getColor()); gridViewHolder.courseBlock.setVisibility(View.VISIBLE); // Only show the course title on the first row of the course if(currentRow == course.getStartRow()){ gridViewHolder.courseTitle.setText(course.getSubjectTitle()); gridViewHolder.courseTitle.setVisibility(View.VISIBLE); } // Adjust rounded corners to make the course look like a single continuous block GradientDrawable bg = (GradientDrawable) gridViewHolder.courseBlock.getBackground(); float[] cornerRadii = new float[8]; // [top-left, top-right, bottom-right, bottom-left] ×2 if(currentRow == course.getStartRow()){ // Round top corners cornerRadii[0] = 8f; cornerRadii[1] = 8f; cornerRadii[2] = 8f; cornerRadii[3] = 8f; } if(currentRow == course.getEndRow()){ // Round bottom corners cornerRadii[4] = 8f; cornerRadii[5] = 8f; cornerRadii[6] = 8f; cornerRadii[7] = 8f; } bg.setCornerRadii(cornerRadii); } } return convertView; } static class GridViewHolder{ TextView itemTitle; View courseBlock; TextView courseTitle; } }
4. Map Dates & Times to Rows/Columns
The final step is converting your raw date/time data into dayIndex, startRow, and endRow:
- Days: Map your date (e.g., "2024-05-20" = Monday) to an index 0-6 (match your GridView's column order).
- Times: Choose a time slot interval (e.g., 30 minutes per row). Convert start/end times to row numbers (e.g., 8:00 AM = row 0, 8:30 AM = row 1, 9:00 AM = row 2).
Example Mapping Logic:
// Convert a time string like "09:00" to a row index public int timeToRow(String timeStr){ String[] parts = timeStr.split(":"); int hour = Integer.parseInt(parts[0]); int minute = Integer.parseInt(parts[1]); // Assuming first row is 8:00 AM, each row represents 30 minutes return ((hour - 8) * 2) + (minute / 30); }
This will ensure your courses line up perfectly with the correct GridView cells.
内容的提问来源于stack exchange,提问作者Dyki

