I am designing a Canvas Drawable inside a layout. This is my code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="4"
android:layout_height="match_parent">
<com.sensennetworks.senanpr.ui.DrawPolygonCanvas
android:id="#+id/drawPolygonCanvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#000"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="onSave"
android:text="Save" />
<android.support.v4.widget.Space
android:layout_width="20dp"
android:layout_height="wrap_content" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="onReset"
android:text="Clear" />
</LinearLayout>
This layout file creates a custom drawable "DrawPolygonCanvas" which can be dragged, in the image below this is dragged out of bounds.
And, this creates a result like this....where the result goes out of boundary completely.
Now my question is how do I create a layout such that the "DrawPolygonCanvas" is strictly inside a layout and it does not go outside it's boundary into the black area with both the buttons.
// Debug helpers to draw lines between the two touch points
private HashMap<String, List<Vector2D>> polygons = new HashMap();
public DrawPolygonCanvas(Context context) {
super(context);
init(context);
}
public DrawPolygonCanvas(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawPolygonCanvas(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public DrawPolygonCanvas(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
Log.e(TAG, "called init");
this.context = context;
// Activity host = (Activity) getContext();
// Log.e(TAG, "called getContext");
// if (host.getIntent().hasExtra("byteArray")) {
// Log.e(TAG, "called hasExtra");
// byte[] byteArray = host.getIntent().getByteArrayExtra("byteArray");
//
//
// Bitmap bm = BitmapFactory.decodeByteArray(byteArray
// , 0, byteArray.length);
// ((GlobalApp) context.getApplicationContext()).setCurrentPreviewBitmap(bm);
// }
Log.e(TAG, "calling setOnTouchListener");
setOnTouchListener(this);
}
public void clearROI() {
Log.e(TAG, "called clearROI");
// Get ROI from the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
cameraROI = sharedPreferences.getString(SettingsActivity.ROI, AnprSettings.DEFAULT_CAMERA_ROI);
Log.e(TAG, "Reloaded ROI = " + cameraROI);
convertString2Polygons();
}
#Override
protected void onDraw(Canvas canvas) {
Log.e(TAG, "called onDraw");
super.onDraw(canvas);
if (!isInitialized) {
// Get ROI from the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
cameraROI = sharedPreferences.getString(SettingsActivity.ROI, AnprSettings.DEFAULT_CAMERA_ROI);
if (cameraROI.isEmpty()) {
cameraROI = AnprSettings.DEFAULT_CAMERA_ROI;
}
convertString2Polygons();
circlePaint = new Paint();
circlePaint.setColor(0xFFFF0000);
linePaint = new Paint();
linePaint.setColor(0xFF00FF00);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeWidth(10);
isInitialized = true;
}
Rect dest = new Rect(0, 0, getWidth(), getHeight());
Paint paint = new Paint();
paint.setFilterBitmap(true);
// get
Bitmap bm = ((GlobalApp) this.context.getApplicationContext()).getCurrentPreviewBitmap();
canvas.drawBitmap(bm, null, dest, paint);
try {
for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {
List<Vector2D> polygon = entry.getValue();
for (int i = 0; i < polygon.size() - 1; i++) {
canvas.drawLine(polygon.get(i).getX(), polygon.get(i).getY(), polygon.get(i + 1).getX(), polygon.get(i + 1).getY(), linePaint);
}
canvas.drawLine(polygon.get(polygon.size() - 1).getX(), polygon.get(polygon.size() - 1).getY(), polygon.get(0).getX(), polygon.get(0).getY(), linePaint);
for (int i = 0; i < polygon.size(); i++) {
canvas.drawCircle(polygon.get(i).getX(), polygon.get(i).getY(), 40, circlePaint);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
#Override
public void onDetachedFromWindow() {
Log.e(TAG, "called onDetachedFromWindow");
super.onDetachedFromWindow();
// Convert polygon back to string.
convertPolygons2String();
// SharedPreferences.Editor editor = UserSharedPref.initializeSharedPreferencesForCameraROI(context).edit();
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
editor.putString(SettingsActivity.ROI, cameraROI);
editor.apply();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.e(TAG, "called onTouch");
canvasTouchManager.update(event);
Vector2D vct = canvasTouchManager.getPoint();
float minDist = 200000.0f;
float radius = 200;
int minIndex = -1;
String key = "";
for (Map.Entry<String, List<Vector2D>> entry : polygons.entrySet()) {
List<Vector2D> points = entry.getValue();
for (int i = 0; i < points.size(); i++) {
float dist = points.get(i) == null ? 0 : Vector2D.subtract(vct, points.get(i)).getLength();
if (dist >= radius) {
continue;
}
if (dist < minDist) {
minDist = dist;
minIndex = i;
Log.e(TAG, "Matching x = " + points.get(i).getX() + ", y = " + points.get(i).getY());
key = entry.getKey();
}
}
}
if (minIndex != -1 && !key.isEmpty()) {
polygons.get(key).set(minIndex, vct);
} else {
Log.e("OK2", "Touch point is too far, dist = " + minDist);
}
invalidate();
return true;
}
}
Related
I am new to learning android, and I am writing a program to show a point and its position(coordination) on the screen.
I use TextView to show the coordinates, and using CustomView to draw the point out.
Here is my xml.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="#+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/tv_pointX"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="X : "
android:textSize="24sp" />
<TextView
android:id="#+id/tv_pointY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="Y : "
android:textSize="24sp" />
</LinearLayout>
<com.example.pointnsendmsgtest3.svPaintCircle
android:id="#+id/TouchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp">
</com.example.pointnsendmsgtest3.svPaintCircle>
</LinearLayout>
</RelativeLayout>
And my main activity of the code. I am just wondering that how can I display all the views in one screen.
There is only one view can be displayed on the screen, base on the last setContentView command shows in my script to the compiler.
public class MainActivity extends Activity{
private TextView tv_pointx;
private TextView tv_pointy;
private LinearLayout panel_touch;
private svPaintCircle m_view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
m_view = new svPaintCircle(this);
m_view.setOnTouchListener(new MyListener());
setContentView(m_view);
setContentView(R.layout.activity_main);
}
public class MyListener implements View.OnTouchListener {
public boolean onTouch(View v, MotionEvent event){
testpoint(event);
return true;
}
private void testpoint(MotionEvent event){
if(!debugOn){
return;
}
//initialize mXs and mYs
ArrayList<Float> mXs = null;
ArrayList<Float> mYs = null;
if (mXs == null && mYs == null){
mXs = new ArrayList<Float>();
mYs = new ArrayList<Float>();
}
mXs.clear();
mYs.clear();
final int N = event.getPointerCount();
float x,y;
for(int i = 0; i < N; i++){
x = event.getX(event.getPointerId(i));
y = event.getY(event.getPointerId(i));
logd("x[" + i + "],y[" + i + "] = " + x + "," + y);
mXs.add(x);
mYs.add(y);
}
if(N > 0)m_view.setPoints(mXs,mYs);
}
}
private final boolean debugOn = true;
private final String TAG = "MyListener";
private int logd(String msg) {
int retVal = 0;
if (debugOn) {
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
Here is the class how to draw the point immediately.
public class svPaintCircle extends android.support.v7.widget.AppCompatImageView {
public svPaintCircle(Context context){
super(context);
}
public svPaintCircle(Context context, AttributeSet attrs) {super(context, attrs);}
public svPaintCircle(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
drawTouchPoint(canvas);
}
ArrayList<Float> mXs = null, mYs = null;
private boolean mDrawn = true;
private Paint mPointPaint = null;
private Paint mRectPaint = null;
private Paint mTextPaint = null;
public void setPoints(ArrayList<Float> mXs, ArrayList<Float> mYs){
if(debugOn) {
if(mPointPaint == null) {
mPointPaint = new Paint();
mPointPaint.setAntiAlias(false);
mPointPaint.setARGB(255,0,96,255);
mRectPaint = new Paint();
mRectPaint.setARGB(0x88,0x44,0x44,0x44); // 0x88 = 136 , 0x44 = 68
mTextPaint = new Paint();
mTextPaint.setTextSize(45);
mTextPaint.setARGB(0xff,0xff,0xff,0xff);
logd("init Paint");
}
this.mXs = mXs;
this.mYs = mYs;
mDrawn = false;
invalidate();
}
}
public void drawTouchPoint(Canvas canvas){
if(debugOn){
if(!mDrawn){
float x,y,rx,ry;
float dx = 80, dy = 80, r = 10;
for(int i = 0; i < mXs.size(); i++){
x = mXs.get(i);
y = mYs.get(i);
//draw cross
//canvas.drawLine(x, y - dy, x, y+dy, mPointPaint);
//canvas.drawLine(x - dx, y, x+dx ,y, mPointPaint);
canvas.drawCircle(x,y,r, mPointPaint);
rx = x;
ry = y - 40;
if(x + 75 > getRight())
rx = x -76;
if(ry < getTop())
ry = y + 20;
canvas.drawRect(0, 0, 320, 45, mRectPaint);
canvas.drawText("x: " + (int)x + " , y:" + (int)y, 0,35, mTextPaint);
}
mDrawn = true;
}
}
}
private final boolean debugOn = true;
private final String TAG = "PointView";
private int logd(String msg){
int retVal = 0;
if(debugOn){
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
How can I make both TextView and CustomView shows together?
no, you can't. setContentView can only be done for one layout.
To add some value to my answer, I would assume your understanding of setContentView is a bit wrong. setContentView is how you tell android which layout file to associate with this activity (as per your example). that's how layouts with different components are done, it's one single file with multiple or different views inside one file (or being referenced from this file, with methods such as include in xml).
From the documentation:
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
https://developer.android.com/reference/android/app/Activity.html#setContentView(int)
I'm using Android Studio.
only works on Android 9
not working on Android 8 and 7
The issue is from the use of #SuppressLint("AppCompatCustomView") // we don't need to support older versions in BRButton.java
how to get this to support older versions ?
E/FirebaseCrash: Firebase Crash Reporting not enabled
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.loafwallet, PID: 6085
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.loafwallet/com.breadwallet.presenter.activities.intro.IntroActivity}: android.view.InflateException: Binary XML file line #23: Binary XML file line #23: Error inflating class com.breadwallet.presenter.customviews.BRButton
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: android.view.InflateException: Binary XML file line #23: Binary XML file line #23: Error inflating class com.breadwallet.presenter.customviews.BRButton
Caused by: android.view.InflateException: Binary XML file line #23: Error inflating class com.breadwallet.presenter.customviews.BRButton
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:414)
at android.app.Activity.setContentView(Activity.java:2414)
at com.breadwallet.presenter.activities.intro.IntroActivity.onCreate(IntroActivity.java:84)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.RuntimeException: Font asset not found fonts/CircularPro-Medium.otf
at android.graphics.Typeface.createFromAsset(Typeface.java:206)
at com.breadwallet.tools.manager.FontManager.get(FontManager.java:55)
at com.breadwallet.tools.manager.FontManager.setCustomFont(FontManager.java:67)
at com.breadwallet.presenter.customviews.BRButton.init(BRButton.java:100)
at com.breadwallet.presenter.customviews.BRButton.(BRButton.java:79)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:414)
at android.app.Activity.setContentView(Activity.java:2414)
at com.breadwallet.presenter.activities.intro.IntroActivity.onCreate(IntroActivity.java:84)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
E/FirebaseInstanceId: Token retrieval failed: SERVICE_NOT_AVAILABLE
E/FirebaseInstanceId: Token retrieval failed: SERVICE_NOT_AVAILABLE
E/FirebaseInstanceId: Token retrieval failed: SERVICE_NOT_AVAILABLE
Application terminated.
IntroActivity.xml
<ImageView
android:id="#+id/BRText"
android:layout_width="128dp"
android:layout_height="64dp"
android:layout_marginTop="96dp"
android:src="#drawable/ctlx_logo"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"/>
<com.breadwallet.presenter.customviews.BRButton
android:id="#+id/button_new_wallet"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="#dimen/bread_margin"
android:layout_marginStart="#dimen/bread_margin"
app:buttonType="1"
android:padding="10dp"
android:text="#string/MenuViewController.createButton"
android:textColor="#color/white"
android:background="#android:color/transparent"
android:textSize="18sp"
app:isBreadButton="true"
app:layout_constraintBottom_toTopOf="#+id/button_recover_wallet"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<com.breadwallet.presenter.customviews.BRButton
android:id="#+id/button_recover_wallet"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_marginBottom="32dp"
android:background="#android:color/transparent"
android:layout_marginEnd="#dimen/bread_margin"
android:layout_marginStart="#dimen/bread_margin"
app:buttonType="2"
android:padding="10dp"
android:text="#string/RecoverWallet.header"
android:textColor="#color/button_secondary_text"
android:textSize="18sp"
app:isBreadButton="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<com.breadwallet.presenter.customviews.BRText
android:id="#+id/textView7"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:lineSpacingMultiplier="1.3"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="#dimen/bread_margin"
android:text="#string/StartViewController.message"
android:textAlignment="center"
android:textColor="#color/white"
android:textSize="#dimen/header"
app:customTFont="CircularPro-Book.otf"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/BRText"/>
<ImageButton
android:id="#+id/faq_button"
android:layout_width="#dimen/faq_dimen"
android:layout_height="#dimen/faq_dimen"
android:layout_marginEnd="#dimen/bread_margin"
android:layout_marginTop="#dimen/bread_margin"
android:background="#drawable/faq_question_white"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<View
android:id="#+id/splash_screen"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:background="#drawable/bread_gradient"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"/>
IntroActivity.java
public static final Point screenParametersPoint = new Point();
#Override
protected void onRestart() {
super.onRestart(); // Always call the superclass method first
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intro);
newWalletButton = (Button) findViewById(R.id.button_new_wallet);
recoverWalletButton = (Button) findViewById(R.id.button_recover_wallet);
splashScreen = findViewById(R.id.splash_screen);
setListeners();
updateBundles();
faq = (ImageButton) findViewById(R.id.faq_button);
faq.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!BRAnimator.isClickAllowed()) return;
BRAnimator.showSupportFragment(app, BRConstants.startView);
}
});
if (!BuildConfig.DEBUG && BRKeyStore.AUTH_DURATION_SEC != 300) {
Log.e(TAG, "onCreate: BRKeyStore.AUTH_DURATION_SEC != 300");
BRReportsManager.reportBug(new RuntimeException("AUTH_DURATION_SEC should be 300"), true);
}
introActivity = this;
getWindowManager().getDefaultDisplay().getSize(screenParametersPoint);
if (Utils.isEmulatorOrDebug(this))
Utils.printPhoneSpecs();
byte[] masterPubKey = BRKeyStore.getMasterPublicKey(this);
boolean isFirstAddressCorrect = false;
if (masterPubKey != null && masterPubKey.length != 0) {
isFirstAddressCorrect = SmartValidator.checkFirstAddress(this, masterPubKey);
}
if (!isFirstAddressCorrect) {
BRWalletManager.getInstance().wipeWalletButKeystore(this);
}
PostAuth.getInstance().onCanaryCheck(this, false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
splashScreen.setVisibility(View.GONE);
}
}, 1000);
}
private void updateBundles() {
BRExecutor.getInstance().forBackgroundTasks().execute(new Runnable() {
#Override
public void run() {
Thread.currentThread().setName("updateBundle");
final long startTime = System.currentTimeMillis();
APIClient apiClient = APIClient.getInstance(IntroActivity.this);
apiClient.updateBundle();
long endTime = System.currentTimeMillis();
Log.d(TAG, "updateBundle DONE in " + (endTime - startTime) + "ms");
}
});
}
private void setListeners() {
newWalletButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!BRAnimator.isClickAllowed()) return;
BreadActivity bApp = BreadActivity.getApp();
if (bApp != null) bApp.finish();
Intent intent = new Intent(IntroActivity.this, SetPinActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_from_right, R.anim.exit_to_left);
}
});
recoverWalletButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!BRAnimator.isClickAllowed()) return;
BreadActivity bApp = BreadActivity.getApp();
if (bApp != null) bApp.finish();
Intent intent = new Intent(IntroActivity.this, RecoverActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_from_right, R.anim.exit_to_left);
}
});
}
#Override
protected void onResume() {
super.onResume();
appVisible = true;
app = this;
}
#Override
protected void onPause() {
super.onPause();
appVisible = false;
}
#Override
protected void onSaveInstanceState(Bundle outState) {
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
}
BRButton.java
#SuppressLint("AppCompatCustomView")
public class BRButton extends Button {
private static final String TAG = BRButton.class.getName();
private static int ANIMATION_DURATION = 30;
private Bitmap shadow;
private Rect shadowRect;
private RectF bRect;
private int width;
private int height;
private int modifiedWidth;
private int modifiedHeight;
private Paint bPaint;
private Paint bPaintStroke;
private int type = 2;
private static final float SHADOW_PRESSED = 0.88f;
private static final float SHADOW_UNPRESSED = 0.95f;
private float shadowOffSet = SHADOW_UNPRESSED;
private static final int ROUND_PIXELS = 16;
private boolean isBreadButton;
public BRButton(Context context) {
super(context);
init(context, null);
}
public BRButton(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public BRButton(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public BRButton(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context ctx, AttributeSet attrs) {
shadow = BitmapFactory.decodeResource(getResources(), R.drawable.shadow);
bPaint = new Paint();
bPaintStroke = new Paint();
shadowRect = new Rect(0, 0, 100, 100);
bRect = new RectF(0, 0, 100, 100);
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.BRButton);
String customFont = a.getString(R.styleable.BRButton_customBFont);
FontManager.setCustomFont(ctx, this, Utils.isNullOrEmpty(customFont) ? "CircularPro-Medium.otf" : customFont);
float px16 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());
//check attributes you need, for example all paddings
int[] attributes = new int[]{android.R.attr.paddingStart, android.R.attr.paddingTop, android.R.attr.paddingEnd, android.R.attr.paddingBottom, R.attr.isBreadButton, R.attr.buttonType};
TypedArray arr = ctx.obtainStyledAttributes(attrs, attributes);
isBreadButton = a.getBoolean(R.styleable.BRButton_isBreadButton, false);
int paddingLeft = arr.hasValue(0) ? arr.getDimensionPixelOffset(0, -1) : (int) px16;
int paddingTop = arr.hasValue(1) ? arr.getDimensionPixelOffset(1, -1) : 0;
int paddingRight = arr.hasValue(2) ? arr.getDimensionPixelOffset(2, -1) : (int) px16;
int paddingBottom = arr.hasValue(3) ? arr.getDimensionPixelOffset(3, -1) + (isBreadButton ? (int) px16 : 0) : (isBreadButton ? (int) px16 : 0);
int type = a.getInteger(R.styleable.BRButton_buttonType, 0);
setType(type);
bPaint.setAntiAlias(true);
bPaintStroke.setAntiAlias(true);
if (isBreadButton) {
setBackground(getContext().getDrawable(R.drawable.shadow_trans));
}
setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
a.recycle();
arr.recycle();
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (observer.isAlive()) {
observer.removeOnGlobalLayoutListener(this);
}
correctTextSizeIfNeeded();
correctTextBalance();
}
});
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (isBreadButton) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(false);
}
if (type != 3)
press(ANIMATION_DURATION);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
unPress(ANIMATION_DURATION);
}
}
return super.onTouchEvent(event);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
private void correctTextSizeIfNeeded() {
int limit = 100;
int lines = getLineCount();
float px = getTextSize();
while (lines > 1 && !getText().toString().contains("\n")) {
limit--;
px -= 1;
setTextSize(TypedValue.COMPLEX_UNIT_PX, px);
lines = getLineCount();
if (limit <= 0) {
Log.e(TAG, "correctTextSizeIfNeeded: Failed to rescale, limit reached, final: " + px);
break;
}
}
}
private void correctTextBalance() {
}
#Override
protected void onDraw(Canvas canvas) {
if (isBreadButton) {
shadowRect.set(5, height / 4, width - 5, (int) (height * shadowOffSet));
modifiedWidth = width - 10;
modifiedHeight = height - height / 4 - 5;
bRect.set(5, 5, modifiedWidth, modifiedHeight + 5);
canvas.drawBitmap(shadow, null, shadowRect, null);
canvas.drawRoundRect(bRect, ROUND_PIXELS, ROUND_PIXELS, bPaint);
if (type == 2 || type == 3)
canvas.drawRoundRect(bRect, ROUND_PIXELS, ROUND_PIXELS, bPaintStroke);
}
super.onDraw(canvas);
}
public void setType(int type) {
if (type == 3) press(1);
this.type = type;
if (type == 1) { //blue
bPaint.setColor(getContext().getColor(R.color.button_primary_normal));
setTextColor(getContext().getColor(R.color.white));
} else if (type == 2) { //gray stroke
bPaintStroke.setColor(getContext().getColor(R.color.extra_light_gray));
bPaintStroke.setStyle(Paint.Style.STROKE);
bPaintStroke.setStrokeWidth(Utils.getPixelsFromDps(getContext(), 1));
setTextColor(getContext().getColor(R.color.light_gray));
bPaint.setColor(getContext().getColor(R.color.button_secondary));
bPaint.setStyle(Paint.Style.FILL);
} else if (type == 3) { //blue strokeww
bPaintStroke.setColor(getContext().getColor(R.color.button_primary_normal));
bPaintStroke.setStyle(Paint.Style.STROKE);
bPaintStroke.setStrokeWidth(Utils.getPixelsFromDps(getContext(), 1));
setTextColor(getContext().getColor(R.color.button_primary_normal));
bPaint.setColor(getContext().getColor(R.color.button_secondary));
bPaint.setStyle(Paint.Style.FILL);
}
invalidate();
}
private void press(int duration) {
ScaleAnimation scaleAnim = new ScaleAnimation(
1f, 0.96f,
1f, 0.96f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1f);
scaleAnim.setDuration(duration);
scaleAnim.setRepeatCount(0);
scaleAnim.setInterpolator(new AccelerateDecelerateInterpolator());
scaleAnim.setFillAfter(true);
scaleAnim.setFillBefore(true);
scaleAnim.setFillEnabled(true);
ValueAnimator shadowAnim = ValueAnimator.ofFloat(SHADOW_UNPRESSED, SHADOW_PRESSED);
shadowAnim.setDuration(duration);
shadowAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
shadowOffSet = (float) animation.getAnimatedValue();
invalidate();
}
});
startAnimation(scaleAnim);
shadowAnim.start();
}
private void unPress(int duration) {
ScaleAnimation scaleAnim = new ScaleAnimation(
0.96f, 1f,
0.96f, 1f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1f);
scaleAnim.setDuration(duration);
scaleAnim.setRepeatCount(0);
scaleAnim.setInterpolator(new AccelerateDecelerateInterpolator());``
scaleAnim.setFillAfter(true);
scaleAnim.setFillBefore(true);
scaleAnim.setFillEnabled(true);
ValueAnimator shadowAnim = ValueAnimator.ofFloat(SHADOW_PRESSED, SHADOW_UNPRESSED);
shadowAnim.setDuration(duration);
shadowAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
shadowOffSet = (float) animation.getAnimatedValue();
invalidate();
}
});
startAnimation(scaleAnim);
shadowAnim.start();
}
}
The error is simply saying Android Studio was unable to find the following assets file
fonts/CircularPro-Medium.otf
Confirm that the file exist in your fonts folder inside your assets directory and rebuild your project.
I am new to programming and I am trying to implement a flood fill algorithm to colorize selected part in the image as a color book app.
I have found this link which provides full working code (but slow) for the algorithm. and also provide QueueLinearFloodFiller which is way faster.
The problem is that The custom MyView class is added to Relativelayout to show the bitmap that will be colored but the image is out of the view like this
I want to wrap it to fill the view and take its size like in wrap_content
I have tried to use this code to resize it
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
but it didn't work.
here is the full code and the XML
public class UnicornColorActivity extends AppCompatActivity {
private RelativeLayout dashBoard;
private MyView myView;
public ImageView image;
Button b_red, b_blue, b_green, b_orange, b_clear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_unicorn_color);
findViewById(R.id.dashBoard);
b_red = (Button) findViewById(R.id.b_red);
b_blue = (Button) findViewById(R.id.b_blue);
b_green = (Button) findViewById(R.id.b_green);
b_orange = (Button) findViewById(R.id.b_orange);
b_red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF0000);
}
});
b_blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF0000FF);
}
});
b_green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF00FF00);
}
});
b_orange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF9900);
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
}
public class MyView extends View {
private Paint paint;
private Path path;
public Bitmap mBitmap;
public ProgressDialog pd;
final Point p1 = new Point();
public Canvas canvas;
//Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
this.paint = new Paint();
this.paint.setAntiAlias(true);
pd = new ProgressDialog(context);
this.paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.unicorn_2).copy(Bitmap.Config.ARGB_8888, true);
//Bitmap.createScaledBitmap(mBitmap, 60, 60 , false);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
this.paint.setColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
public void changePaintColor(int color){
this.paint.setColor(color);
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage("Filling....");
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
// flood fill
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor, int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0 && image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0 && image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1 && image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < (height - 1) && image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="542dp"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/selectableItemBackground"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="#+id/dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/b_red"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="10dp" >
</RelativeLayout>
</android.support.v7.widget.CardView>
<Button
android:id="#+id/b_red"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#FF0000" />
<Button
android:id="#+id/b_green"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_red"
android:background="#00FF00" />
<Button
android:id="#+id/b_blue"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_green"
android:background="#0000FF" />
<Button
android:id="#+id/b_orange"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_blue"
android:background="#FF9900" />
<Button
android:id="#+id/button5"
android:layout_width="60dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Clear" />
Can Someone please help me to fix this
I have a setup in which I have some ImageViews around a center, and when the user clicks a Button, I want the Views to rotate around the center view, in an elliptical way.
What I have at current time is an elliptical movement, but the view is rotating in a weird axis, not on the center axis, as required.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.didasko.calculus.maca.TelaAtomo"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/maca_cinza"
android:background="#null"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_eletron_0"
android:src="#drawable/eletron_nao_completado"
android:background="#null"
android:layout_marginRight="46dp"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_marginBottom="78dp"
android:layout_above="#+id/tela_atomo_maca_central"/>
</RelativeLayout>
tela_atomo_maca_central is the center element
tela_atomo_eletron_0 is the view I want to move elliptically
final ImageButton eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = 46 * Math.cos(i);
double y = 78 * Math.sin(i);
Ponto p = new Ponto(x,y);
pontos.add(p);
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
eletron.postDelayed(eletronRunnable,100);
}
private class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
I'm probably making logical mistakes, because I can make it move elliptically, just not where I want.
How can I make the Image move elliptically around the center?
Based on your existing code I made a sample project and here is what I acheived -
Here is the modified code -
public class ActivityTest extends AppCompatActivity {
ImageButton eletron,center;
ArrayList<Ponto> pontos = new ArrayList<>();
int contagem = 0;
DemoRelativeLayout rel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.so_demo);
eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
center = (ImageButton) findViewById(R.id.tela_atomo_maca_central);
rel = (DemoRelativeLayout)findViewById(R.id.demo);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = (200 * Math.cos(i));
double y = (400 * Math.sin(i));
Ponto p = new Ponto(x,y);
pontos.add(p);
}
eletron.postDelayed(eletronRunnable,2000);
}
#Override
protected void onStart() {
super.onStart();
rel.drawCircle(pontos,center.getX() + center.getWidth()/2,center.getY() + center.getHeight()/2);
rel.invalidate();
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
/*RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);*/
eletron.setTranslationX((float) p.getX() + (eletron.getWidth()/2 + center.getWidth()/2));
eletron.setTranslationY((float)p.getY() + (eletron.getHeight()/2 + center.getHeight()/2));
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
public class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
}
I have also changed the xml file -
<com.wandertails.stackovrflw.DemoRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:background="#ffffff"
android:id="#+id/demo"
>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#444444"
android:background="#null"/>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_eletron_0"
android:src="#880080"
android:background="#null"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_above="#+id/tela_atomo_maca_central"/>
</com.wandertails.stackovrflw.DemoRelativeLayout>
Finally the DemoRelativeLayout if you want to draw the elliptical path -
public class DemoRelativeLayout extends RelativeLayout
{
ArrayList<ActivityTest.Ponto> pontos;
float cntrX,cntrY;
public DemoRelativeLayout(Context context) {
super(context);
}
public DemoRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DemoRelativeLayout(Context context, AttributeSet attrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(pontos != null){
Paint p = new Paint();
p.setColor(Color.RED);
for (ActivityTest.Ponto pt : pontos){
float x = (float)pt.getX() + cntrX;
float y = (float)pt.getY() + cntrY;
canvas.drawCircle(x,y,5,p);
}
}
}
public void drawCircle(ArrayList<ActivityTest.Ponto> pp,float x,float y){
cntrX = x;
cntrY = y;
pontos = pp;
}
}
I hope this is all you want..
I'm trying to draw grid (just 8x8 lines) in background, but my drawing view covers it and grid doesn't show up. My DrawingView handles touches and draws circles. Grid must draw grids in background (it does when DrawingView is gone).
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private RelativeLayout layout;
private DrawingView drawingView;
private FloatingActionButton pickPhoto;
private final int SELECT_PHOTO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (RelativeLayout) findViewById(R.id.layout);
pickPhoto = (FloatingActionButton) findViewById(R.id.insertPhoto);
drawingView = (DrawingView) findViewById(R.id.drawingView);
assert drawingView != null;
drawingView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
pickPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Save")
.setIcon(R.drawable.ic_save)
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
FloatingActionMenu fab = (FloatingActionMenu) findViewById(R.id.fab);
assert fab != null;
fab.setVisibility(View.GONE);
Bitmap bitmap = getBitmap(layout);
saveChart(bitmap, layout.getMeasuredHeight(), layout.getMeasuredWidth());
fab.setVisibility(View.VISIBLE);
return false;
}
})
.setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return super.onCreateOptionsMenu(menu);
}
public void saveChart(Bitmap getbitmap, float height, float width) {
File folder = new File(Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"My drawings");
if (!folder.exists()) {
folder.mkdirs();
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File file = new File(folder.getPath() + File.separator + "/" + timeStamp + ".png");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileOutputStream ostream;
try {
ostream = new FileOutputStream(file);
Bitmap save = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
Canvas now = new Canvas(save);
now.drawRect(new Rect(0, 0, (int) width, (int) height), paint);
now.drawBitmap(getbitmap,
new Rect(0, 0, getbitmap.getWidth(), getbitmap.getHeight()),
new Rect(0, 0, (int) width, (int) height), null);
save.compress(Bitmap.CompressFormat.PNG, 100, ostream);
} catch (NullPointerException | FileNotFoundException e) {
e.printStackTrace();
}
}
public Bitmap getBitmap(RelativeLayout layout) {
layout.setDrawingCacheEnabled(true);
layout.buildDrawingCache();
Bitmap bmp = Bitmap.createBitmap(layout.getDrawingCache());
layout.setDrawingCacheEnabled(false);
return bmp;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case SELECT_PHOTO:
if (resultCode == RESULT_OK) {
try {
final Uri imageUri = imageReturnedIntent.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
drawingView.setImage(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
DrawingView.java:
class DrawingView extends SurfaceView {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private ArrayList<Point> points;
private Bitmap mBitmap;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
setFocusable(true);
setFocusableInTouchMode(true);
points = new ArrayList<>();
setBackgroundColor(Color.WHITE);
}
#Override
protected void onDraw(Canvas canvas) {
if (mBitmap != null)
canvas.drawBitmap(mBitmap, 0, 0, paint);
for (Point p : points)
canvas.drawCircle(p.x, p.y, 50, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
points.add(new Point((int) event.getX(), (int) event.getY()));
invalidate();
return false;
}
public void setImage(Bitmap bitmap) {
mBitmap = bitmap;
invalidate();
}
}
Grid.java:
public class Grid extends View{
private int rowsCount = 8;
private int columnsCount = 8;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public Grid(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas) {
int height = getHeight();
int width = getWidth();
for (int i = 0; i < rowsCount; ++i) {
canvas.drawLine(0, height / rowsCount * (i + 1), width, height / rowsCount * (i + 1), paint);
}
for (int i = 0; i < columnsCount; ++i) {
canvas.drawLine(width / columnsCount * (i + 1), 0, width / columnsCount * (i + 1), height, paint);
}
super.onDraw(canvas);
}
}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layout"
tools:context=".MainActivity"
android:orientation="vertical">
<reminder.com.paint.Grid
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<reminder.com.paint.DrawingView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawingView"
android:background="#00FFFFFF"
android:layout_alignParentEnd="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.clans.fab.FloatingActionMenu
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
fab:menu_fab_size="normal"
fab:menu_showShadow="true"
fab:menu_shadowColor="#66000000"
fab:menu_shadowRadius="4dp"
fab:menu_shadowXOffset="1dp"
fab:menu_shadowYOffset="3dp"
fab:menu_colorNormal="#DA4336"
fab:menu_colorPressed="#E75043"
fab:menu_colorRipple="#99f47070"
fab:menu_animationDelayPerItem="50"
fab:menu_icon="#drawable/fab_add"
fab:menu_buttonSpacing="0dp"
fab:menu_labels_margin="0dp"
fab:menu_labels_showAnimation="#anim/fab_slide_in_from_right"
fab:menu_labels_hideAnimation="#anim/fab_slide_out_to_right"
fab:menu_labels_paddingTop="4dp"
fab:menu_labels_paddingRight="8dp"
fab:menu_labels_paddingBottom="4dp"
fab:menu_labels_paddingLeft="8dp"
fab:menu_labels_padding="8dp"
fab:menu_labels_textColor="#FFFFFF"
fab:menu_labels_textSize="14sp"
fab:menu_labels_cornerRadius="3dp"
fab:menu_labels_colorNormal="#333333"
fab:menu_labels_colorPressed="#444444"
fab:menu_labels_colorRipple="#66FFFFFF"
fab:menu_labels_showShadow="true"
fab:menu_labels_singleLine="false"
fab:menu_labels_ellipsize="none"
fab:menu_labels_maxLines="-1"
fab:menu_labels_position="left"
fab:menu_openDirection="up"
fab:menu_backgroundColor="#android:color/transparent"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_gravity="end">
<com.github.clans.fab.FloatingActionButton
android:id="#+id/insertPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_insert_photo_24dp"
fab:fab_size="mini"
fab:fab_label="Add photos" />
<com.github.clans.fab.FloatingActionButton
android:id="#+id/addCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_brightness_1_24dp"
fab:fab_size="mini"
fab:fab_label="Add circles" />
</com.github.clans.fab.FloatingActionMenu>
</RelativeLayout>
private Paint mPaintGridLine;
...
mPaintGridLine = new Paint();
mPaintGridLine.setColor(Color.WHITE);
mPaintGridLine.setStyle(Paint.Style.STROKE);
mPaintGridLine.setStrokeWidth(1);
...
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
final int w = getWidth();
final int h = getHeight();
final int colCount = 10;
final int rowCount = 10;
// vertical lines
final int vLinesCount = colCount - 1;
for (int i=0; i<vLinesCount; i++)
{
float pos = (w / colCount) * (i + 1);
canvas.drawLine(pos, 0, pos, h, mPaintGridLine);
}
// horizontal lines
final int hLinesCount = rowCount - 1;
for (int i=0; i<hLinesCount; i++)
{
float pos = (h / rowCount) * (i + 1);
canvas.drawLine(0, pos, w, pos, mPaintGridLine);
}
}