Parent layout has a specified width value (50dp), and height set to MATCH_PARENT. In that layout I am adding a few ImageView widgets using Java, and because parent layout has specified width, I can set width and height of each ImageView to MATCH_PARENT and using Java I can make that ImageView square by setting its height as width.
This is my code:
public class Icon extends ImageView {
public AppIcon(final Context context)
{
super(context);
}
public AppIcon(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public AppIcon(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(final int width, final int height)
{
setMeasuredDimension(width, width);
}
}
Is this a good method to make each ImageView square? I think it's too simple, like something is missing.
P.S.: My method works, but I need to be sure, that everything is fine.
Your code is working one but it can be enhanced. See my code:
Updated my code.
The image will be scaled based on the measured width and height and whichever is smaller.
public class Icon extends ImageView {
public Icon(final Context context) {
super(context);
}
public Icon(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public Icon(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
if (measuredWidth > measuredHeight) {
setMeasuredDimension(measuredHeight, measuredHeight);
} else {
setMeasuredDimension(measuredWidth, measuredWidth);
}
}
}
Related
I am fairly new to Java and android studio. I would like to animate my bar which I created with random value. I have created customView with android studio and drawn a canvas rectangle. Next step is feed some random values and animate the bar. I acheived this feat with (Math.random) in JavaScript.
public class CustomView extends View {
private Rect rect;
private Paint paint;
int radius;
public CustomView(Context context){
super(context);
init(null);
}
public CustomView(Context context, AttributeSet attrs){
super(context, attrs);
init(attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
init(attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(#Nullable AttributeSet set){
rect = new Rect();
// the flag is more pixelated
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
postInvalidate();
}
//drawing a canvas
#Override
protected void onDraw(Canvas canvas){
int viewWidth = getWidth();
int viewHeight = getHeight();
int leftTopX = viewWidth - 750;
int leftTopY = viewHeight - 750;
int rightBotX = viewWidth + 150;
int rightBotY = viewHeight + 150;
paint.setColor(Color.MAGENTA);
canvas.drawRect(leftTopX,leftTopY, rightBotX,rightBotY,paint);
paint.setColor(Color.GREEN);
}
}
This is what I have achieved so far by now.But how can I animate bar with Java ?
Try this -
I used it with seekbar. You can use it for your view. As per your case. You should Progressbar or Seekbar.
seekbar = ((CustomSeekbar) findViewById(R.id.customSeekBar));
seekbar.setMax(2600);
final ObjectAnimator animation = ObjectAnimator.ofInt(seekbar, "progress", 0, 800;
animation.setDuration(1500);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();
seekbar.clearAnimation();
Here 0 is the starting value and 800 is the max value. Please change is as per your requirement.
I already know how to use a custom component in a xml. Now, I'm trying to call one programmatically. I haven't found any tutorial about this so I tried to do it like how we declare a view programmatically. One problem I stumbled upon is that how do I get an AttributeSet that I pass on my constructor? I don't know how I get or create that to pass it for my custom component.
This is my custom component class.
public class CheckOutItem extends ConstraintLayout {
public Context ctx;
public Paint mPaint;
public Rect mRect;
int mSquareColor;
public ImageView imgThumbnail;
public TextView lblAbbrev, lblFullName;
public ConstraintLayout lytMain;
String TAG = "sharePOS";
public CheckOutItem(Context context) {
super(context);
ctx = context;
init(null);
}
public CheckOutItem(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.checkout_item, this);
ctx = context;
init(attrs);
}
public CheckOutItem(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
ctx = context;
init(attrs);
}
private void init(#Nullable AttributeSet set){
//inflate(ctx, R.layout.checkout_item, this);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRect = new Rect();
if(set == null){
return;
}
TypedArray ta = getContext().obtainStyledAttributes(set, R.styleable.CheckOutItem);
this.imgThumbnail = findViewById(R.id.imgItemThumbnail);
this.lblAbbrev = findViewById(R.id.lblItemAbbrevName);
this.lblFullName = findViewById(R.id.lblItemFullName);
this.lytMain = findViewById(R.id.lytMain);
this.lblAbbrev.setText(ta.getText(R.styleable.CheckOutItem_abbrevText));
this.lblAbbrev.setTextSize(ta.getDimension(R.styleable.CheckOutItem_abbrevTextSize, 1f));
this.lblAbbrev.setTextColor(ta.getColor(R.styleable.CheckOutItem_abbrevTextColor, Color.BLACK));
this.lblFullName.setText(ta.getText(R.styleable.CheckOutItem_fullNameText));
this.lblFullName.setTextSize(ta.getDimension(R.styleable.CheckOutItem_fullNameTextSize, 1f));
this.lblFullName.setTextColor(ta.getColor(R.styleable.CheckOutItem_fullNameTextColor, Color.BLACK));
this.lblFullName.setBackgroundColor(ta.getColor(R.styleable.CheckOutItem_fullNameBackgroundColor, Color.WHITE));
this.lytMain.setBackgroundColor(ta.getColor(R.styleable.CheckOutItem_mainBackgroundColor, Color.LTGRAY));
this.lytMain.setBackground(ta.getDrawable(R.styleable.CheckOutItem_mainBackgroundDrawable));
ta.recycle();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mRect.left = 0;
mRect.right = getWidth();
mRect.top = 0;
mRect.bottom = getHeight();
Log.d(TAG, "rect: " + mRect);
canvas.drawRect(mRect, mPaint);
}
}
UPDATE:
How do I set a margin in the custom component? Regular LayoutParams with setMargins() doesn't seem to work.
I wanted to draw an image on canvas using bitmapFactory, but it gave me an error.
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.isRecycled()' on a null object reference
at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:54)
at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:226)
at android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:78)
at com.example.canvastest.GameView.onDraw(GameView.java:23)
I tried to change null paint with actual paint object but it was no good.
I also tried using Rect for space but is was also not good.
private Bitmap bmp;
public GameView(Context context) {
super(context);
bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawBitmap(bmp, 10, 10, null);
}
Try to create method init(Context context) like this:
public void init(Context context) {
this.context = context;
bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
}
Then:
public GameView(Context context) {
super(context);
init(context);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
I need to know when the user scroll up or down. I managed to achieve that but now I am stuck getting the result back to my main class where I need it. Specifically I don't know how to pass the results to an interface I created.
Here is the error I get:
Attempt to invoke interface method 'void
com.app.android.interfaces.ScrollDirection.Down(int)' on a
null object reference
And here is my custom ScrollView:
public class CustomScrollView extends ScrollView {
private ScrollDirection scrolldirection;
public CustomScrollView(Context context) {
super(context);
scrolldirection = (ScrollDirection) context;
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onScrollChanged(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
super.onScrollChanged(scrollX, scrollY, oldScrollX, oldScrollY);
if(scrollY<oldScrollY){
scrolldirection.Down(1);
}else{
scrolldirection.Down(-1);
}
}
public interface ScrollDirection{
public void Down(int direction);
}
}
you need to add this line scrolldirection = (ScrollDirection) context; inside every constructor
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
scrolldirection = (ScrollDirection) context;
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
scrolldirection = (ScrollDirection) context;
}
To allow Android Studio to interact with your view, at a minimum you must provide a constructor that takes a Context and an AttributeSet object as parameters
Docs link
Update : The recent issue was the implementation of CustomScrollView inside Fragment but Fragment do not have their context. To implement this ,make parent Activity implements the ScrollDirection and make some function in Fragment and call them from Activity's Down function.
In my application i can scaling an ImageView using this class
`public class resizeAvatar extends View {
private final Drawable sfondoAvatar;
public resizeAvatar(Context context) {
super(context);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs) {
super(context, attrs);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
#Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * sfondoAvatar.getIntrinsicHeight() / sfondoAvatar.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
`
And writing in the layout:
<com.myapp.app.resizeAvatar
android:id="#+id/mainvoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_centerVertical="true"/>
But in this way i can't have the onClick event.. i need do the same but using an ImageButton.. Is there a way?
In the activity where you include this view and in the onCreate method do the following:
resizeAvatar myMainvoice = (resizeAvatar) v.findViewById(R.id.mainvoice);
myMainVoice.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
//place your on click logic here
}
});