Actually I programming a app that use image rotation. But when I rotate image, it doesn't show anything.
This is my code:
XML file:
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rotate_test_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/android"
android:src="#drawable/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="matrix"
android:adjustViewBounds="true"
android:contentDescription="#string/android_description" >
</ImageView>
</LinearLayout>
Activity file:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rotate_test_layout);
ImageView imageView = (ImageView)findViewById(R.id.android);
imageView.setScaleType(ScaleType.MATRIX);
Matrix matrix = new Matrix();
matrix.postRotate(90);
imageView.setImageMatrix(matrix);
}
You are making a mistake here:
imageView.setImageMatrix(matrix);
Instead of doing that you have to apply that matrix to the existing Bitmap to get a new bitmap which you can then assign to the ImageView.
Drawable drawable = getResources().getDrawables(R.drawable.android);
Bitmap existingBitmap = ((BitmapDrawable) drawable).getBitmap();
Bitmap rotated = Bitmap.createBitmap(existingBitmap, 0, 0, existingBitmap.getWidth(), existingBitmap.getHeight(), matrix, true);
imageView.setImageBitmap(rotated);
You can rotate ImageView without using matrix.
test it.
imageView.setRotation(90.0f);
Related
I am trying to programatically change the width of an ImageView without resizing the image. The ImageView originally shows the entire image, but when the width of the image is decreased, a portion of the image should be cut off, like this:
However, when my code reduces the width of the ImageView from 350dp to 200dp, the image is automatically resized instead:
How do I ensure that the ImageView does not resize the image when I decrease its width? Below is my code:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/photo_1_preview"
android:layout_width="350dp"
android:layout_height="350dp"
android:adjustViewBounds="false"
android:background="#drawable/android"/>
</LinearLayout>
MainActivity.java:
package com.example.changingimageviewwidth;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Reduce the width of the image preview box
ImageView imagePreviewBox = findViewById(R.id.photo_1_preview);
imagePreviewBox.getLayoutParams().width = 250;
}
}
Use android:scaleType="matrix" for the ImageView and put the desired image in android:src.
NOTE: In this case, I set the LinearLayout to be 400x400 because the image size is 400x400 px and wrap the ImageView inside of a LinearLayout just for clarity.
main.xml
<?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:background="#333333"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_height="400px"
android:layout_width="400px"
android:orientation="vertical"
android:background="#0000FF">
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:src="#drawable/android"
android:scaleType="matrix"
android:id="#+id/iv"/>
</LinearLayout>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = findViewById(R.id.iv);
ViewGroup.LayoutParams params = iv.getLayoutParams();
params.width = 200; //200 pixels.
//Not necessary in my test. You may need to call the following
//method if you set the params outside of onCreate(), onCreateView().
//iv.requestLayout();
}
}
Output:
Set the scale type to CENTER_CROP. That will center the image in the view, and crop out anything that doesn't fit.
To get your desired behavior, simply set android:scaleType="fitStart" to your ImageView in xml. It will not change the aspect ratio of the src, but aligns it to the start of the ImageView, just as you mentioned.
The problem you're facing is because the drawable is set as a background of ImageView instead of being set as a source
After you fix that, the right scaleType to choose for your use-case is fitStart which will maintain the original aspect ratio for the bitmap and align it to the top-left of the ImageView
Please use the updated layout file -
<?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="vertical" >
<ImageView
android:id="#+id/photo_1_preview"
android:layout_width="350dp"
android:layout_height="350dp"
android:adjustViewBounds="false"
android:scaleType="fitStart"
android:src="#drawable/android"/>
</LinearLayout>
Try with the following code.
//activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/image_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:scaleType="fitCenter"
android:src="#drawable/dumy" />
</LinearLayout>
//MainActivity.java
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.image_view);
imageView.getLayoutParams().width = dpToPixels(150);
imageView.requestLayout();
imageView.invalidate();
}
private int dpToPixels(int size) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, getResources().getDisplayMetrics());
}
}
I want to create a vertical seekbar with progress displaying near to thumb.
I created vertical seekbar by overriding Seekbar class and rotate the canvas. But I don't know how to make the text near to thumb.
#Override
protected final void onDraw(#NonNull final Canvas c) {
if (null == mPaint) {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(50);
}
c.rotate(ROTATION_ANGLE);
c.translate(-getHeight(), 0);
super.onDraw(c);
Rect rect = getThumb().getBounds();
c.drawText(getProgress()+"%", rect.exactCenterX(), rect.exactCenterY(), mPaint);
}
So the problem is If I drawText like this the text also rotated.
So how to fix this?
Meanwhile, I tried some custom View implementation and I am a noob on that.
Update to Khemraj's answer
Actually changing the thumb is the simple trick as said by Khemraj. But the problem is when rotating the canvas all its contents will rotate(simple logic). When updating the thumb also will reflect this problem. So the simple thing is to make a rotated CustomTextView.
Method to make thumb
public Drawable getThumb(int progress) {
int width = getWidth();
((TextView) mThumbView.findViewById(R.id.tvProgress)).setText(String.format(Locale.getDefault(), "%d%%", progress));
mThumbView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Bitmap bitmap = Bitmap.createBitmap(mThumbView.getMeasuredWidth(), mThumbView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
mThumbView.layout(0, 0, mThumbView.getMeasuredWidth(), mThumbView.getMeasuredHeight());
mThumbView.draw(canvas);
return new BitmapDrawable(getResources(), bitmap);
}
The layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<ImageView
android:layout_marginTop="30dp"
android:id="#+id/imageView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/seek_thumb_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.samsung.lighting.presentation.ui.custom_views.RotatedTextView
android:id="#+id/tvProgress"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:gravity="center"
android:text="20%"
android:textColor="#000000"
android:textSize="12sp"
app:angle="90"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView6" />
</android.support.constraint.ConstraintLayout>
The RotatedTextView
public class RotatedTextView extends AppCompatTextView {
private int mRotationAngle = 90;
#Override
protected void onDraw(Canvas canvas) {
if (mRotationAngle == 90) {
canvas.rotate(mRotationAngle);
canvas.translate(0, -getWidth());
} else if (mRotationAngle == -90) {
canvas.rotate(mRotationAngle);
canvas.translate(-getHeight(), 0);
}
super.onDraw(canvas);
}
}
So first we will rotate the Text to 90 or -90 degrees and set as thumb to VerticalSeekBar and in vertical seekbar rotate the canvas to 90 or -90 degrees. So finally we will get the actual result
Here I posted the working example.
Thanks, Khemraj
Can we custom marker icon google map?
I dont want just simply change the icon bitmap (I know how to do it)
I want to change the icon in the way like I have a xml layout (with have one imageview and a textview) and I want to inflate this xml (like custom info window). But I want to make it marker icon, so I can set image and text by coding
Note that I dont want a info window, I want it to be a marker
You can create your layour and convert that layout into Drawable and you can add that drawable into icon of your marker.
You can create your layout like this,
<?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="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_name"
"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="2dp"
android:text="Name"
android:textSize="16sp"/>
</LinearLayout>
Below method will give your the Bitmap from a layout,
private Bitmap getBitmapFromLayout(int layout) {
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layout, null);
view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
view.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
Drawable drawable = view.getBackground();
if (drawable != null)
drawable.draw(canvas);
view.draw(canvas);
return bitmap;
}
You can add the Bitmap in map marker icon like this,
mMap.addMarker(new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(getBitMapFromLayout([your layout id]))));
I am making an Android app and attempting to programatically draw some clickable, rectangular blocks with text on one of two custom views contained in a ScrollLayout. The XML for my ScrollLayout looks like this:
<ScrollView
android:layout_width="match_parent"
android:id="#+id/calendarGridContainerView"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_below="#+id/employeeSpinnerContainer"
android:paddingBottom="72dp"
android:layout_height="match_parent"
android:overScrollMode="never"
android:fillViewport="true"
android:elevation="1dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:id="#+id/schedule_view_container"
android:layout_height="wrap_content">
<FrameLayout
android:layout_height="wrap_content"
android:id="#+id/schedule_time_frame"
android:layout_width="100dp"
android:layout_alignParentTop="false"
android:layout_weight="0.5">
<include
layout="#layout/schedule_time_view"
android:layout_height="wrap_content"
android:layout_width="100dp" />
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/schedule_grid_frame"
android:minHeight="179dp"
android:layout_toRightOf="#+id/schedule_time_frame"
android:layout_centerHorizontal="false"
android:layout_weight="8">
<include
layout="#layout/schedule_grid_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</FrameLayout>
</LinearLayout>
</ScrollView>
Note that the layout called scheduleGridLayout is where I am trying to draw these rectangles. It has the following XML:
<?xml version="1.0" encoding="utf-8"?>
<(package).ScheduleGridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:scheduleGridLayout="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
</(package).ScheduleGridLayout>
(When copying the above code, I removed the package name.)
In the constructor for ScheduleGridLayout.java, I call this.setWillNotDraw(false);. Before drawing the rectangles, I draw some horizontal gridlines on ScheduleGridLayout through its overridden onDraw() method:
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.LTGRAY);
final int width = getWidth();
final int rowHeight = ScheduleTimeLayout.SCHEDULE_VIEW_ROW_HEIGHT + ScheduleTimeLayout.TIME_LABEL_HEIGHT;
for(int i = 0; i < ScheduleTimeLayout.TIME_SEGMENT_COUNT + 1; i++){
if ((i % (int)(1.0/ScheduleTimeLayout.SEGMENT_SIZE)) == 0){
paint.setColor(Color.GRAY);
paint.setStrokeWidth((float)4.0);
}
else{
paint.setColor(Color.LTGRAY);
paint.setStrokeWidth((float)2.0);
}
int y = 178 + (int)(i*(rowHeight + 1) - rowHeight/2.0);
canvas.drawLine(0, y, width, y, paint);
}
Since I want the rectangles to be clickable, I have to add them as some sort of views rather than simply drawing their images onto the canvas. I've tried a few different ways to draw the rectangles-- currently I try to do it in onFinishInflate() in ScheduleGridLayout.java, like so:
Bitmap bmp = Bitmap.createBitmap(60,200,Bitmap.Config.RGB_565);
Bitmap tempBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);
paint = new Paint();
paint.setColor(Color.RED);
tempCanvas.drawBitmap(bmp, 0, 0, null);
tempCanvas.drawRoundRect(new RectF(0,0,600,600), 2, 2, paint);
ImageView testBlock = new ImageView(getContext());
testBlock.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
addView(testBlock);
However, there the block does not appear when I do this.
In a separate attempt, I tried creating an XML layout file for the schedule block:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<com.dalc.dalccalendar.ScheduleBlock
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:scheduleGridLayout="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/schedule_block">
</com.dalc.dalccalendar.ScheduleBlock>
In ScheduleBlock.java, I override onMeasure() to set the size of the block using setMeasuredDimension, and I override onDraw() with the following code:
super.onDraw(canvas);
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawPaint(paint);
String bgColor = "#FF0000";
setBackgroundColor(Color.parseColor(bgColor));
I noticed that red rectangle does appear in the XML file's preview, but not when I try to add the block in ScheduleGridLayout:
FrameLayout blockFrame = (FrameLayout)LayoutInflater.from(getContext()).inflate(R.layout.schedule_block_container, this, false);
testBlock.setElevation(4);
addView(blockFrame);
Not only does the rectangle not appear when I run the app, but I've found that the onDraw() method for ScheduleBlock is not called. What am I doing wrong? How can I make these blocks appear inside my scrollview on top of the gridlines and be interactable with clicks? I'd prefer to be able to do with with custom views if possible, since each block needs to be associated with specific data.
I am absolutly new in Android development and I have the followind doubt.
I have to draw images one next to each other into a Canvas object.
So let to do an example of what I neeed:
Into the /res/drawable/ folder of my project I have this icon (I have resized it before put it into my project but I think that this is not so important):
So I have to put 3 of these icon one next to each other into a specific ImageView of my activity view (adding some white space between an image and the next one).
So I have done something like this:
1) This is the code of my fragment_screen_slide.xml file that represent the layout where these images have to be placed:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="0dp">
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:scaleType="fitXY"
android:layout_height="250dp" />
<TextView android:id="#android:id/text1"
style="#style/pastaTitleTextStyle" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
style="#style/HeaderTextStyle"
android:text="Difficoltà :" />
<ImageView
android:id="#+id/starContainer"
android:layout_width="fill_parent"
android:scaleType="fitXY"
android:layout_height="250dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
In particular these images have to be placed into this ImageView contained in the previous code snippet:
<ImageView
android:id="#+id/starContainer"
android:layout_width="fill_parent"
android:scaleType="fitXY"
android:layout_height="250dp" />
Here I have a first doubt because Androi Studio report an error on this line:
android:id="#+id/starContainer"
The reported error is a red underline on the # and when I pass the mouse pointer on it I can read the following error message:
<interface declaration>, <perceable declaration>, AidToken.import or AidTokenTye.package expected, got '#'
It seems strange to me because I am only creatin an id for the ImageView and because I have not problem when Gradle build the project.
Then, into the Java code that actually put the images into the previous ImageView I have done something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
System.out.println("PAGE NUMBER: "+ mPageNumber + 1);
// Create the Canvas where the images are putted:
Canvas difficultyCanvas = creaImgDifficulty();
switch (mPageNumber + 1) {
case 1:
imgSlideView.setImageResource(R.drawable.carbonara);
((TextView) rootView.findViewById(android.R.id.text1)).setText(getString(R.string.carbonara));
difficultyCanvas = creaImgDifficulty();
ImageView starContainer = (ImageView) rootView.findViewById(R.id.starContainer);
starContainer.draw(difficultyCanvas);
break;
// OTHER CASES
}
private Canvas creaImgDifficulty() {
Canvas canvas;
Bitmap chefHatOk = BitmapFactory.decodeResource(getResources(), R.star);
Bitmap output = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
canvas = new Canvas(output);
int space = 10; // the space between images
for(int i = 0; i < 3; i++) {
canvas.drawBitmap(chefHatOk, i * (chefHatOk.getWidth() + space), 0, null);
}
return canvas;
}
}
So, as you can see in the previous code sippet, when the view is created first I create a new Canvas object (that contains the repeated images) calling the creaImgDifficulty() and then I try to draw this Canvas object into the previous ImageView having id=starContainer.
The creaImgDifficulty() create the Canvas object and draw the bitmap on it 3 times.
I obtain no error when I run the application but the images is not displayed into my ImageView.
Why? What is wrong? What am I missing? How can I try to solve this issue?
XML cannot contain capitals. Switch your ID line to:
android:id="#+id/star_container"
Then change your java file references to match.