android - 自定义日历和日历适配器

标签 android baseadapter

我有一个自定义日历,是根据看到的那个修改的 here .在初始加载时,它会按预期显示所有内容。

但是我有两个问题。

1.) 在上个月按钮上,它会按预期从八月到七月,但不会清除所有图像。

2.) 从 7 月到 8 月,它停留在 7 月并重新安排日期。

基础适配器:

public class CalendarAdapter extends BaseAdapter {
    private Context mContext;
    private java.util.Calendar month;
    public GregorianCalendar pmonth; // calendar instance for previous month
    public GregorianCalendar pmonthmaxset;
    private GregorianCalendar selectedDate;
    public static List<String> dayString;
    private List<String[]> anArrayOfStrings = new ArrayList<String[]>();
    int firstDay, maxWeeknumber, maxP, calMaxP, lastWeekDay, leftDays, mnthlength;
    String itemvalue, curentDateString;
    DateFormat df;
    ImageView mimgPeriod, mimgEnergy, mimgIntercorse, mimgPregancy, mimgHeadache, mimgMood;
    DateFormat formatter;
    Date rowdatetemp;
    Date caldatetemp;
    String box;
    private int mHeight = 0;
    private int mWidth = 0;

    public CalendarAdapter(Context c, GregorianCalendar monthCalendar) {
        CalendarAdapter.dayString = new ArrayList<String>();
        Locale.setDefault( Locale.US );
        month = monthCalendar;
        selectedDate = (GregorianCalendar) monthCalendar.clone();
        mContext = c;
        month.set(GregorianCalendar.DAY_OF_MONTH, 1);
        new ArrayList<String>();
        df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        curentDateString = df.format(selectedDate.getTime());
        refreshDays();
        box = null;

    }

    public void setItems(List<String[]> anArrayOfStrings) {
        this.anArrayOfStrings = anArrayOfStrings;
    }

    public int getCount() {
        return dayString.size();
    }

    public Object getItem(int position) {
        return dayString.get(position);
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new view for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        TextView dayView;

        if (convertView == null) { // if it's not recycled, initialize some
                                    // attributes
            LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.calendar_item, null);
        }

        dayView = (TextView) v.findViewById(R.id.date);

        // separates daystring into parts.
        String[] separatedTime = dayString.get(position).split("-");

        // taking last part of date. ie; 2 from 2012-12-02
        String gridvalue = separatedTime[2].replaceFirst("^0*", "");

        // checking whether the day is in current month or not.
        if ((Integer.parseInt(gridvalue) > 1) && (position < firstDay)) {
            // setting offdays to white color.
            dayView.setTextColor(Color.WHITE);
            dayView.setClickable(false);
            dayView.setFocusable(false);
        } else if ((Integer.parseInt(gridvalue) < 7) && (position > 28)) {
            dayView.setTextColor(Color.WHITE);
            dayView.setClickable(false);
            dayView.setFocusable(false);
        } else {
            // setting curent month's days in blue color.
            dayView.setTextColor(Color.BLUE);
        }

        dayView.setText(gridvalue);

        //create date string for comparison
        String date = dayString.get(position);

        if (date.length() == 1) {
            date = "0" + date;
        }

        String monthStr = "" + (month.get(GregorianCalendar.MONTH) + 1);
        if (monthStr.length() == 1) {
            monthStr = "0" + monthStr;
        }

        //look in the hashtable in order to find the position date and then populate the img's
        if ((anArrayOfStrings != null) && (anArrayOfStrings.size() > 0)) {
            if (formatter == null) {
                formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
            }
            Log.i("PROJECTCARUSO","Date: " + date);
            for (String[] row : anArrayOfStrings) {
                //convert date's
                try {
                    caldatetemp = (Date)formatter.parse(date); 
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                try {
                    rowdatetemp = (Date)formatter.parse(row[0]); 
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                // current position date in calendar
                // array date is after the calendar date
                if (rowdatetemp.after(caldatetemp)) {
                    break;
                //current position date > first array date then continue to see if there is one for this date
                } else if (rowdatetemp.before(caldatetemp)) {
                    continue;
                //Found a match
                } else if (date.equalsIgnoreCase(row[0])) { 
                    for (int i = 1; i < row.length; i++) {
                        Log.i("PROJECTCARUSO","row[" + i +"]: " + row[i]);

                        //Now that we have a match look through each detail
                        if ( row[i]!= null ) {
                                if ((i == 1) && ((row[i].equalsIgnoreCase("yes")) || (isNumeric(row[i]))))  {
                                    mimgPeriod      = (ImageView) v.findViewById(R.id.imgPeriod);
                                    setVisible(v, mimgPeriod);
                                    mimgPeriod.setImageAlpha(100);
                                    box = "red";
                                    continue; 
                                }

                                if ((i == 2) && ((row[i].equalsIgnoreCase("yes")) || (isNumeric(row[i])))) {
                                    mimgIntercorse  = (ImageView) v.findViewById(R.id.imgIntercorse);
                                    setVisible(v, mimgIntercorse);
                                    mimgIntercorse.setImageAlpha(100);
                                    continue; 
                                }

                                if ((i == 4) && ((row[i].equalsIgnoreCase("yes")) || (isNumeric(row[i])))) {
                                    mimgHeadache    = (ImageView) v.findViewById(R.id.imgHeadache);
                                    setVisible(v, mimgHeadache);
                                    mimgHeadache.setImageAlpha(100);
                                    continue; 
                                }

                                if ((i == 5) && ((row[i].equalsIgnoreCase("yes")) || (isNumeric(row[i])))) {
                                    mimgPregancy    = (ImageView) v.findViewById(R.id.imgPregancy);
                                    setVisible(v, mimgPregancy);
                                    mimgPregancy.setImageAlpha(100);
                                    continue; 
                                }
                        }

                        if (( row[i]!= null ) && (i == 6) && (!row[i].equalsIgnoreCase("no"))) {
                            mimgEnergy      = (ImageView) v.findViewById(R.id.imgEnergy);
                            setImg(v, mimgEnergy, row[i].toString());
                            setVisible(v, mimgEnergy);
                            continue; 
                        }

                        if (( row[i]!= null ) && (i == 3) && (!row[i].equalsIgnoreCase("no"))) {
                            mimgMood        = (ImageView) v.findViewById(R.id.imgMood);
                            setImg(v, mimgMood, row[i].toString());
                            setVisible(v, mimgMood);
                            continue; 
                        }

                        if (( row[i]!= null ) && (i == 7) || (box != null)) {

                            if (box == null) {
                                if (row[i].equalsIgnoreCase("no")) {
                                    box = "brown";

                                } else {
                                    box = "yellow";
                                }
                            }

                            Drawable []layers = new Drawable [2];
                            int imageResource1 = mContext.getResources().getIdentifier("drawable/calendar_cell", null, mContext.getPackageName());
                            Drawable background = v.getResources().getDrawable(imageResource1);
                            layers [0]= background;

                            int imageResource = mContext.getResources().getIdentifier("drawable/box_" + box, null, mContext.getPackageName());
                            Drawable boxImg = v.getResources().getDrawable(imageResource);
                            boxImg.setAlpha(100);
                            layers [1]= boxImg;

                            LayerDrawable layerDrawable = new LayerDrawable (layers);

                            mWidth = v.getWidth();
                            mHeight=v.getHeight();
                            v.getLayoutParams().height = mHeight;
                            v.getLayoutParams().width = mWidth;
                            v.setBackground(layerDrawable);

                            //reset
                            box = null;

                            continue; 
                        }
                    }
                } else {
                    break;
                }
            }
        } else {
            Log.i("PROJECTCARUSO","RESETING VIEWS TO INVISIBLE");
            mimgMood        = (ImageView) v.findViewById(R.id.imgMood);
            mimgEnergy      = (ImageView) v.findViewById(R.id.imgEnergy);
            mimgPregancy    = (ImageView) v.findViewById(R.id.imgPregancy);
            mimgHeadache    = (ImageView) v.findViewById(R.id.imgHeadache);
            mimgIntercorse  = (ImageView) v.findViewById(R.id.imgIntercorse);
            mimgPeriod      = (ImageView) v.findViewById(R.id.imgPeriod);
            setInvisibleVisible(v, mimgMood);
            setInvisibleVisible(v, mimgEnergy);
            setInvisibleVisible(v, mimgPregancy);
            setInvisibleVisible(v, mimgHeadache);
            setInvisibleVisible(v, mimgIntercorse);
            setInvisibleVisible(v, mimgPeriod);
        }

        //clear the array after using it.
        //anArrayOfStrings.clear();
        return v;       
    }

    public View setVisible(View view, ImageView iv) {
        iv.setVisibility(View.VISIBLE);
        return view;
    }

    public View setInvisibleVisible(View view, ImageView iv) {
        iv.setVisibility(View.INVISIBLE);
        return view;
    }

    public View setImg(View view, ImageView iv, String mood) {
        iv.setImageAlpha(100);
        iv.setVisibility(View.VISIBLE);
        int draw = mContext.getResources().getIdentifier("drawable/" + mood, null, mContext.getPackageName()); 
        iv.setImageResource(draw);
        return view;
    }

    public void refreshDays() {
        // clear items
        anArrayOfStrings.clear();

        dayString.clear();
        Locale.setDefault( Locale.US );
        pmonth = (GregorianCalendar) month.clone();

        // month start day. ie; sun, mon, etc
        firstDay = month.get(GregorianCalendar.DAY_OF_WEEK);

        // finding number of weeks in current month.
        maxWeeknumber = month.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH);

        // allocating maximum row number for the gridview.
        mnthlength = maxWeeknumber * 7;
        maxP = getMaxP(); // previous month maximum day 31,30....
        calMaxP = maxP - (firstDay - 1);// calendar offday starting 24,25 ...

        pmonthmaxset = (GregorianCalendar) pmonth.clone();
        pmonthmaxset.set(GregorianCalendar.DAY_OF_MONTH, calMaxP + 1);

        for (int n = 0; n < mnthlength; n++) {

            itemvalue = df.format(pmonthmaxset.getTime());
            pmonthmaxset.add(GregorianCalendar.DATE, 1);
            dayString.add(itemvalue);

        }
    }

    private int getMaxP() {
        int maxP;
        if (month.get(GregorianCalendar.MONTH) == month
                .getActualMinimum(GregorianCalendar.MONTH)) {
            pmonth.set((month.get(GregorianCalendar.YEAR) - 1),
                    month.getActualMaximum(GregorianCalendar.MONTH), 1);
        } else {
            pmonth.set(GregorianCalendar.MONTH,
                    month.get(GregorianCalendar.MONTH) - 1);
        }
        maxP = pmonth.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);

        return maxP;
    }

    @SuppressWarnings("unused")
    public static boolean isNumeric(String str)  
    {  
      try  
      {  
        double d = Double.parseDouble(str);  
      }  
      catch(NumberFormatException nfe)  
      {  
        return false;  
      }  
      return true;  
    }

}

日历:

public class CalendarFragment extends Fragment {

    public GregorianCalendar month;// calendar instances.
    public CalendarAdapter adapter;           // adapter instance
    public Handler handler;                   // for grabbing some event values for showing the dot
                                              // marker.
    public ArrayList<String> items;           // container to store calendar items which
                                              // needs showing the event marker
    int i;
    List<String[]> anArrayOfStrings = new ArrayList<String[]>();
    String startdate, enddate;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }     

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {     
        View view = inflater.inflate(R.layout.fragment_calendar, null);

        month = (GregorianCalendar) GregorianCalendar.getInstance();
        month.set(Calendar.DAY_OF_MONTH, 1-1);

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd",Locale.US);

        //start date for cursor
        startdate = df.format(month.getTime());

        //end date
        month.add(Calendar.MONTH, 1);
        month.add(Calendar.DAY_OF_MONTH, +5);
        enddate = df.format(month.getTime());

        month.add(Calendar.MONTH, -1);
        Locale.setDefault( Locale.US );
        month = (GregorianCalendar) GregorianCalendar.getInstance();

        items = new ArrayList<String>();
        adapter = new CalendarAdapter(getActivity(), month);

        GridView gridview = (GridView) view.findViewById(R.id.gridview);
        gridview.setAdapter(adapter);

        handler = new Handler();
        handler.post(calendarUpdater);

        TextView title = (TextView) view.findViewById(R.id.title);
        title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));

        RelativeLayout previous = (RelativeLayout) view.findViewById(R.id.previous);

        previous.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                setPreviousMonth();
                refreshCalendar();
            }
        });

        RelativeLayout next = (RelativeLayout) view.findViewById(R.id.next);
        next.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                setNextMonth();
                refreshCalendar();

            }
        });

        gridview.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v,
                    int position, long id) {

                String selectedGridDate = CalendarAdapter.dayString
                        .get(position);
                String[] separatedTime = selectedGridDate.split("-");
                String gridvalueString = separatedTime[2].replaceFirst("^0*",
                        "");// taking last part of date. ie; 2 from 2012-12-02.
                int gridvalue = Integer.parseInt(gridvalueString);
                // navigate to next or previous month on clicking offdays.
                if ((gridvalue > 10) && (position < 8)) {
                    setPreviousMonth();
                    refreshCalendar();
                } else if ((gridvalue < 7) && (position > 28)) {
                    setNextMonth();
                    refreshCalendar();
                }
            }
        });
        return view;
    }

    protected void setNextMonth() {
        if (month.get(GregorianCalendar.MONTH) == month
                .getActualMaximum(GregorianCalendar.MONTH)) {
            month.set((month.get(GregorianCalendar.YEAR) + 1),
                    month.getActualMinimum(GregorianCalendar.MONTH), 1);
        } else {
            month.set(GregorianCalendar.MONTH,
                    month.get(GregorianCalendar.MONTH) + 1);
        }

    }

    protected void setPreviousMonth() {
        if (month.get(GregorianCalendar.MONTH) == month
                .getActualMinimum(GregorianCalendar.MONTH)) {
            month.set((month.get(GregorianCalendar.YEAR) - 1),
                    month.getActualMaximum(GregorianCalendar.MONTH), 1);
        } else {
            month.set(GregorianCalendar.MONTH,
                    month.get(GregorianCalendar.MONTH) - 1);
        }

    }

    public void refreshCalendar() {
        TextView title = (TextView) getActivity().findViewById(R.id.title);

        adapter.refreshDays();
        adapter.notifyDataSetChanged();
        handler.post(calendarUpdater); // generate some calendar items

        title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));
    }

    public Runnable calendarUpdater = new Runnable() {

        @Override
        public void run() {

            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd",Locale.US);

            //start date for cursor
            month.add(Calendar.DAY_OF_MONTH, -1);
            startdate = df.format(month.getTime());

            //end date
            month.add(Calendar.MONTH, 1);
            enddate = df.format(month.getTime());
            month.add(Calendar.MONTH, -1);

            anArrayOfStrings.clear();

            // Get the data
            Cursor c = getActivity().getContentResolver().query(StatusProvider.CONTENT_URI_CHARTING, null, "? < " + StatusData.KEY_CHARTING_DATE + " AND ? > " + StatusData.KEY_CHARTING_DATE , new String[] {startdate, enddate}, StatusData.KEY_CHARTING_DATE + " ASC");
            c.moveToFirst();
            while(c.isAfterLast() == false){
                anArrayOfStrings.add( new String [] {c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_DATE)),
                                              c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_PERIOD)), c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_INTERCORSE)), 
                                              c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_MOOD)), c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_HEADACHE)), 
                                              c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_TEST)), c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_ENERGY)),
                                              c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_FERTILE) )});


                Log.i("PROJECTCARUSO","DATE ADDED TO ARRAY:" +  c.getString(c.getColumnIndex(StatusData.KEY_CHARTING_DATE)));

                i+=1;
                c.moveToNext();
            } 

            adapter.setItems(anArrayOfStrings);
            adapter.notifyDataSetChanged();
        }
    };

}

日历项.xml

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

    <LinearLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1"
            android:textColor="#0000D7"
            android:textSize="14sp"
            android:textStyle="bold" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/imgPeriod"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/period"  
            android:visibility="invisible"/>

        <ImageView
            android:id="@+id/imgIntercorse"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/intercorse"
            android:visibility="invisible" />

        <ImageView
            android:id="@+id/imgPregancy"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/pregnancy"
            android:visibility="invisible"  />
    </LinearLayout>


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/imgEnergy"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/energy_1"
            android:visibility="invisible" />

        <ImageView
            android:id="@+id/imgHeadache"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/pregnancy"
            android:visibility="invisible" />

        <ImageView
            android:id="@+id/imgMood"
            android:layout_width="15dp"
            android:layout_height="15dp"
            android:src="@drawable/mood"
            android:visibility="invisible" />
     </LinearLayout>

</LinearLayout>

fragment 日历.xml

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

    <RelativeLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/calendar_top" >

        <RelativeLayout
            android:id="@+id/previous"
            android:layout_width="40dip"
            android:layout_height="30dip"
            android:layout_alignParentLeft="true" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:background="@drawable/arrow_left" />
        </RelativeLayout>

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="5dip"
            android:textColor="#000000"
            android:textSize="18dip"
            android:textStyle="bold" />

        <RelativeLayout
            android:id="@+id/next"
            android:layout_width="40dip"
            android:layout_height="30dip"
            android:layout_alignParentRight="true" >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:background="@drawable/arrow_right" />
        </RelativeLayout>
    </RelativeLayout>

    <GridView
        android:id="@+id/gridview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:listSelector="@android:color/transparent"
        android:numColumns="7"
        android:stretchMode="columnWidth" />

</LinearLayout>

最佳答案

第一个修复:我没有重置背景。所以这修复了那部分。现在,上个月的 View (日期)不会重新填充。

//set background
int imageResource = mContext.getResources().getIdentifier("drawable/calendar_cell", null, mContext.getPackageName());
Drawable orgImg = v.getResources().getDrawable(imageResource);
v.setBackground(orgImg);

第二个修复:重复使用日历对象会丢弃您的日历。创建一个新的日历对象,这样它们就不会相互冲突。

关于android - 自定义日历和日历适配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17889878/

相关文章:

安卓;如何在其他小部件保持左对齐时右对齐按钮

android - ListView 第一个元素不可点击

java - fragment 中带有 Gridview 的 Android ImageAdapter

android - GridView 内的项目在上下滚动时再次加载

android - 使用 SharedPreferences 在 ListView 中保存 ToggleButton 状态

android - 如何在代码中选择 ListView 中的第一项(使用 baseadapter)以更改其背景

Android Activity 转换不出现

android - 重新创建 View 后, fragment 从ViewModel中丢失数据

java - Java中从子类构造函数调用 super 构造函数

使用数据作为 map 的 notifyDataSetChanged 后,Android ListView 不刷新