SherlockActionBar NullPointerException - java
I'm working on an android app that is a hearing test. it was quite outdated so I've had to update it. I've used the Sherlock library so the app is compatible for many different phones. What I'm trying to do is get the results of a hearing test to show up. The problem I'm getting it when I draw the graph to show the user how well they did, I'm getting a null pointer exception.
once the test is completed, the user is taken to the Saved tests Activity shown below:
public class SavedResultsActivity extends SherlockListActivity {
// TODO set column names when saving test implemented
private static final String TEST_NAME_COLUMN = ResultsDatabase.SAVED_NAME;
private static final String TEST_DATE_COLUMN = ResultsDatabase.COLUMN_NAME_CREATE_DATE;
private ResultsDatabase mDb;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDb = new ResultsDatabase(this);
setContentView(R.layout.saved_tests);
ActionBar ab = getSherlock().getActionBar();
SherlockHelper.setupActionBar(ab, this);
TextView titleText = (TextView)findViewById(R.id.title_text);
titleText.setText(R.string.Saved_Tests);
// Set the empty view
getListView().setEmptyView(findViewById(R.id.empty));
getListView().setItemsCanFocus(true);
// Get a cursor with all phones
Cursor c = getSavedTests();
if ( c != null ) {
// Set up our adapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.saved_results_item, c,
new String[] { TEST_NAME_COLUMN, TEST_DATE_COLUMN, TEST_DATE_COLUMN },
new int[] { android.R.id.text1, android.R.id.text2, R.id.delete_button });
adapter.setViewBinder(mViewBinder);
// Set up our adapter
setListAdapter(adapter);
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
Intent intent = new Intent(this, TabbedResults.class);
Cursor cursor = (Cursor) getListAdapter().getItem(position);
intent.putExtra(ResultsDatabase._ID, cursor.getInt(cursor.getColumnIndex(ResultsDatabase._ID)));
startActivity(intent);
}
private final ViewBinder mViewBinder = new SimpleCursorAdapter.ViewBinder(){
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if ( view.getId() == android.R.id.text1 ){
String name = cursor.getString(columnIndex);
TextView nameView = (TextView)view;
nameView.setText(name);
} else if ( view.getId() == android.R.id.text2 ){
long date = cursor.getLong(columnIndex);
String dateStr = DateUtils.formatDateTime(view.getContext(), date, DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE);
TextView dateView = (TextView)view;
dateView.setText(dateStr);
} else if ( view.getId() == R.id.delete_button ){
int idCol = cursor.getColumnIndex(ResultsDatabase._ID);
final long id = cursor.getLong(idCol);
view.setOnClickListener( new OnClickListener(){
#Override
public void onClick(View v) {
deleteTest(id);
}
});
}
return true;
}
};
private static final String DELETE_SELECTION = ResultsDatabase._ID + " = ? ";
private void deleteTest(long id) {
String[] whereArgs = new String[]{String.valueOf(id)};
SQLiteDatabase db = mDb.getWritableDatabase();
db.delete(ResultsDatabase.TABLE_NAME, DELETE_SELECTION, whereArgs);
SimpleCursorAdapter adapter = (SimpleCursorAdapter) getListAdapter();
adapter.getCursor().requery();
adapter.notifyDataSetChanged();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
// TODO fetch list of saved tests
private Cursor getSavedTests(){
// get cursor
SQLiteDatabase db = mDb.getReadableDatabase();
Cursor c = db.query(ResultsDatabase.TABLE_NAME, null, null, null, null, null,null);
startManagingCursor(c);
return c;
}
}
Here the user will click on the test they want to view and that will take the user to a tabbed results page one tab for one ear the other tab for the other ear. I've used fragments for this:
public class TabbedResults extends SherlockFragmentActivity{
TabHost mTabHost;
TabManager mTabManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_indicator);
ActionBar ab = this.getSupportActionBar();
SherlockHelper.setupActionBar(ab, this);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
mTabManager.addTab(mTabHost.newTabSpec(getString(R.string.Left_ear)).setIndicator(getString(R.string.Left_ear)),
ResultActivity.Results.class, null);
mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator(getString(R.string.Left_ear)),
ResultActivity.Results.class, null);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tab", mTabHost.getCurrentTabTag());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
}
this method uses another method called TabManager to manage which tab is open etc:
public class TabManager extends SherlockFragmentActivity implements TabHost.OnTabChangeListener {
private final FragmentActivity mActivity;
private final TabHost mTabHost;
private final int mContainerId;
private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
TabInfo mLastTab;
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
private Fragment fragment;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
#Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
mActivity = activity;
mTabHost = tabHost;
mContainerId = containerId;
mTabHost.setOnTabChangedListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mActivity));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
if (info.fragment != null && !info.fragment.isDetached()) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
ft.detach(info.fragment);
ft.commit();
}
mTabs.put(tag, info);
mTabHost.addTab(tabSpec);
}
#Override
public void onTabChanged(String tabId) {
TabInfo newTab = mTabs.get(tabId);
if (mLastTab != newTab) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
if (mLastTab != null) {
if (mLastTab.fragment != null) {
ft.detach(mLastTab.fragment);
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mActivity,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
ft.attach(newTab.fragment);
}
}
mLastTab = newTab;
ft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
private Intent createIntent( boolean aRight) {
Intent newIntent = new Intent(getIntent());
newIntent.putExtra(ResultActivity.IS_RIGHT_EAR, aRight);
newIntent.setClass(this, ResultActivity.class);
return newIntent;
}
}
So the activity used to show the results of each ear is the results activity:
public class ResultActivity extends SherlockFragmentActivity {
public static final String IS_RIGHT_EAR = "is_right_ear";
private ArrayList<EarSrt> leftAnswerList;
private ArrayList<EarSrt> rightAnswerList;
private boolean isRightEarTab = true;
private boolean bothEarsBad;
private boolean leftEarBad;
private boolean rightEarBad;
#SuppressWarnings("unchecked")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result);
Intent intent = getIntent();
int rowId = intent.getIntExtra(ResultsDatabase._ID, -1);
if ( rowId != -1 ) {
ResultsDatabase db = new ResultsDatabase(this);
String select = "(" + ResultsDatabase._ID + " == " + rowId + ")";
Cursor c = db.getReadableDatabase().query(ResultsDatabase.TABLE_NAME, null, select, null, null, null,null);
if ( c.moveToFirst() ) {
int leftEarColumn = c.getColumnIndex(ResultsDatabase.LEFT_EAR);
byte[] leftEarByteArray = c.getBlob(leftEarColumn);
int rightEarColumn = c.getColumnIndex(ResultsDatabase.RIGHT_EAR);
byte[] rightEarByteArray = c.getBlob(rightEarColumn);
leftAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(leftEarByteArray);
rightAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(rightEarByteArray);
}
} else {
byte[] leftEarByteArray = getIntent().getByteArrayExtra(ResultsDatabase.LEFT_EAR);
byte[] rightEarByteArray = getIntent().getByteArrayExtra(ResultsDatabase.RIGHT_EAR);
leftAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(leftEarByteArray);
rightAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(rightEarByteArray);
}
isRightEarTab = getIntent().getBooleanExtra(IS_RIGHT_EAR, true);
setResults(leftAnswerList, rightAnswerList);
if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
Fragment newFragment = new Results();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.resultsContainer, newFragment).commit();
}
}
private float calculateAverage(List<EarSrt> steps) {
float srt = 0.0f;
int length = steps.size();
for (int i = (int)Math.ceil( (float)length/(float)2); i < length; i++) {
EarSrt es = steps.get(i);
srt += es.getSrt();
//printf("%f ," , [es srt]);
}
srt = srt / (length-(float)Math.ceil( (float)length/(float)2));
// printf("\n%f\n" , srt);
return srt;
}
private void setResults(List<EarSrt> leftEar, List<EarSrt> rightEar) {
float esLeft = calculateAverage(leftEar);
float esRight = calculateAverage(rightEar);
leftEarBad = (esLeft > 24.0);
rightEarBad = (esRight > 24.0);
bothEarsBad = (leftEarBad && rightEarBad);
setResultCaption(bothEarsBad, leftEarBad, rightEarBad);
}
/**
* TODO: this needs finishing
*/
private void setResultCaption(boolean bothEarsBad, boolean leftEarBad, boolean rightEarBad) {
TextView resultsTextView = (TextView)findViewById(R.id.results_text);
StringBuilder resultsText = new StringBuilder();
if (bothEarsBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
}else{
if (leftEarBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss_for_your_left_ear));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
} else if (rightEarBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss_for_your_Right_ear));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
}else {
resultsText.append(getString(R.string.There_is_no_indication_of_hearing_loss));
}
}
resultsText.append(getString(R.string.The_results_of_the__hearing_test_are_not_to_be_utilized_as_an_official_outcome_for_assessing_levels_of_hearing_loss_True_hearing_loss_assessments_can_only_be_determined_by_a_licensed_hearing_healthcare_provider));
resultsTextView.setText(resultsText.toString());
}
public void goToLocate(View aView){
Intent locate = new Intent( this, MapActivity.class);
startActivity(locate);
finish();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
public static class Results extends SherlockFragment{
// #Override
// public void onCreate(Bundle savedInstanceState){
// super.onCreate(savedInstanceState);
//
// }
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.results_layout, container, false);
return rootView;
}
}
}
Now this class uses the GraphView class to draw the graph:
public final class GraphView extends View {
private static final float SCALE = 0.008f; // map (min,max) to ( 0, 1)
private static final float WIDTH = 0.02f; // map (min,max) to ( 0, 1)
ArrayList<EarSrt> mPoints;
// drawing tools
private RectF rimRect;
private RectF rimRectTop;
private RectF rimRectBottom;
private float[] centreLine;
private RectF topSideBar;
private RectF bottomSideBar;
private Paint rimPaintTop;
private Paint rimPaintBottom;
private Paint outerRimPaint;
private Paint centreLinePaint;
private Paint topSideBarPaint;
private Paint bottomSideBarPaint;
private Paint titlePaint;
private Paint keyPaint;
private Paint correctPointPaint;
private Paint incorrectPointPaint;
private Paint linePaint;
private Paint pointOutlinePaint;
private Paint averagePaint;
private Paint backgroundPaint;
// end drawing tools
private Bitmap background; // holds the cached static part
private float mAverage;
public GraphView(Context context) {
super(context);
init();
}
public GraphView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GraphView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
initDrawingTools();
}
private String getTitle() {
return getContext().getString(R.string.Normal_hearing);
}
private void initDrawingTools() {
rimRect = new RectF(0.0f, 0.0f, 1.0f, 1.0f);
rimRectTop = new RectF(0.0f, 0.5f, 1.0f, 1.0f);
rimRectBottom = new RectF(0.0f, 0.0f, 1.0f, 0.5f);
centreLine = new float[4];
centreLine[0]=0.0f;
centreLine[1]=0.5f;
centreLine[2]=1.0f;
centreLine[3]=0.5f;
topSideBar = new RectF(0.95f, 0.5f, 1.0f, 1.0f);
bottomSideBar = new RectF(0.95f, 0.0f, 1.0f, 0.5f);
// the linear gradient is a bit skewed for realism
rimPaintTop = new Paint();
rimPaintTop.setFlags(Paint.ANTI_ALIAS_FLAG);
rimPaintTop.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xff9ea3ac,
0xffc0c2c6,
TileMode.CLAMP));
rimPaintBottom = new Paint();
rimPaintBottom.setFlags(Paint.ANTI_ALIAS_FLAG);
rimPaintBottom.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xffc5cbbd,
0xff3d4649,
TileMode.CLAMP));
outerRimPaint = new Paint();
outerRimPaint.setAntiAlias(true);
outerRimPaint.setStyle(Paint.Style.STROKE);
outerRimPaint.setColor(Color.argb(0x4f, 0x33, 0x36, 0x33));
outerRimPaint.setStrokeWidth(0.001f);
centreLinePaint = new Paint();
centreLinePaint.setStyle(Paint.Style.STROKE);
centreLinePaint.setColor(0xff90cc38);
centreLinePaint.setAntiAlias(true);
centreLinePaint.setStrokeWidth(0.02f);
topSideBarPaint = new Paint();
topSideBarPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
topSideBarPaint.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xffc5cbbd,
0xff3d4649,
TileMode.CLAMP));
bottomSideBarPaint = new Paint();
bottomSideBarPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
bottomSideBarPaint.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xff4c9b3e,
0xffa0dd61,
TileMode.CLAMP));
titlePaint = new Paint();
titlePaint.setColor(0xffffffff);
titlePaint.setAntiAlias(true);
titlePaint.setTypeface(Typeface.DEFAULT_BOLD);
titlePaint.setTextAlign(Paint.Align.CENTER);
titlePaint.setTextSize(0.05f);
titlePaint.setTextScaleX(0.8f);
keyPaint = new Paint();
keyPaint.setColor(0xff000000);
keyPaint.setAntiAlias(true);
keyPaint.setTypeface(Typeface.DEFAULT_BOLD);
keyPaint.setTextAlign(Paint.Align.LEFT);
keyPaint.setTextSize(0.05f);
keyPaint.setTextScaleX(0.8f);
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
linePaint = new Paint();
linePaint.setColor(0xffffffff);
linePaint.setStrokeWidth(0);
averagePaint = new Paint();
averagePaint.setColor(0xff000000);
averagePaint.setStyle(Paint.Style.FILL);
correctPointPaint = new Paint();
correctPointPaint.setColor(0xff90cc38);
correctPointPaint.setStyle(Paint.Style.FILL);
incorrectPointPaint = new Paint();
incorrectPointPaint.setColor(0xffb1b3ba);
correctPointPaint.setStyle(Paint.Style.FILL);
pointOutlinePaint = new Paint();
pointOutlinePaint.setStyle(Paint.Style.STROKE);
pointOutlinePaint.setColor(0xffffffff);
pointOutlinePaint.setAntiAlias(true);
pointOutlinePaint.setStrokeWidth(0.0f);
}
private void drawRim(Canvas canvas) {
// first, draw the metallic body
canvas.drawRect(rimRectTop, rimPaintTop);
canvas.drawRect(rimRectBottom, rimPaintBottom);
// now the outer rim circle
canvas.drawRect(rimRect, outerRimPaint);
// Draw middleline
canvas.drawLines(centreLine, centreLinePaint);
// Draw sidebars
canvas.drawRect(topSideBar, topSideBarPaint);
canvas.drawRect(bottomSideBar, bottomSideBarPaint);
}
public void setPoints( ArrayList<EarSrt> aPoints){
mPoints = aPoints;
}
private void drawTitle(Canvas canvas) {
String title = getTitle();
canvas.drawText(title, 0.2f, 0.1f, titlePaint);
}
private void drawBackground(Canvas canvas) {
if (background == null) {
} else {
canvas.drawBitmap(background, 0, 0, backgroundPaint);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = (int)(width * 0.8f);
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas);
canvas.restore();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
regenerateBackground();
}
private void regenerateBackground() {
// free the old bitmap
if (background != null) {
background.recycle();
}
background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas backgroundCanvas = new Canvas(background);
float scaleWidth = (float) getWidth();
float scaleHeight = (float) getHeight();
backgroundCanvas.scale(scaleWidth, scaleHeight/1.23f);
drawRim(backgroundCanvas);
drawTitle(backgroundCanvas);
drawPoints(backgroundCanvas);
drawKey(backgroundCanvas);
}
private void drawPoints(Canvas canvas) {
float gap = 1.0f/((float)mPoints.size()+2);
// Iterate though the points twice, once to
// draw the line and one to draw the points
// doesn't appear to be the most efficient
// method, but calculations of point size etc
// Draw line
int count = 1;
float prev_x = 0.0f;
float prev_y = 0.0f;
for ( EarSrt vo : mPoints){
float y_pos = 0.5f + 2*( vo.getSrt() - 24.0f)*SCALE;
float x_pos = gap*count;
if ( count != 1 ){
canvas.drawLine(prev_x, prev_y, x_pos, y_pos, linePaint);
}
count++;
prev_x = x_pos;
prev_y = y_pos;
}
// draw points
count = 1;
for ( EarSrt vo : mPoints){
float y_pos = 0.5f + 2*( vo.getSrt() - 24.0f)*SCALE;
float x_pos = gap*count;
count++;
RectF rect = new RectF(x_pos - WIDTH, y_pos - WIDTH, x_pos + WIDTH, y_pos + WIDTH);
if ( vo.isCorrect() ) {
canvas.drawRect(rect, correctPointPaint);
} else {
canvas.drawRect(rect, incorrectPointPaint);
}
canvas.drawRect(rect, pointOutlinePaint);
}
// Plot average line
float yAverage = 0.5f + 2*( mAverage - 24.0f)*SCALE;
RectF averageRect = new RectF(0.95f, yAverage - WIDTH/2.0f, 1.0f, yAverage + WIDTH/2.0f);
canvas.drawRect(averageRect, averagePaint);
}
private void drawKey(Canvas canvas) {
float rightEdge = 0.05f;
float leftEdge = 0.05f + 4 * WIDTH;
// Example correct square
RectF rect = new RectF(rightEdge, 1.1f - WIDTH, rightEdge + 2 * WIDTH, 1.1f + WIDTH);
canvas.drawRect(rect, correctPointPaint);
canvas.drawRect(rect, pointOutlinePaint);
String correctResults = getContext().getString(R.string.Correct_results);
canvas.drawText(correctResults, leftEdge, 1.1f + WIDTH, keyPaint);
// Test result line
RectF averageRect = new RectF(rightEdge, 1.2f - WIDTH/2.0f, rightEdge + 2 * WIDTH, 1.2f + WIDTH/2.0f);
canvas.drawRect(averageRect, averagePaint);
String testResults = getContext().getString(R.string.Your_test_result);
canvas.drawText(testResults, leftEdge, 1.2f + WIDTH/2.0f, keyPaint);
}
public void setAverage(float aAverage) {
mAverage = aAverage;
}
}
the issues I'm getting are on the GraphView class in the drawPoints, regenerateBackground and onSizeChanged methods.
Another issue I have is showing the correct information in the correct tab. So for one tab it only shows the results from the left are and vice versa. Any help on these issues would be massively grateful as I've been trying to get this to work for ages!!
Thanks again for any help thats given.
Related
What is the VINTF manifest in android studio? Have an error
2020-04-22 16:14:49.759 1809-1809/? E/servicemanager: Could not find android.hardware.power.IPower/default in the VINTF manifest. This keeps popping up. Am coding a camera, that when a button is clicked, an image is cropped. Here is a custom view I am adding to a fragment. public class DrawView extends View { Point[] points = new Point[4]; /** * point1 and point 3 are of same group and same as point 2 and point4 */ int groupId = -1; private ArrayList<ColorBall> colorballs = new ArrayList<>(); private int mStrokeColor = Color.parseColor("#AADB1255"); private int mFillColor = Color.parseColor("#55DB1255"); private Rect mCropRect = new Rect(); // array that holds the balls private int balID = 0; // variable to know what ball is being dragged Paint paint; public DrawView(Context context) { this(context, null); } public DrawView(Context context, AttributeSet attrs) { this(context, attrs, -1); } public DrawView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { paint = new Paint(); setFocusable(true); // necessary for getting the touch events } private void initRectangle(int X, int Y) { //initialize rectangle. points[0] = new Point(); points[0].x = X - 200; points[0].y = Y - 100; points[1] = new Point(); points[1].x = X; points[1].y = Y + 30; points[2] = new Point(); points[2].x = X + 30; points[2].y = Y + 30; points[3] = new Point(); points[3].x = X + 30; points[3].y = Y; balID = 2; groupId = 1; // declare each ball with the ColorBall class for (int i = 0; i < points.length; i++) { colorballs.add(new ColorBall(getContext(), R.drawable.gray_circle, points[i], i)); } } // the method that draws the balls #Override protected void onDraw(Canvas canvas) { if(points[3]==null) { //point4 null when view first create initRectangle(getWidth() / 2, getHeight() / 2); } int left, top, right, bottom; left = points[0].x; top = points[0].y; right = points[0].x; bottom = points[0].y; for (int i = 1; i < points.length; i++) { left = left > points[i].x ? points[i].x : left; top = top > points[i].y ? points[i].y : top; right = right < points[i].x ? points[i].x : right; bottom = bottom < points[i].y ? points[i].y : bottom; } paint.setAntiAlias(true); paint.setDither(true); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeWidth(5); //draw stroke paint.setStyle(Paint.Style.STROKE); paint.setColor(mStrokeColor); paint.setStrokeWidth(2); mCropRect.left = left + colorballs.get(0).getWidthOfBall() / 2; mCropRect.top = top + colorballs.get(0).getWidthOfBall() / 2; mCropRect.right = right + colorballs.get(2).getWidthOfBall() / 2; mCropRect.bottom = bottom + colorballs.get(3).getWidthOfBall() / 2; canvas.drawRect(mCropRect, paint); //fill the rectangle paint.setStyle(Paint.Style.FILL); paint.setColor(mFillColor); paint.setStrokeWidth(0); canvas.drawRect(mCropRect, paint); // draw the balls on the canvas paint.setColor(Color.RED); paint.setTextSize(18); paint.setStrokeWidth(0); for (int i =0; i < colorballs.size(); i ++) { ColorBall ball = colorballs.get(i); canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(), paint); canvas.drawText("" + (i+1), ball.getX(), ball.getY(), paint); } } // events when touching the screen public boolean onTouchEvent(MotionEvent event) { int eventAction = event.getAction(); int X = (int) event.getX(); int Y = (int) event.getY(); switch (eventAction) { case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on // a ball if (points[0] == null) { initRectangle(X, Y); } else { //resize rectangle balID = -1; groupId = -1; for (int i = colorballs.size()-1; i>=0; i--) { ColorBall ball = colorballs.get(i); // check if inside the bounds of the ball (circle) // get the center for the ball int centerX = ball.getX() + ball.getWidthOfBall(); int centerY = ball.getY() + ball.getHeightOfBall(); paint.setColor(Color.CYAN); // calculate the radius from the touch to the center of the // ball double radCircle = Math .sqrt((double) (((centerX - X) * (centerX - X)) + (centerY - Y) * (centerY - Y))); if (radCircle < ball.getWidthOfBall()) { balID = ball.getID(); if (balID == 1 || balID == 3) { groupId = 2; } else { groupId = 1; } invalidate(); break; } invalidate(); } } break; case MotionEvent.ACTION_MOVE: // touch drag with the ball if (balID > -1) { // move the balls the same as the finger colorballs.get(balID).setX(X); colorballs.get(balID).setY(Y); paint.setColor(Color.CYAN); if (groupId == 1) { colorballs.get(1).setX(colorballs.get(0).getX()); colorballs.get(1).setY(colorballs.get(2).getY()); colorballs.get(3).setX(colorballs.get(2).getX()); colorballs.get(3).setY(colorballs.get(0).getY()); } else { colorballs.get(0).setX(colorballs.get(1).getX()); colorballs.get(0).setY(colorballs.get(3).getY()); colorballs.get(2).setX(colorballs.get(3).getX()); colorballs.get(2).setY(colorballs.get(1).getY()); } invalidate(); } break; case MotionEvent.ACTION_UP: // touch drop - just do things here after dropping break; } // redraw the canvas invalidate(); return true; } public Drawable doTheCrop(Bitmap sourceBitmap) throws IOException { //Bitmap sourceBitmap = null; //Drawable backgroundDrawable = getBackground(); /* if (backgroundDrawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable; if(bitmapDrawable.getBitmap() != null) { sourceBitmap = bitmapDrawable.getBitmap(); } }*/ //source bitmap was scaled, you should calculate the rate float widthRate = ((float) sourceBitmap.getWidth()) / getWidth(); float heightRate = ((float) sourceBitmap.getHeight()) / getHeight(); //crop the source bitmap with rate value int left = (int) (mCropRect.left * widthRate); int top = (int) (mCropRect.top * heightRate); int right = (int) (mCropRect.right * widthRate); int bottom = (int) (mCropRect.bottom * heightRate); Bitmap croppedBitmap = Bitmap.createBitmap(sourceBitmap, left, top, right - left, bottom - top); Drawable drawable = new BitmapDrawable(getResources(), croppedBitmap); return drawable; /* setContentView(R.layout.fragment_dashboard); Button btn = (Button)findViewById(R.id.capture); if (btn == null){ System.out.println("NULL"); } try{ btn.setText("HI"); } catch (Exception e){ } //setBackground(drawable);*/ //savebitmap(croppedBitmap); } private File savebitmap(Bitmap bmp) throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 60, bytes); File f = new File(Environment.getExternalStorageDirectory() + "/" + "testimage.jpg"); Toast.makeText(getContext(), "YUP", Toast.LENGTH_LONG).show(); f.createNewFile(); FileOutputStream fo = new FileOutputStream(f); fo.write(bytes.toByteArray()); fo.close(); return f; } public static class ColorBall { Bitmap bitmap; Context mContext; Point point; int id; public ColorBall(Context context, int resourceId, Point point, int id) { this.id = id; bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId); mContext = context; this.point = point; } public int getWidthOfBall() { return bitmap.getWidth(); } public int getHeightOfBall() { return bitmap.getHeight(); } public Bitmap getBitmap() { return bitmap; } public int getX() { return point.x; } public int getY() { return point.y; } public int getID() { return id; } public void setX(int x) { point.x = x; } public void setY(int y) { point.y = y; } } } Here is the fragment that I have added a camera do, basically the main part of the application that I am working on. public class DashboardFragment extends Fragment { private DashboardViewModel dashboardViewModel; //All my constants private DrawView mDrawView; private Drawable imgDraw; private TextureView txtView; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static{ ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 180); } private String cameraID; private String pathway; CameraDevice cameraDevice; CameraCaptureSession cameraCaptureSession; CaptureRequest captureRequest; CaptureRequest.Builder captureRequestBuilder; private Size imageDimensions; private ImageReader imageReader; private File file; Handler mBackgroundHandler; HandlerThread mBackgroundThread; public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { dashboardViewModel = ViewModelProviders.of(this).get(DashboardViewModel.class); View root = inflater.inflate(R.layout.fragment_dashboard, container, false); try{ txtView = (TextureView)root.findViewById(R.id.textureView); txtView.setSurfaceTextureListener(textureListener); mDrawView = root.findViewById(draw_view); Button cap = (Button)root.findViewById(R.id.capture); cap.setClickable(true); cap.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { try { Log.i("HOLA","HOLA"); takePicture(); } catch (CameraAccessException e) { e.printStackTrace(); } } }); } catch (Exception e){ Log.i("HI",e.toString()); } /* txtView = (TextureView)root.findViewById(R.id.textureView); txtView.setSurfaceTextureListener(textureListener); mDrawView = root.findViewById(R.id.draw_view); Button cap = (Button)root.findViewById(R.id.capture); cap.setClickable(true); cap.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { try { Log.i("HOLA","HOLA"); takePicture(); } catch (CameraAccessException e) { e.printStackTrace(); } } });*/ return root; } #Override public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults){ if (requestCode == 101){ if (grantResults[0] == PackageManager.PERMISSION_DENIED){ Toast.makeText(getActivity().getApplicationContext(), "Permission is required",Toast.LENGTH_LONG); } } } TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() { #Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { try { openCamera(); } catch (CameraAccessException e) { e.printStackTrace(); } } #Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { } #Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; } #Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } }; private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { #Override public void onOpened(#NonNull CameraDevice camera) { cameraDevice = camera; try { createCameraPreview(); } catch (CameraAccessException e) { e.printStackTrace(); } } #Override public void onDisconnected(#NonNull CameraDevice cameraDevice) { cameraDevice.close(); } #Override public void onError(#NonNull CameraDevice cameraDevice, int i) { cameraDevice.close(); cameraDevice = null; } }; private void createCameraPreview() throws CameraAccessException { SurfaceTexture texture = txtView.getSurfaceTexture(); //? texture.setDefaultBufferSize(imageDimensions.getWidth(), imageDimensions.getHeight()); Surface surface = new Surface(texture); captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(surface); cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { #Override public void onConfigured(#NonNull CameraCaptureSession session) { if (cameraDevice == null){ return; } cameraCaptureSession = session; try { updatePreview(); } catch (CameraAccessException e) { e.printStackTrace(); } } #Override public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) { Toast.makeText(getActivity().getApplicationContext(), "CONFIGURATION", Toast.LENGTH_LONG); } }, null); } private void updatePreview() throws CameraAccessException { if (cameraDevice == null){ return; } captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler); } private void openCamera() throws CameraAccessException { CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE); cameraID = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); imageDimensions = map.getOutputSizes(SurfaceTexture.class)[0]; if (ActivityCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101); return; } manager.openCamera(cameraID, stateCallback, null); } private void takePicture() throws CameraAccessException { if (cameraDevice == null) { Log.i("NOt working", "hi"); return; } CameraManager manager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE); CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId()); Size[] jpegSizes = null; jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG); int width = 640; int height = 480; if (jpegSizes != null && jpegSizes.length > 0) { width = jpegSizes[0].getWidth(); height = jpegSizes[0].getHeight(); } final ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); List<Surface> outputSurfaces = new ArrayList<>(2); outputSurfaces.add(reader.getSurface()); outputSurfaces.add(new Surface(txtView.getSurfaceTexture())); final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); captureBuilder.addTarget(reader.getSurface()); captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); Long tsLong = System.currentTimeMillis() / 1000; String ts = tsLong.toString(); file = new File(Environment.getExternalStorageDirectory() + "/" + ts + ".jpg"); pathway = Environment.getExternalStorageDirectory() + "/" + ts + ".jpg"; //cameraDevice.close(); ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() { #Override public void onImageAvailable(ImageReader imageReader) { Image image = null; //image = reader.acquireLatestImage(); image = reader.acquireNextImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.capacity()]; buffer.get(bytes); Bitmap bitmap = BitmapFactory.decodeByteArray(bytes , 0, bytes.length); try { Drawable back = mDrawView.doTheCrop(bitmap); Button btn = (Button)getView().findViewById(R.id.capture); btn.setBackground(back); } catch (IOException e) { e.printStackTrace(); } /* try { save(bytes); } catch (IOException e) { e.printStackTrace(); } finally { if (image != null){ image.close(); } }*/ } }; reader.setOnImageAvailableListener(readerListener, mBackgroundHandler); final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback(){ #Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result){ super.onCaptureCompleted(session, request, result); try { createCameraPreview(); } catch (CameraAccessException e) { e.printStackTrace(); } } }; cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { #Override public void onConfigured(#NonNull CameraCaptureSession session) { try { session.capture(captureBuilder.build(), captureListener, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } #Override public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) { } }, mBackgroundHandler); } private void save (byte[] bytes) throws IOException { OutputStream outputStream = null; outputStream = new FileOutputStream(file); outputStream.write(bytes); Toast.makeText(getActivity().getApplicationContext(),pathway,Toast.LENGTH_LONG).show(); outputStream.close(); imgDraw = Drawable.createFromPath(pathway); //mDrawView.doTheCrop(imgDraw); } #Override public void onResume(){ super.onResume(); startBackgroundThread(); if (txtView.isAvailable()){ try { openCamera(); } catch (CameraAccessException e) { e.printStackTrace(); } } else{ txtView.setSurfaceTextureListener(textureListener); } } private void startBackgroundThread() { mBackgroundThread = new HandlerThread("Camera Background"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); } protected void stopBackgroundThread() throws InterruptedException{ mBackgroundThread.quitSafely(); mBackgroundThread.join(); mBackgroundThread = null; mBackgroundHandler = null; } #Override public void onPause(){ try { stopBackgroundThread(); } catch (InterruptedException e) { e.printStackTrace(); } super.onPause(); } } Here is the xml file for that fragment. <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.dashboard.DashboardFragment"> <TextureView android:id = "#+id/textureView" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.PeavlerDevelopment.OpinionMinion.ui.dashboard.DrawView android:id="#+id/draw_view" android:layout_width="match_parent" android:layout_height="match_parent"/> <Button android:id="#+id/capture" android:layout_width="100dp" android:layout_height="200dp" android:clickable="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent"></Button> </androidx.constraintlayout.widget.ConstraintLayout> The problem seems to lie somewhere in the doCrop method of the DrawView class. If there is anything else that would help make the problem more clear, let me know! I will gladly share the github repo with you. Thank you.
As you can see in Android Design Documenation the VINTF stands for Vendor Interface and its a Manifest structure to aggregate data form the device. That specific log means that your manifest is missing something like this: <hal> <name>android.hardware.power</name> <transport>hwbinder</transport> <version>1.1</version> <interface> <name>IPower</name> <instance>default</instance> </interface> </hal> which basically is hardware power information. I think it's not related to what you are trying to do, but I need more info than that log.
Paint with Java
So I need do one app in Android Studio like Paint I have this in Myview.Java. I obtain the coordinates but I can´t save and draw the segment. I tried with a Vector and I thing Vector is a solution, but isn´t working like I did public class MyView extends View { Paint paint = null; int figure; public MyView(Context context) { super(context); paint = new Paint(); figure = 0; } public MyView(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); figure = 0; } public MyView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint = new Paint(); figure = 0; } #Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int x = getWidth(); int y = getHeight(); int radius; radius = 100; paint.setStyle(Paint.Style.FILL); paint.setColor(Color.WHITE); canvas.drawPaint(paint); // Use Color.parseColor to define HTML colors paint.setColor(Color.parseColor("#CD5C5C")); if (figure == 1) canvas.drawCircle(x / 2, y / 2, radius, paint); } public void setfigure(int a) { this.figure = a; } } In MainActivity I have this code public class MainActivity extends AppCompatActivity { MyView v; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); v = findViewById(R.id.teste); } #Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); //String x1 = "" + x; TextView textView = (TextView) findViewById(R.id.testecord); TextView textView2 = (TextView) findViewById(R.id.testecord2); Ponto2D pinicial = new Ponto2D(Math.round(x), Math.round(y)); Ponto2D pfinal = new Ponto2D(Math.round(x), Math.round(y)); String x1 = "" + pinicial.x; String x2 = "" + pfinal.x; textView.setText(x1); textView2.setText(x2); int n = 4; // tamanho do vetor int v[] = new int[n]; // declaração e alocação de espaço para o vetor "v" int i; // índice ou posição // processando os "n" elementos do vetor "v" for (i = 0; i < n; i++) { v[i] = pinicial.x; // na i-ésima posição do vetor "v" armazena o valor da variável "i" } return true; } public void f(View vs) { v.setfigure(1); v.invalidate(); } } I need save the points who user click to draw one straight segment. I have the code of segment and of Point. public class Segmento_de_Reta { Ponto2D pinicial; Ponto2D pfinal; String cor; public Segmento_de_Reta(Ponto2D a, Ponto2D b) { pinicial = a; pfinal = b; }
How can I create an animation class to use in other activities in android?
I have this animation activity for falling images. It works perfectly. What I would like to is change this, so I can call something like, startImageFallAnimation(), in another activity, and have it show over the current activity. I'd hate to have to add all this code to every activity I want to use it in. I experimented for a few hours, with no luck. How can I accomplish this? import com.tmp.animation.R; public class FallAnimationActivity extends Activity { // 100 = lots falling / 1000 = less falling public int imageInterval = 100; private int[] LEAVES = { R.drawable.coin, R.drawable.starsm, //R.drawable.leaf_yellow, //R.drawable.leaf_other, }; private Rect mDisplaySize = new Rect(); private RelativeLayout mRootLayout; private ArrayList<View> mAllImageViews = new ArrayList<View>(); private float mScale; #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Display display = getWindowManager().getDefaultDisplay(); display.getRectSize(mDisplaySize); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); mScale = metrics.density; mRootLayout = (RelativeLayout) findViewById(R.id.main_layout); new Timer().schedule(new ExeTimerTask(), 0, imageInterval); } public void create() { setContentView(R.layout.main); Display display = getWindowManager().getDefaultDisplay(); display.getRectSize(mDisplaySize); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); mScale = metrics.density; mRootLayout = (RelativeLayout) findViewById(R.id.main_layout); new Timer().schedule(new ExeTimerTask(), 0, imageInterval); } public void startAnimation(final ImageView aniView) { aniView.setPivotX(aniView.getWidth()/2); aniView.setPivotY(aniView.getHeight()/2); long delay = new Random().nextInt(Constants.MAX_DELAY); final ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.setDuration(Constants.ANIM_DURATION); animator.setInterpolator(new AccelerateInterpolator()); animator.setStartDelay(delay); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int angle = 50 + (int)(Math.random() * 101); int movex = new Random().nextInt(mDisplaySize.right); #Override public void onAnimationUpdate(ValueAnimator animation) { float value = ((Float) (animation.getAnimatedValue())).floatValue(); aniView.setRotation(angle*value); aniView.setTranslationX((movex-40)*value); aniView.setTranslationY((mDisplaySize.bottom + (150*mScale))*value); } }); animator.start(); } private Handler mHandler = new Handler() { #Override public void handleMessage(Message msg) { super.handleMessage(msg); int viewId = new Random().nextInt(LEAVES.length); Drawable d = getResources().getDrawable(LEAVES[viewId]); LayoutInflater inflate = LayoutInflater.from(FallAnimationActivity.this); ImageView imageView = (ImageView) inflate.inflate(R.layout.ani_image_view, null); imageView.setImageDrawable(d); mRootLayout.addView(imageView); mAllImageViews.add(imageView); LayoutParams animationLayout = (LayoutParams) imageView.getLayoutParams(); animationLayout.setMargins(0, (int)(-150*mScale), 0, 0); animationLayout.width = (int) (60*mScale); animationLayout.height = (int) (60*mScale); startAnimation(imageView); } }; private class ExeTimerTask extends TimerTask { #Override public void run() { // we don't really use the message 'what' but we have to specify something. mHandler.sendEmptyMessage(Constants.EMPTY_MESSAGE_WHAT); } } } EDIT- After lots of work, this is the best I've got, but I cant solve passing context into the handler, or passing the layout into the first method. import com.tmp.animation.R; public class FallPop { private static final String TAG = FallPop.class.toString(); private static final FallPop INSTANCE = new FallPop(); private int[] LEAVES = { R.drawable.leaf_green, R.drawable.leaf_red, R.drawable.leaf_yellow, R.drawable.leaf_other, }; private Rect mDisplaySize = new Rect(); private RelativeLayout mRootLayout; private ArrayList<View> mAllImageViews = new ArrayList<View>(); private float mScale; private FallPop(){ } public static FallPop getInstance() { return INSTANCE; } public Context context; public Context context2; int count = 0; public void doAnim(Context context){ WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); display.getRectSize(mDisplaySize); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); mScale = metrics.density; // FIX!!! // mRootLayout = (RelativeLayout) findViewById(R.id.main_layout); new Timer().schedule(new ExeTimerTask(), 0, 200); } public void startAnimation(final ImageView aniView) { aniView.setPivotX(aniView.getWidth()/2); aniView.setPivotY(aniView.getHeight()/2); long delay = new Random().nextInt(Constants.MAX_DELAY); final ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.setDuration(Constants.ANIM_DURATION); animator.setInterpolator(new AccelerateInterpolator()); animator.setStartDelay(delay); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int angle = 50 + (int)(Math.random() * 101); int movex = new Random().nextInt(mDisplaySize.right); #Override public void onAnimationUpdate(ValueAnimator animation) { float value = ((Float) (animation.getAnimatedValue())).floatValue(); aniView.setRotation(angle*value); aniView.setTranslationX((movex-40)*value); aniView.setTranslationY((mDisplaySize.bottom + (150*mScale))*value); } }); animator.start(); } Handler mHandler = new Handler() { #Override public void handleMessage(Message msg) { super.handleMessage(msg); int viewId = new Random().nextInt(LEAVES.length); // Need some context here \/ Drawable d = ContextCompat.getDrawable(context, LEAVES[viewId]); // Original line, also didnt work \/ //Drawable d = getResources().getDrawable(LEAVES[viewId]); LayoutInflater inflate = LayoutInflater.from(context); ImageView imageView = (ImageView) inflate.inflate(R.layout.ani_image_view, null); imageView.setImageDrawable(d); mRootLayout.addView(imageView); mAllImageViews.add(imageView); RelativeLayout.LayoutParams animationLayout = (RelativeLayout.LayoutParams) imageView.getLayoutParams(); animationLayout.setMargins(0, (int) (-150 * mScale), 0, 0); animationLayout.width = (int) (60 * mScale); animationLayout.height = (int) (60 * mScale); startAnimation(imageView); } }; class ExeTimerTask extends TimerTask { #Override public void run() { // we don't really use the message 'what' but we have to specify something. mHandler.sendEmptyMessage(Constants.EMPTY_MESSAGE_WHAT); } } }
Create a Java class with static method startImageFallAnimation(),where you will write all your animation code and just call the method wherever it is required
The quickest solution I can think of would be to make the target Activities extend this class and change the access level of the member variables in FallAnimationActivity to 'protected'. Depending on whether you need this in all/most Activities, I'd put the logic in a base class.
have context as a parameter in your util class example: public animation(Imageview imageview, Context mContext) { Animation slideLeft = AnimationUtils.loadAnimation(mContext, R.anim.slide_out_left); imageview.startAnimation(slideLeft); } then in the activity you want to call it in do // for activity Utils.animation(Your image view, this) //for fragment Utils.animation(Your image view, getContext) my utility class is called Utils, so you type whatever you named the class and call the method accordingly
In Android change a Method from Void to Return?
I'm creating a game in which I'm drawing a path that starts at the center x,y coordinates of a RelativeLayout. I'm getting the x,y coordinates, but I can't figure out how to pass the coordinates into the Path Drawing Class using my getNumbers() method. I've got this bit in the onCreate: getNumbers(); path_em = new PathEM(this, xTint, yTint); gBoard_RL.addView(path_em); root_RL.addView(gBoard_RL); and here's getNumbers(): public void getNumbers() { gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener(NumbersoGLL); } OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() { #Override public void onGlobalLayout() { xRLWInt = gBoard_RL.getWidth() / 2; yRLHInt = gBoard_RL.getHeight() / 2; xTint = gBoard_RL.getLeft() + xRLWInt; yTint = gBoard_RL.getTop() + yRLHInt; } }; I think I have to rewrite getNumbers() so that's it's not void, but returns xTint and yTint, right? I don't know how to do that because public void onGlobalLayout() can't be changed to pass an int, when I try I get an error saying that it HAS to be void. So basically, what I'm trying to do is in the onCreate of Game3 Class I need to get the center coordinate integers, then pass them into my Path Drawing Class. Here's the entire Game 3 Class: public class Game3 extends Activity { PathEM path_em; RelativeLayout root_RL, gBoard_RL, startTimer_RL; LayoutParams root_LP, startTimer_LP, gBoardInfo_LP, gBoard_LP, rootStartTimer_LP; LayoutInflater LayInf = null; View root_VUE, gBoardInfo_VUE; TextView gameScore_TV, gameTime_TV, readyCD_TV; FrameLayout root_FrameL; int xScrInt, yScrInt, xRLWInt, yRLHInt, xTint, yTint; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); overridePendingTransition(R.anim.cutin, R.anim.cutout); // -- Create Root Layout root_RL = new RelativeLayout(this); root_LP = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); root_RL.setId(1); root_RL.setBackgroundColor(Color.WHITE); root_RL.setLayoutParams(root_LP); // --- END Create Root Layout // --- Create GameBoard LayInf = (LayoutInflater) getApplicationContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); gBoardInfo_VUE = LayInf.inflate(R.layout.game1_info, null); gBoardInfo_LP = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); gBoardInfo_LP.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE); gBoardInfo_VUE.setId(2); gBoardInfo_VUE.setLayoutParams(gBoardInfo_LP); gameTime_TV = (TextView) gBoardInfo_VUE .findViewById(R.id.game1_timeValue2_TV); gameScore_TV = (TextView) gBoardInfo_VUE .findViewById(R.id.game1_scoreValue2_TV); root_RL.addView(gBoardInfo_VUE); gBoard_RL = new RelativeLayout(this); gBoard_LP = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); gBoard_LP.addRule(RelativeLayout.BELOW, gBoardInfo_VUE.getId()); gBoard_LP.setMargins(10, 10, 10, 10); gBoard_RL.setLayoutParams(gBoard_LP); gBoard_RL.setBackgroundColor(Color.BLUE); //--- add stuff here getNumbers(); path_em = new PathEM(this, xTint, yTint); gBoard_RL.addView(path_em); root_RL.addView(gBoard_RL); root_FrameL = new FrameLayout(this); root_FrameL.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); root_FrameL.addView(root_RL); setContentView(root_FrameL); // --- END Create GameBoard }//--- END onCreate public void getNumbers() { gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener(NumbersoGLL); } OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() { #Override public void onGlobalLayout() { xRLWInt = gBoard_RL.getWidth() / 2; yRLHInt = gBoard_RL.getHeight() / 2; xTint = gBoard_RL.getLeft() + xRLWInt; yTint = gBoard_RL.getTop() + yRLHInt; } }; //--- PathEM Class public class PathEM extends View { Paint paint = new Paint(); Path path = new Path(); public PathEM(Context context, int xTint, int yTint){ super(context); } Pt[] thePath = { new Pt(xTint, yTint), new Pt(200, 200), new Pt(200, 500), new Pt(400, 500) }; #Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(Color.GREEN); paint.setStrokeWidth(7); paint.setStyle(Paint.Style.STROKE); path.moveTo(thePath[0].x, thePath[0].y); for (int i = 1; i < thePath.length; i++) { path.lineTo(thePath[i].x, thePath[i].y); } canvas.drawPath(path, paint); }// --- END onDraw class Pt { float x, y; Pt(float _x, float _y) { x = _x; y = _y; } } } }
You should put the code where you initialize the PathEM object in the onGlobalLayout() Method. Like this: OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() { #Override public void onGlobalLayout() { xRLWInt = gBoard_RL.getWidth() / 2; yRLHInt = gBoard_RL.getHeight() / 2; xTint = gBoard_RL.getLeft() + xRLWInt; yTint = gBoard_RL.getTop() + yRLHInt; path_em = new PathEM(this, xTint, yTint); gBoard_RL.addView(path_em); root_RL.addView(gBoard_RL); } };
How about creating a Constants Class and setting the variable of contants variable in your onGlobalLayout() method. That way you need not do any return. public class Constants { public static int value1=0; public static int value2=0; public static int value3=0; public static int value4=0; } In your onGlobalLayout() method Constants.value1= gBoard_RL.getWidth() / 2; Constants.value2= gBoard_RL.getHeight() / 2; Constants.value3= gBoard_RL.getLeft() + xRLWInt; Constants.value4= gBoard_RL.getTop() + yRLHInt;
In Android, when is an Interface called?
This is my first attempt at an Android game. I need to draw a path that starts at the center of the screen, and I'm getting the center screen coordinates using OnGlobalLayoutListener. In order to pass the center coordinates to my View class I'm using an Interface. Now, assuming that the Interface is working, it's passing 0,0 because the drawn path is starting at the upper left of my Relative Layout. I'm getting the correct coordinates because for now I'm passing them to a TextView so I can see the coordinates, but they're not getting passed to the View class because the path starts in the upper left, not the center of my Relative Layout. So I guess my question is: Does the Interface get triggered before onCreate completes? And if so, how can I get the center screen data to the Interface before the Interface is triggered? Can I somehow trigger the Interface after I get the screen data? Here are the classes I'm working with, first the Main Activity: public class Game1 extends Activity implements GBoardValueSetter { DrawPath dp; TextView gameScore_TV, gameTime_TV; private CountDownTimer mainGameCD; private boolean mainGameTimerHasStarted = false; private final long mainCDTime = 30 * 1000; private final long mainCDInterval = 1 * 1000; // ---GameBoard variables RelativeLayout root_RL, gBoardInfo_RL, gBoard_RL; LayoutInflater LayInf = null; View root_VUE, gBoardInfo_VUE; LayoutParams root_LP, gBoardInfo_LP, gBoard_LP; int xScr2Int, yScr2Int, xScrInt, yScrInt, xCenterInt, yCenterInt; String xCenterStr, yCenterStr, xHStr, yWStr; float xCenter_FL, yCenter_FL; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); overridePendingTransition(R.anim.cutin, R.anim.cutout); root_RL = new RelativeLayout(this); root_LP = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); root_RL.setId(1); root_RL.setBackgroundColor(Color.WHITE); root_RL.setLayoutParams(root_LP); setContentView(root_RL); createBlankGBoard(); addDP(); }// --- END onCreate //--- Interface call #Override public void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt) { xC_IInt = xCenterInt; yC_IInt = yCenterInt; dp.setCenterInt(xC_IInt, yC_IInt); }//--- END Interface call public void createBlankGBoard(){ LayInf = (LayoutInflater) getApplicationContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); gBoardInfo_VUE = LayInf.inflate(R.layout.game1_info, null); gBoardInfo_LP = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); gBoardInfo_LP.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE); gBoardInfo_VUE.setId(2); gBoardInfo_VUE.setLayoutParams(gBoardInfo_LP); gameTime_TV = (TextView) gBoardInfo_VUE.findViewById(R.id.game1_timeValue2_TV); gameScore_TV = (TextView) gBoardInfo_VUE.findViewById(R.id.game1_scoreValue2_TV); root_RL.addView(gBoardInfo_VUE); gBoard_RL = new RelativeLayout(this); gBoard_LP = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); gBoard_LP.addRule(RelativeLayout.BELOW, gBoardInfo_VUE.getId()); gBoard_LP.setMargins(10, 10, 10, 10); gBoard_RL.setLayoutParams(gBoard_LP); gBoard_RL.setBackgroundColor(Color.MAGENTA); root_RL.addView(gBoard_RL); getGameBoardNumbers(); } public void addDP(){ root_RL.removeView(gBoard_RL); dp = new DrawPath(this); gBoard_RL.setBackgroundColor(Color.CYAN); gBoard_RL.addView(dp); root_RL.addView(gBoard_RL); } //-- Get GameBoard info using oGLL public void getGameBoardNumbers(){ gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener( NumbersoGLL); } //-- oGLL OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() { #Override public void onGlobalLayout() { xScrInt = gBoard_RL.getWidth(); yScrInt = gBoard_RL.getHeight(); xScr2Int = gBoard_RL.getWidth()/2; yScr2Int = gBoard_RL.getHeight()/2; xCenterInt = gBoard_RL.getLeft() + xScr2Int; yCenterInt = gBoard_RL.getTop() + yScr2Int; xHStr = String.valueOf(xScrInt); yWStr = String.valueOf(yScrInt); xCenter_FL = (float)xCenterInt; yCenter_FL = (float)yCenterInt; String xCInt_Str = String.valueOf(xCenterInt); String yCInt_Str = String.valueOf(yCenterInt); gameScore_TV.setText(xCInt_Str + ", " + yCInt_Str); } }; } Here's the View Class: public class DrawPath extends View { Paint paint = new Paint(); Path path = new Path(); private int xC_Int, yC_Int; class Pt { float x, y; Pt(float _x, float _y) { x = _x; y = _y; } } public void setCenterInt(int xC_IInt, int yC_IInt){ this.xC_Int = xC_IInt; this.yC_Int = yC_IInt; } Pt[] thePath = { new Pt(xC_Int, yC_Int), new Pt(200, 200), new Pt(200, 500), new Pt(400, 500) }; public DrawPath(Context context) { super(context); } #Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(Color.RED); paint.setStrokeWidth(7); paint.setStyle(Paint.Style.STROKE); path.moveTo(thePath[0].x, thePath[0].y); for (int i = 1; i < thePath.length; i++) { path.lineTo(thePath[i].x, thePath[i].y); } canvas.drawPath(path, paint); } } And the Interface Class: public interface GBoardValueSetter { void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt); }
In your interface call to your activity, you assign the parameters you get from the call: public void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt) { xC_IInt = xCenterInt; <-- RIGHT THERE yC_IInt = yCenterInt; <-- RIGHT THERE dp.setCenterInt(xC_IInt, yC_IInt); }//--- END Interface call xCenterInt and yCenterInt are problably 0