草庐IT

android - 在Android中调用自定义View的onDraw()方法

coder 2023-11-20 原文

我已经为日历创建了一个 CustomView。我有一个 onDraw 方法来在日历中绘制文本。我想在单击它时更改日期文本的颜色。我怎样才能实现它?

日历 View .java :

package com.example.calendar_module;

import java.util.Calendar;

import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.MonthDisplayHelper;
import android.view.MotionEvent;
import android.widget.ImageView;

public class CalendarView extends ImageView {

private static int WEEK_TOP_MARGIN = 0;
private static int WEEK_LEFT_MARGIN = 05;
private static int CELL_WIDTH = 20;
private static int CELL_HEIGH = 20;
private static int CELL_MARGIN_TOP = 05;
private static int CELL_MARGIN_LEFT = 29;
private static float CELL_TEXT_SIZE;
private static int CALENDAR_WIDTH;
private static int CALENDAR_HEIGHT;

private static final String TAG = "CalendarView"; 
private String[] mDayString = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
private Calendar mRightNow = null;
private Drawable mWeekTitle = null;
private Cell mToday = null;
private Cell[][] mCells = new Cell[6][7];
private Cell[] mDayCells = new Cell[7];
private OnCellTouchListener mOnCellTouchListener = null;
MonthDisplayHelper mHelper;
Drawable mDecoration = null;

public interface OnCellTouchListener {
    public void onTouch(Cell cell);
}

public CalendarView(Context context) {
    this(context, null);
}

public CalendarView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public CalendarView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mDecoration = context.getResources().getDrawable(R.drawable.typeb_calendar_today);      
    initCalendarView();
}

private void initCalendarView() {

    mRightNow = Calendar.getInstance();
    // prepare static vars

    Resources res = getResources();
    WEEK_TOP_MARGIN  = (int) res.getDimension(R.dimen.week_top_margin);
    WEEK_LEFT_MARGIN = (int) res.getDimension(R.dimen.week_left_margin);

    CELL_WIDTH = (int) res.getDimension(R.dimen.cell_width);
    CELL_HEIGH = (int) res.getDimension(R.dimen.cell_heigh);
    CELL_MARGIN_TOP = (int) res.getDimension(R.dimen.cell_margin_top);
    CELL_MARGIN_LEFT = (int) res.getDimension(R.dimen.cell_margin_left);
   //       CALENDAR_HEIGHT = 700;
  //        CALENDAR_WIDTH = 700;
  //        
    CALENDAR_HEIGHT = (int) res.getDimension(R.dimen.calendar_height);
    CALENDAR_WIDTH = (int) res.getDimension(R.dimen.calendar_width);

    System.out.println("Width and Hight :"+CALENDAR_WIDTH+" "+CALENDAR_HEIGHT);
    System.out.println("Dimen Width and Height : "+R.dimen.calendar_width+" "+R.dimen.calendar_height);

    CELL_TEXT_SIZE = res.getDimension(R.dimen.cell_text_size);
    // set background
  //        setImageResource(R.drawable.background);
    mWeekTitle = res.getDrawable(R.drawable.calendar_week);

    mHelper = new MonthDisplayHelper(mRightNow.get(Calendar.YEAR), mRightNow.get(Calendar.MONTH));


}

private void initCells() {

    class _calendar {
        public int day;
        public boolean thisMonth;
        public _calendar(int d, boolean b) {
            day = d;
            thisMonth = b;
        }
        public _calendar(int d) {
            this(d, false);
        }
    };
    _calendar tmp[][] = new _calendar[6][7];

    for(int i=0; i<tmp.length; i++) {
        int n[] = mHelper.getDigitsForRow(i);
        for(int d=0; d<n.length; d++) {
            if(mHelper.isWithinCurrentMonth(i,d))
                tmp[i][d] = new _calendar(n[d], true);
            else
                tmp[i][d] = new _calendar(n[d]);

        }
    }

    Calendar today = Calendar.getInstance();
    int thisDay = 0;
    mToday = null;
    if(mHelper.getYear()==today.get(Calendar.YEAR) && mHelper.getMonth()==today.get(Calendar.MONTH)) {
        thisDay = today.get(Calendar.DAY_OF_MONTH);
    }


    // build cells
    Rect Bound = new Rect(CELL_MARGIN_LEFT, CELL_MARGIN_TOP, CELL_WIDTH+CELL_MARGIN_LEFT, CELL_HEIGH+CELL_MARGIN_TOP);
   //       for( int i=0 ; i < 7 ; i++ )
   //       {
   //           
    //          mDayCells[i] = new Cell(mDayString[i],new Rect(Bound),CELL_TEXT_SIZE);
  //            Bound.offset(CELL_WIDTH, 0);
 //         
 //     }
 //     
 //     Bound.offset(0, CELL_HEIGH);      // move to next row and first column
 //     Bound.left = CELL_MARGIN_LEFT;
 //     Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;
 //     

    for(int week=0; week<mCells.length; week++) {
        for(int day=0; day<mCells[week].length; day++) 
        {

            if(tmp[week][day].thisMonth) {
                if(day==0 || day==6 )
                    mCells[week][day] = new RedCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
                else 
                    mCells[week][day] = new Cell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
            } else {

                mCells[week][day] = new GrayCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
            }

            Bound.offset(CELL_WIDTH, 0); // move to next column 

            // get today
            if(tmp[week][day].day==thisDay && tmp[week][day].thisMonth) {
                mToday = mCells[week][day];
                mDecoration.setBounds(mToday.getBound());
            }
        }

        Bound.offset(0, CELL_HEIGH); // move to next row and first column
        Bound.left = CELL_MARGIN_LEFT;
        Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;

    }       
}

@Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
  //        Rect re = getDrawable().getBounds();
  //        WEEK_LEFT_MARGIN = CELL_MARGIN_LEFT = (right-left - re.width()) / 2;
  //        mWeekTitle.setBounds(WEEK_LEFT_MARGIN, WEEK_TOP_MARGIN, WEEK_LEFT_MARGIN+mWeekTitle.getMinimumWidth(), WEEK_TOP_MARGIN+mWeekTitle.getMinimumHeight());

    initCells();
    super.onLayout(changed, left, top, right, bottom);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    System.out.println("Width : "+CALENDAR_WIDTH);
    System.out.println("Height : "+CALENDAR_HEIGHT);
    setMeasuredDimension(CALENDAR_WIDTH, CALENDAR_HEIGHT);
  //        setMeasuredDimension(100,200);
}

public void setTimeInMillis(long milliseconds) {
    mRightNow.setTimeInMillis(milliseconds);
    initCells();
    this.invalidate();
}

public int getYear() {
    return mHelper.getYear();
}

public int getMonth() {
    return mHelper.getMonth();
}

public void nextMonth() {
    mHelper.nextMonth();
    initCells();
    invalidate();
}

public void previousMonth() {
    mHelper.previousMonth();
    initCells();
    invalidate();
}

public boolean firstDay(int day) {
    return day==1;
}

public boolean lastDay(int day) {
    return mHelper.getNumberOfDaysInMonth()==day;
}

public void goToday() {
    Calendar cal = Calendar.getInstance();
    mHelper = new MonthDisplayHelper(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH));
    initCells();
    invalidate();
}

public Calendar getDate() {
    return mRightNow;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(mOnCellTouchListener!=null){
        for(Cell[] week : mCells) {
            for(Cell day : week) {
                if(day.hitTest((int)event.getX(), (int)event.getY())) {
                    mOnCellTouchListener.onTouch(day);
                }                       
            }
        }
    }
    return super.onTouchEvent(event);
}

public void setOnCellTouchListener(OnCellTouchListener p) {
    mOnCellTouchListener = p;
}

@Override
protected void onDraw(Canvas canvas) {
    // draw background
    super.onDraw(canvas);
    mWeekTitle.draw(canvas);

    // draw cells
    for(Cell[] week : mCells) {
        for(Cell day : week) {
            day.draw(canvas);           
        }
    }

    // draw today
    if(mDecoration!=null && mToday!=null) {
        mDecoration.draw(canvas);
    }
}



public class GrayCell extends Cell {
    public GrayCell(int dayOfMon, Rect rect, float s) {
        super(dayOfMon, rect, s);
        mPaint.setColor(Color.LTGRAY);
    }           
}

private class RedCell extends Cell {

    public RedCell(int dayOfMon, Rect rect, float s) {
        super(dayOfMon, rect, s);
        mPaint.setColor(0xdddd0000);
    }           

}


}

细胞.java :

  package com.example.calendar_module;

  import android.graphics.Canvas;
  import android.graphics.Paint;
  import android.graphics.Rect;
  import android.graphics.RectF;
  import android.graphics.drawable.Drawable;
  import android.util.Log;

  public class Cell {
private static final String TAG = "Cell";
protected Rect mBound = null;
protected int mDayOfMonth = 1;  // from 1 to 31
protected Paint mPaint = new Paint(Paint.SUBPIXEL_TEXT_FLAG
        |Paint.ANTI_ALIAS_FLAG);
int dx, dy;
protected String mDayString;
private Cell cell ;

public Cell(int dayOfMon, Rect rect, float textSize, boolean bold) {
    mDayOfMonth = dayOfMon;
    mBound = rect;
    mPaint.setTextSize(textSize);
    mPaint.setColor(Color.BLACK);
    if(bold) mPaint.setFakeBoldText(true);

    dx = (int) mPaint.measureText(String.valueOf(mDayOfMonth)) / 2;
    dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
}

public Cell(String day,Rect rect,float textSize,boolean bold)
{
    mDayString = day;
    mBound = rect;
    mPaint.setTextSize(textSize);
    mPaint.setColor(Color.BLACK);
    if(bold) mPaint.setFakeBoldText(true);

    dx = (int) mPaint.measureText(String.valueOf(mDayString)) / 2;
    dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;

}

public Cell(String day , Rect rect , float textSize , int newColor)
{
    mDayString = day;
    mBound = rect;
    mPaint.setTextSize(textSize);
    mPaint.setColor(newColor);


    dx = (int) mPaint.measureText(String.valueOf(mDayString)) / 2;
    dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
}

public Cell(int dayOfMon, Rect rect, float textSize) {
    this(dayOfMon, rect, textSize, false);
}
public Cell(String day,Rect rect,float textSize)
{
    this(day,rect,textSize,false);
}

protected void draw(Canvas canvas) {
    canvas.drawText(String.valueOf(mDayOfMonth), mBound.centerX() - dx, mBound.centerY() + dy, mPaint);
}

public int getDayOfMonth() {
    return mDayOfMonth;
}

public boolean hitTest(int x, int y) {
    return mBound.contains(x, y); 
}

public Rect getBound() {
    return mBound;
}

public String toString() {
    return String.valueOf(mDayOfMonth)+"("+mBound.toString()+")";
}




}

日历 Activity .java

package com.example.calendar_module;

import java.util.GregorianCalendar;

import com.example.calendar_module.CalendarView.OnCellTouchListener;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.DateUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class CalendarActivity extends Activity{

public static final String MIME_TYPE = "vnd.android.cursor.dir/vnd.example.calendar_module.date";
public static String mClickedDate, mClickedMonth;
CalendarView mView = null;
TextView mHit;
Handler mHandler = new Handler();
private  Button mNextButton;
private Button mPreviousButton;
private TextView mMonthText ;
private int mMonthInt;
private ListView mEventListView;


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mView = (CalendarView)findViewById(R.id.calendar);

    mEventListView = (ListView) findViewById(R.id.EventsList);
    mEventListView.setAdapter(new BadgeAdapter(this));

    mView.setOnCellTouchListener(new OnCellTouchListener() {

        @Override
        public void onTouch(Cell cell) {

            TextView mMonthText = (TextView)findViewById(R.id.MonthText);
            mClickedDate = ""+cell.getDayOfMonth();
            mClickedMonth =""+mMonthText.getText();
 //             System.out.println("Clicked date is : "+mClickedDate+" "+mClickedMonth);
 //             startActivity(new Intent(CalendarActivity.this,Event.class));

 //             cell = new Cell(cell.getDayOfMonth(),new Rect(cell.getBound()),Color.MAGENTA);

        }
    });

    mNextButton = (Button) findViewById(R.id.NextMonth);
    mPreviousButton = (Button) findViewById(R.id.PreviousMonth);
    mMonthText = (TextView) findViewById(R.id.MonthText);

    mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());

 //        System.out.println("CurrentMonth is : "+mView.getMonth());

 //        if(getIntent().getAction().equals(Intent.ACTION_PICK))
 //         findViewById(R.id.hint).setVisibility(View.INVISIBLE);
    mNextButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mView.nextMonth();
            mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());

        }
    });

    mPreviousButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            mView.previousMonth();
            mMonthText.setText(DateUtils.getMonthString(mView.getMonth(), DateUtils.LENGTH_LONG)+", "+mView.getYear());
        }
    });

    System.out.println("Calendar View Height : "+mView.getHeight());

}



private class RedCell extends Cell {

    public RedCell(Cell cell) {
        super(cell.getDayOfMonth(),new Rect(cell.getBound()), R.dimen.cell_text_size);
        mPaint.setColor(Color.RED);


    }           

  }




}

最佳答案

在该 View 的 onClick() 方法中调用 mView.invalidate();。这将调用 onDraw()(最终),然后它将为您的 View 运行绘图代码。

关于android - 在Android中调用自定义View的onDraw()方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15381448/

有关android - 在Android中调用自定义View的onDraw()方法的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  10. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

随机推荐