I faced with such a problem that Canvas does not paint in HorizontalScrollView. Instead, I get a blank screen. But if we add any other object, then everything is working perfectly.I have someone with that?
Here my Point.class
public class Point extends View implements Serializable {
private float x;
private float y;
private Paint paint = new Paint();
public Point(Context context) {
super(context);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawCircle(getX(), getY(), 5f, paint);
}
}
My Field class, where I want to display my points
public class GraphicField extends RelativeLayout {
private RelativeLayout scrollLayout;
public GraphicField(Context context) {
super(context);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.graph_field, this);
scrollLayout = (RelativeLayout) view.findViewById(R.id.scrollLayout);
init();
}
private void init() {
Point point = new Point(getContext());
point.setX(10);
point.setY(10);
scrollLayout.addView(point);
point = new Point(getContext());
point.setX(200);
point.setY(200);
scrollLayout.addView(point);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<LinearLayout
android:id="#+id/leftLayout"
android:layout_width="10dp"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:gravity="right"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp">
<View
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="#color/blue_dark" />
</LinearLayout>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/leftLayout"
android:fillViewport="true">
<RelativeLayout
android:id="#+id/scrollLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:background="#color/blue_dark"
android:minWidth="1000dp" />
</RelativeLayout>
</HorizontalScrollView>
</RelativeLayout>
If I replace HorizontalScrollView to RelativeLayout, then points perfectly displaying. Please help someone
What seems to be wrong is that your view collpases when placed in ScrollViews.
You'll solve the issue by adding the following attributes to your view's xml line codes :
android:minHeight="1000"
android:minWidth="1000"
But best solution is to override the 'onMeasure() method of your CustomView class :
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 2000; //enter your width in px
int desiredHeight = 1000; //enter your height in px
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(desiredWidth, widthSize);
} else {
width = desiredWidth;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(desiredHeight, heightSize);
} else {
height = desiredHeight;
}
setMeasuredDimension(width, height);
}
Related
I am drawing a view in canvas with existing views. But it draw below the view. Not exactly on the view.
public class MyView extends View {
Paint paint;
ViewGroup viewGroup;
Context context;
public MyView(Context context, ViewGroup viewGroup) {
super(context);
this.viewGroup = viewGroup;
this.context = context;
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paint = new Paint();
paint.setColor(context.getResources().getColor(R.color.gray));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Point point = getLocationOnScreen(child);
Rect rect = new Rect();
int x = point.x;
int y = point.y;
rect.left = x;
rect.top = y;
rect.right = x + child.getWidth();
rect.bottom = y + child.getHeight();
canvas.drawRect(rect, paint);
}
/*for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Rect rect = new Rect();
rect.left = child.getLeft();
rect.top = child.getTop();
rect.bottom = child.getBottom();
rect.right = child.getRight();
canvas.drawRect(rect, paint);
}*/
}
public static Point getLocationOnScreen(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Point(location[0], location[1]);
}
}
My MainActivity:
public class MainActivity extends AppCompatActivity {
ConstraintLayout constraintLayout;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
constraintLayout = findViewById(R.id.parent_view);
imageView = findViewById(R.id.item_profile_img);
imageView.post(() -> {
ViewGroup viewGroup = (ViewGroup) constraintLayout;
constraintLayout.addView(new MyView(MainActivity.this,viewGroup));
});
}
}
activity_main.xml:
<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"
tools:ignore="HardcodedText,MissingConstraints"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
tools:ignore="HardcodedText,MissingConstraints"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:id="#+id/parent_view">
<ImageView
android:id="#+id/item_profile_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_launcher_background"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription,MissingConstraints" />
<TextView
android:id="#+id/item_student_name_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="Student name"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="#+id/item_profile_img" />
<TextView
android:id="#+id/item_student_college"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student college"
app:layout_constraintStart_toEndOf="#+id/item_profile_img"
app:layout_constraintTop_toBottomOf="#+id/item_student_name_title" />
<TextView
android:id="#+id/item_student_specialization"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student specialization"
app:layout_constraintStart_toEndOf="#+id/item_profile_img"
app:layout_constraintTop_toBottomOf="#+id/item_student_college" />
<TextView
android:id="#+id/item_student_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Student description"
app:layout_constraintTop_toBottomOf="#+id/item_profile_img"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Please review my code and let me know where I did mistake.
Try This
change you're for loop inside onDraw() like this
for (int i = 0; i < viewGroup.getChildCount() - 1; ++i) {
View child = viewGroup.getChildAt(i);
Rect rect = new Rect();
// int x = point.x;
// int x = point.x;
int x = (int) child.getX() - dpToPx(20);
int y = (int) child.getY() - dpToPx(20);
rect.left = x;
rect.top = y;
rect.right = x + child.getWidth();
rect.bottom = y + child.getHeight();
canvas.drawRect(rect, paint);
}
use a view.getX() and view.getY() it returns proper x and y position of view minus value 20 is the padding of your parent view
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
I have created a custom semi-donutchart(dash chart) for my Android app (I could not find any library to do it..If you know any comment it).
EDIT: I tried animate its entry (the details are given below) and it did not work. So I started searching for how to animate a normal TextView or ImageView in a fragment and I was unable to do so. Now I am changing the post so people can learn how to animate a view (Not just a custom view) in a fragment. Any answers that say how to animate a view in a fragment are welcome.
The code is as follows
public class DonutChart extends View {
private float radius;
Paint paint;
Paint shadowPaint;
int a,b,c;
Path myPath;
Path shadowPath;
RectF outterCircle;
RectF innerCircle;
RectF shadowRectF;
public DonutChart(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.DonutChart,0, 0);
try {
radius = a.getDimension(R.styleable.DonutChart_radius, 20.0f);
} finally {
a.recycle();
}
paint = new Paint();
paint.setDither(true);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setAntiAlias(true);
paint.setStrokeWidth(radius / 14.0f);
shadowPaint = new Paint();
shadowPaint.setColor(0xf0000000);
shadowPaint.setStyle(Paint.Style.STROKE);
shadowPaint.setAntiAlias(true);
shadowPaint.setStrokeWidth(6.0f);
shadowPaint.setMaskFilter(new BlurMaskFilter(4, BlurMaskFilter.Blur.SOLID));
myPath = new Path();
shadowPath = new Path();
outterCircle = new RectF();
innerCircle = new RectF();
shadowRectF = new RectF();
float adjust = (.019f*radius);
shadowRectF.set(adjust, adjust, radius*2-adjust, radius*2-adjust);
adjust = .038f * radius;
outterCircle.set(adjust, adjust, radius*2-adjust, radius*2-adjust);
adjust = .276f * radius;
innerCircle.set(adjust, adjust, radius * 2 - adjust, radius * 2 - adjust);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw shadow
paint.setShader(null);
float adjust = (.0095f*radius);
paint.setShadowLayer(8, adjust, -adjust, 0xaa000000);
drawDonut(canvas, paint, 180, (180+a+b+c));
//Maroon
//setGradient(0xff84BC3D,0xff5B8829);
setGradient(0xffffb300,0xffffb300);
drawDonut(canvas,paint, (180+a),b);
//Violet
//setGradient(0xffe04a2f,0xffB7161B);
setGradient(0xffd32f2f,0xfff44336);
drawDonut(canvas, paint, 180,a);
// White
// setGradient(Color.TRANSPARENT,Color.TRANSPARENT);
//drawDonut(canvas, paint, 0, 180);
// Green
setGradient(0xff388e3c,0xff66bb6a);
drawDonut(canvas, paint,(180+a+b),c);
}
public void drawDonut(Canvas canvas, Paint paint, float start,float sweep){
myPath.reset();
myPath.arcTo(outterCircle, start, sweep, false);
myPath.arcTo(innerCircle, start+sweep, -sweep, false);
myPath.close();
canvas.drawPath(myPath, paint);
}
public void setGradient(int sColor, int eColor){
paint.setShader(new RadialGradient(radius, radius, radius - 5,
new int[]{sColor, eColor},
new float[]{.6f, .95f}, TileMode.CLAMP));
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int desiredWidth = (int) radius*2;
int desiredHeight = (int) radius*2;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//70dp exact
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
}else if (widthMode == MeasureSpec.AT_MOST) {
//wrap content
width = Math.min(desiredWidth, widthSize);
} else {
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(desiredHeight, heightSize);
} else {
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
public void getData(int x,int y){
invalidate();
a=((x*180)/10);
b=(y*180)/10;
c=180-(a+b);
a=90;
b=40;
c=(180-(a+b));
//Toast.makeText(getContext(),"Inside Chart "+s1+" "+s2+" "+s3 +" "+String.valueOf(x),Toast.LENGTH_SHORT).show();
}
}
The layout for the graph is defined as follows
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:customviews="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
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"
android:background="#android:color/transparent"
android:id="#+id/statistics_1_page"
tools:context=".MainActivity">
<com.spintum.preexam.DonutChart
android:id="#+id/donutChart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
customviews:radius="100dp"
android:gravity="center"
android:layout_gravity="center"
android:layout_marginTop="75dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/PerformanceRating"
android:textSize="22sp"
android:textStyle="bold"
android:gravity="center"
android:text="You Average Score is 80%"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/PerformanceRating_1"
android:textSize="18sp"
android:textStyle="bold|italic"
android:layout_gravity="center"
android:text="Don't Stop till you reach 100"/>
</LinearLayout>
I inflate the layout using a fragment as follows
public class Fragment_Statistics extends Fragment {
DonutChart chart;
public View onCreateView(LayoutInflater layoutInflater,ViewGroup container,Bundle SavedInstances){
View statistics_fragment=getActivity().getLayoutInflater().inflate(R.layout.fragment_statistics, null);
chart = (DonutChart) statistics_fragment.findViewById(R.id.donutChart);
chart.getData(2, 2);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Delay and give the device enough time to render the chart
}
}, 2000);
Animation animation_clock=AnimationUtils.loadAnimation(getActivity(),R.anim.clockwise);
chart.startAnimation(animation_clock);
return statistics_fragment;
}
#Override
public void onResume() {
super.onResume();
chart.invalidate();
}
ClockWise animation defined in the fragment is as follows
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000" >
</rotate>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:startOffset="5000"
android:fromDegrees="360"
android:toDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000" >
</rotate>
I think I have done everything correctly but no animation is created and the page just appears with the chart..
Can someone tell me what is wrong with my code or is there a better way to do it than the one I have tried to do?
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.24">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/background_tree"
/>
<AbsoluteLayout
android:id="#+id/llMapContainer"
android:layout_width="match_parent"
android:layout_height="390dp"
android:layout_x="0dp"
android:layout_y="44dp"
android:orientation="vertical" >
<ImageView
android:id="#+id/imgLocation"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_x="48px"
android:layout_y="440px"
android:src="#drawable/character_icon" />
</AbsoluteLayout>
</RelativeLayout>
</LinearLayout>
I want to place ImageView in the circles of the tree in my xml file . I tried using coordinates but it changes its positions with different screen size .
Step 1:Create CircularimageView.class
public class CircularImageView extends ImageView {
private int borderWidth;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public CircularImageView(Context context) {
super(context);
setup();
}
public CircularImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
this.setBorderWidth(2);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
loadBitmap();
// init shader
if (image != null) {
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}
return (result + 2);
}
}
Step2:In layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.24">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.packagename.CircularImageView
android:id="#+id/imgLocation"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_x="48px"
android:layout_y="440px"
android:src="#drawable/character_icon" />
</RelativeLayout>
</LinearLayout>
I implemented an ImageView-extended view with zooming and panning via gesture listeners. It works perfectly but my problem is that I need a white border around this view.
I tried to add a padding and set bitmap background to white but it didn't work correctly: view has white border on right and top but scales towards them.
Placing view into layout will work ok (I tried it) but such way complicates their layout's code.
I tried to draw rectangle behind the image but it didn't work properly. In fact, in way I tried it didn't work at all.
So I want to know is there a way to have (to draw or with padding) white border around view that can be zoomed and panned.
I think that the problem lays somewhere in onMeasure but I really don't know where to start.
My view is placed in layout with overridden onMeasure (btw how to make it nicer? it's ugly now :( ):
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int myWidth = MeasureSpec.getSize(widthMeasureSpec);
int myHeight = MeasureSpec.getSize(heightMeasureSpec);
float leftHeight = myHeight * 12f / 15f;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child != null) {
switch (child.getId()) {
case R.id.llButtons:
child.measure(MeasureSpec.makeMeasureSpec(myWidth - 20,
MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec((int) (myHeight / 15f), MeasureSpec.AT_MOST)
);
break;
case R.id.hsvFilters:
child.measure(myWidth, MeasureSpec.makeMeasureSpec((int) (myHeight * 2f /
15f),
MeasureSpec.AT_MOST
));
break;
case R.id.flFrame:
child.measure(myWidth - 20,
(int) leftHeight);
break;
}
}
}
}
layout:
<com.project.android.views.FluidContainer 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:id="#+id/fdAdjustImage"
android:orientation="vertical"
tools:context="com.project.android.dialogs.AdjustImageFragment">
<LinearLayout
android:weightSum="100"
android:id="#+id/llButtons"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="wrap_content">
<com.inkly.android.views.ButtonFont
android:id="#+id/bChangePhoto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="15dp"
android:textSize="19sp"
android:layout_weight="45"
android:text="#string/change_photo"
android:background="#drawable/btn_blue"
style="#style/RegularButton"/>
<View
android:layout_weight="10"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<com.inkly.android.views.ButtonFont
android:id="#+id/bDone"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:gravity="center"
android:textSize="19sp"
android:layout_weight="45"
android:text="#string/done"
android:background="#drawable/btn_green"
style="#style/RegularButton"/>
</LinearLayout>
<com.inkly.android.views.FluidCard
android:background="#fff"
android:layout_gravity="center"
android:padding="10dp"
android:id="#+id/flFrame"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ProgressBar
android:id="#+id/progress"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateOnly="true"
android:layout_gravity="center"
style="#android:style/Widget.Holo.Light.ProgressBar.Large"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:scrollbars="none"
android:id="#+id/hsvFilters"
android:background="#fff"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:orientation="horizontal"
android:id="#+id/llFilters"
android:layout_height="wrap_content"/>
</HorizontalScrollView>
and my view:
scaling:
public FluidCard(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setScaleType(ScaleType.MATRIX);
mScaleDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
float mFocusX;
float mFocusY;
float mScaleMoveX = 0;
float mScaleMoveY = 0;
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mFocusX = detector.getFocusX();
mFocusY = detector.getFocusY();
mScaleMoveX = mFocusX * (1f - mScaleFactor);
mScaleMoveY = mFocusY * (1f - mScaleFactor);
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
float newScaleFactor = mScaleFactor * detector.getScaleFactor();
if (newScaleFactor < mScaleFactor) {
newScaleFactor *= 0.94f;
}
newScaleFactor = Math.max(1f, Math.min(newScaleFactor, 10.0f));
boolean isDecrease = newScaleFactor < mScaleFactor;
mScaleFactor = newScaleFactor;
float newScaleMoveX = mFocusX * (1f - mScaleFactor);
float newScaleMoveY = mFocusY * (1f - mScaleFactor);
if (newScaleMoveX != mScaleMoveX || newScaleMoveY != mScaleMoveY) {
float dx = newScaleMoveX - mScaleMoveX;
float dy = newScaleMoveY - mScaleMoveY;
if (isDecrease) {
float minOffsX = getMeasuredWidth() - 10 - mScaledWidth * mScaleFactor;
if (mMoveX + dx < minOffsX) {
mMoveX = minOffsX;
} else {
if (mMoveX + dx <= 0) {
mMoveX += dx;
} else {
mMoveX = 0;
}
}
float minOffsY = getMeasuredHeight() - 10 - mScaledHeight * mScaleFactor;
if (mMoveY + dy < minOffsY) {
mMoveY = minOffsY;
} else {
if (mMoveY + dy <= 0) {
mMoveY += dx;
} else {
mMoveY = 0;
}
}
} else {
mMoveX += dx;
mMoveY += dy;
}
mScaleMoveX = newScaleMoveX;
mScaleMoveY = newScaleMoveY;
mForceInvalidate = true;
}
return true;
}
});
mMoveDetector = new MoveGestureDetector(context, new MoveGestureDetector.SimpleOnMoveGestureListener() {
#Override
public boolean onMoveBegin(MoveGestureDetector detector) {
return true;
}
#Override
public boolean onMove(MoveGestureDetector detector) {
PointF focusDelta = detector.getFocusDelta();
float newX = mMoveX + focusDelta.x;
if (newX <= 0 && newX + mScaledWidth * mScaleFactor >= getMeasuredWidth() - 10) {
mMoveX = newX;
mForceInvalidate = true;
}
float newY = mMoveY + focusDelta.y;
if (newY <= 0 && newY + mScaledHeight * mScaleFactor >= getMeasuredHeight() - 10) {
mMoveY = newY;
mForceInvalidate = true;
}
return true;
}
});
mPaint.setFilterBitmap(false);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
rectPaint.setColor(Color.WHITE);
mBackground = new Rect();
}
onMeasure:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (w == 0 && h == 0) {
int oldWidth = MeasureSpec.getSize(widthMeasureSpec);
int oldHeight = MeasureSpec.getSize(heightMeasureSpec);
double width, height;
if (mAspectRatio > 1f) {
height = oldHeight;
width = Math.ceil(oldHeight / mAspectRatio);
} else {
width = oldWidth;
height = Math.ceil(oldWidth * mAspectRatio);
}
if (height > oldHeight || width > oldWidth) {
float k = 1.1f;
while (height > oldHeight || width > oldWidth) {
height /= k;
width /= k;
k += 0.01f;
}
}
w = (int) Math.ceil(width);
h = (int) Math.ceil(height);
}
if (getDrawable() != null) {
setupMatrix(w, h);
}
setMeasuredDimension(w, h);
}
onTouch:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mEditEnabled) {
mScaleDetector.onTouchEvent(event);
boolean isScaling = mScaleDetector.isInProgress();
if (!isScaling) mMoveDetector.onTouchEvent(event);
if (mForceInvalidate) {
mForceInvalidate = false;
mMatrix.reset();
mMatrix.setScale(mScale, mScale);
if (mScaleFactor > 1) {
mMatrix.postScale(mScaleFactor, mScaleFactor);
}
mMatrix.postTranslate(mMoveX, mMoveY);
invalidate();
}
return true;
}
return super.onTouchEvent(event);
}
draw:
#Override
public void draw(Canvas canvas) {
int sc = canvas.saveLayer(10, 10, getWidth() - 10, getHeight() - 10, null,
Canvas.CLIP_TO_LAYER_SAVE_FLAG);// | Canvas.FULL_COLOR_LAYER_SAVE_FLAG ?
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.setMatrix(mMatrix);
super.draw(canvas);
canvas.restore();
canvas.restoreToCount(sc);
}
UPD:
android:cropToPadding="true" didn't work the way I need, although the resulting picture is now smaller (but that's not good).
I have to draw a custom view below A banner for that like the pick attached PICK
below DaTTab banner I have to draw the Rectangle view my xml
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include android:id="#+id/banner" layout="#layout/upper_border" />
<com.example.ui_1.Border_Portrait
android:id="#+id/custom_display_view1"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_below="#+id/banner"
/>
Draw_Border.jav
class Border_Portrait extends View{
private static final int DEFAULT_SIZE = 100;
int mViewHeight , mViewWidth ;
Paint mPaint ;
Canvas mCanvas ;
int margin ;
float [] mPoints ;
int mLogoHeight ;
int mLogoWidth ;
int dy,dx ;
public Border_Portrait(Context context) {
super(context);
}
public Border_Portrait(Context context, AttributeSet attrs) {
super(context, attrs);
margin = 7 ;
mPaint = new Paint();
mPaint.setColor(Color.rgb(0,188,226));
mPaint.setStrokeWidth(3);
mLogoHeight = ScreenUtils.convertDIPToPixels(getContext(), 50 + margin );
mLogoWidth = ScreenUtils.convertDIPToPixels(getContext(), 66 + margin);
dy = ScreenUtils.convertDIPToPixels(getContext(),1) ;
dx= ScreenUtils.convertDIPToPixels(getContext(),1) ;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.save();
mPoints = new float [] {
margin + mLogoWidth ,margin,//1
getWidth()-margin ,margin ,//1
getWidth()-margin ,margin ,//2
getWidth()-margin , getHeight()-margin ,//2
getWidth()-margin , getHeight()-margin , //3
margin , getHeight()-margin , //3
margin , getHeight() - margin , //4
margin , mLogoHeight + dy ,//4
margin , mLogoHeight + dy , // 5
margin + mLogoWidth + dx ,mLogoHeight + dy, //5
margin + mLogoWidth ,mLogoHeight + dy, //6
margin + mLogoWidth ,margin, //6
} ;
canvas.drawLines(mPoints, mPaint);
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
}
private int calculateMeasure(int measureSpec) {
return 0 ;
}
}
my question is how to measure the Width of the border at run time I have refer
THIS
and other links too but till now no luck
Just got the answer add margin in main.xml
<com.example.ui_1.Border_Portrait
android:id="#+id/custom_display_view1"
android:layout_marginTop="50dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>