I wanted to rotate an imageview on center point with a duration(ex: 5 sec).
is it possible ? how ?
like this picture :
public class RotateImageView extends ImageView {
private Animation mRotation;
public bool isAnimating = false;
public RotateImageView(Context context) {
super(context);
Init(null);
}
public RotateImageView(Context context, AttributeSet attrs) {
super(context, attrs);
Init(attrs);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RotateImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Init(attrs);
}
private void Init(AttributeSet attrs) {
startAnimation();
}
public void startAnimation() {
if (mRotation == null) {
mRotation = AnimationUtils.loadAnimation(getContext(), R.anim.rotate);
mRotation.setRepeatCount(Animation.INFINITE);
}
this.startAnimation(mRotation);
isAnimating = true;
}
public void stopAnimation() {
if (mRotation != null)
clearAnimation();
isAnimating = false;
}
#Override
public void setVisibility(int visibility) {
if (visibility == GONE || visibility == INVISIBLE) {
clearAnimation();
} else if (visibility == VISIBLE) {
startAnimation(mRotation);
}
super.setVisibility(visibility);
}
}
rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:fromDegrees="0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="0"
android:toDegrees="360" />
EDITED
RotateImageView image = new RotateImageView(Context);
image.addOnClickListener(new View.OnClickListener(){
if(image.isAnimating)
image.stopAnimating();
else
image.startAnimating();
}
Use this animation.xml:
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000" />
Related
I'm making a custom View that displays a spinner to show that the camera is focusing.
public class ApertureAnimation extends View
{
private final static String TAG = "ApertureAnimation";
private AnimationDrawable animationDrawable;
public ApertureAnimation(Context context)
{
super(context);
init(null, 0);
}
public ApertureAnimation(Context context, AttributeSet attrs)
{
super(context, attrs);
init(attrs, 0);
}
public ApertureAnimation(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle)
{
animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.apperature_focus, null);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
int contentWidth = getWidth() - paddingLeft - paddingRight;
int contentHeight = getHeight() - paddingTop - paddingBottom;
if(animationDrawable != null)
{
animationDrawable.setBounds(paddingLeft, paddingTop, paddingLeft + contentWidth, paddingTop + contentHeight);
animationDrawable.start();
animationDrawable.draw(canvas);
}
}
public void start()
{
if(animationDrawable != null)
animationDrawable.start();
}
public void stop()
{
if(animationDrawable != null)
animationDrawable.stop();
}
}
apperature_focus.xml
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="#drawable/apperature_0" android:duration="200" />
<item android:drawable="#drawable/apperature_30" android:duration="200" />
<item android:drawable="#drawable/apperature_60" android:duration="200" />
</animation-list>
The issue I'm having is that only the first frame shows when I call start(). I am able to get the animation to work if I use an ImageView outside of a class extending View, like this https://developer.android.com/guide/topics/graphics/drawable-animation, but when I try to bring that code into this custom UI component it doesn't work.
This question already has answers here:
Discrete SeekBar
(2 answers)
Closed 5 years ago.
i achieved tooltip design using this link as reference, now i want to achieved seekbar interval as vertical line and not as dots with numbers as like above the image.
Check this code it may help you
public class DWRulerSeekbar extends RelativeLayout implements SeekBar.OnSeekBarChangeListener {
private int seekbarMinValue = 0;
private int seekbarMaxValue = 50;
private SeekBar seekBar;
private Context context;
private OnDWSeekBarListener listener;
private LayoutParams lp;
public interface OnDWSeekBarListener {
public void onStopSeekbarValue(double value);
}
public DWRulerSeekbar(Context context) {
super(context);
this.context = context;
init();
}
public DWRulerSeekbar(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public DWRulerSeekbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
public DWRulerSeekbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.context = context;
init();
}
private void init() {
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
if (getHeight() > 0) {
addCompoenet();
getViewTreeObserver().removeOnPreDrawListener(this);
}
return false;
}
});
}
private void addCompoenet() {
removeAllViews();
LineRulerView lineRulerView = new LineRulerView(context);
LayoutParams rulerLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getHeight() / 3 * 2);
rulerLayoutParams.setMargins(0, 5, 0, 0);
rulerLayoutParams.addRule(CENTER_IN_PARENT);
lineRulerView.setLayoutParams(rulerLayoutParams);
lineRulerView.setMinMaxValue(4, 21);
lineRulerView.setBackgroundColor(Color.TRANSPARENT);
addView(lineRulerView);
DisplayMetrics metrics = getResources().getDisplayMetrics();
int densityDpi = (int)(metrics.density * 160f);
seekBar = new SeekBar(context);
lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 60);
seekBar.setThumb(getResources().getDrawable(R.drawable.green_round_circlebg));
seekBar.setProgressDrawable(getResources().getDrawable(R.drawable.seekbar));
seekBar.setProgress(0);
seekBar.setVisibility(View.VISIBLE);
seekBar.setBackgroundColor(Color.TRANSPARENT);
seekBar.setLayoutParams(lp);
seekBar.setMax(15);
seekBar.setOnSeekBarChangeListener(this);
addView(seekBar);
}
public DWRulerSeekbar setDWRulerSeekbarListener(OnDWSeekBarListener listener) {
this.listener = listener;
return this;
}
public DWRulerSeekbar setMinMaxValue(int seekbarMinValue, int seekbarMaxValue) {
this.seekbarMinValue = seekbarMinValue;
this.seekbarMaxValue = seekbarMaxValue;
addCompoenet();
return this;
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (listener != null) {
listener.onStopSeekbarValue(seekbarMinValue + progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
and in xml you have to add this
<com.xelpmoc.zommodity.customseekbar.DWRulerSeekbar
android:id="#+id/dwRulerSeekbar"
android:layout_width="match_parent"
android:layout_marginTop="10dp"
android:layout_height="75dp">
</com.xelpmoc.zommodity.customseekbar.DWRulerSeekbar>
To get the values from seekbar add this in activity
private void initDWSeekbar() {
seekbar_ruler = (DWRulerSeekbar) findViewById(R.id.dwRulerSeekbar);
seekbar_ruler
.setMinMaxValue((int) MIN_VALUE, (int) MAX_VALUE)
.setDWRulerSeekbarListener(new DWRulerSeekbar.OnDWSeekBarListener() {
#Override
public void onStopSeekbarValue(double value) {
timeslorval=value;
}
});
}
seekbar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:height="5dp" android:gravity="center"
android:id="#android:id/background"
android:drawable="#drawable/seek_bar_background"/>
<item android:height="5dp" android:gravity="center"
android:id="#android:id/progress"
android:drawable="#drawable/seek_bar_progress" />
</layer-list>
and green_round_circlebg.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:width="20dp" android:height="20dp">
<shape android:shape="oval" >
<solid android:color="#2CC285"></solid>
<stroke android:color="#000000" android:width="1dp"></stroke>
</shape>
</item>
</layer-list>
I'm rotating an ImageView by using an Animation defined by a XML file.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<rotate
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="90"
android:fillAfter="true" />
</set>
Although ImageView has the getRotation() method , it only returns the first value that has been set to the image object.
Is there anyway to get the current rotation degrees by using a XML animation? If not, what should be the best way to go with it?
public class CustomImageView extends ImageView {
private ObjectAnimator rotationAnimator;
public CustomImageView(Context context) {
super(context);
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setRotation(float rotation) {
super.setRotation(rotation);
// Do something
}
public synchronized void startAnimation(int animationDuration) {
if (rotationAnimator == null || !rotationAnimator.isRunning()) {
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf2 = Keyframe.ofFloat(0.5f, 180f);
Keyframe kf1 = Keyframe.ofFloat(1f, 360f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
rotationAnimator = ObjectAnimator.ofPropertyValuesHolder(this, pvhRotation);
rotationAnimator.setRepeatCount(ObjectAnimator.INFINITE);
rotationAnimator.setInterpolator(new LinearInterpolator());
rotationAnimator.setDuration(animationDuration);
rotationAnimator.start();
}
else {
// Already running
}
}
Version 2, since you are having problems
public class CustomImageView extends ImageView {
private ObjectAnimator rotationAnimator;
private float myRotation;
public CustomImageView(Context context) {
super(context);
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setMyRotation(float rotation) {
this.myRotation = rotation;
Log.d("CustomImage", "Rotation: " + rotation);
invalidate();
}
public synchronized void startAnimation(int animationDuration) {
if (rotationAnimator == null || !rotationAnimator.isRunning()) {
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf2 = Keyframe.ofFloat(0.5f, 180f);
Keyframe kf1 = Keyframe.ofFloat(1f, 360f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("myRotation", kf0, kf1, kf2);
rotationAnimator = ObjectAnimator.ofPropertyValuesHolder(this, pvhRotation);
rotationAnimator.setRepeatCount(ObjectAnimator.INFINITE);
rotationAnimator.setInterpolator(new LinearInterpolator());
rotationAnimator.setDuration(animationDuration);
rotationAnimator.start();
}
else {
// Already running
}
}
public synchronized void stopAnimation() {
if (rotationAnimator != null) {
rotationAnimator.cancel();
rotationAnimator = null;
}
}
public synchronized boolean getAnimationRunning() {
return rotationAnimator != null && rotationAnimator.isRunning();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.rotate(myRotation, getWidth() / 2.0f, getHeight() / 2.0f);
super.onDraw(canvas);
}
}
Sample logcat output:
04-22 22:48:55.475 16341-16341/animation.example.com.animationdemo D/CustomImage﹕ Rotation: 358.44
04-22 22:48:55.490 16341-16341/animation.example.com.animationdemo D/CustomImage﹕ Rotation: 0.48000813
04-22 22:48:55.505 16341-16341/animation.example.com.animationdemo D/CustomImage﹕ Rotation: 2.4
04-22 22:48:55.525 16341-16341/animation.example.com.animationdemo D/CustomImage﹕ Rotation: 4.44
I have packed the code into a simple project: LINK
I want to implement a scale animation to View (or ImageView) when it gets focus. Here is my current implementation:
public class ScaleFocusImageView extends ImageView {
private Context mContext;
public ScaleFocusImageView(Context context, AttributeSet attr) {
super(context, attr);
mContext = context;
}
#Override
protected void onFocusChanged (boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if(gainFocus) {
Animation a = AnimationUtils.loadAnimation(mContext, R.anim.scale_up);
this.startAnimation(a);
}
}
}
And here is my animation xml 'scale_up.xml':
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="1.5"
android:fromYScale="1.0"
android:toYScale="1.5"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="175"/>
</set>
I can't get the scale effect when got focus in the end, I just see it scale quickly and shrink to original as normal. Why does this implementation not work how I expect, and how can I fix it?
Ok now try this updated code:--
this is the class for imageview:--
public class ScaleFocusImageView extends ImageView {
private Context mContext;
boolean flag;
public ScaleFocusImageView(Context context, AttributeSet attr) {
super(context, attr);
mContext = context;
}
#Override
protected void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (gainFocus) {
zoom(1f, 1f, new PointF(getWidth() / 2, getHeight() / 2));
} else {
zoom(2f, 2f, new PointF(getWidth() / 2, getHeight() / 2));
}
}
/** zooming is done from here */
#SuppressLint("NewApi")
public void zoom(Float scaleX, Float scaleY, PointF pivot) {
setPivotX(pivot.x);
setPivotY(pivot.y);
setScaleX(scaleX);
setScaleY(scaleY);
}
}
Add this to your XML animation:
android:repeatMode="reverse"
By reversing the animation, the image won't be loaded shrinked but the animation will follow the reverse scale.
The xml animation file will be like this now:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="1.5"
android:fromYScale="1.0"
android:toYScale="1.5"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="3000"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
Because checkbox isnt an option for my project I want the checkable to have a background when checked.Supporting from 2.3 i havent manage to solve this problem yet.
Selection is correct but what i see at screen isnt.Random color at random row..
Fist i have this
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/abs__list_selector_holo_light" />
<item android:state_checked="true" android:drawable="#drawable/abs__list_selector_holo_light" />
<item android:state_selected="true" android:drawable="#drawable/abs__list_selector_holo_light" />
<item android:drawable="#drawable/abs__list_selector_holo_light" />
</selector>
-
public class CheckableRelativeLayout extends RelativeLayout implements
Checkable {
private boolean isChecked;
private List<Checkable> checkableViews;
private static final int[] CheckedStateSet = {
R.attr.state_checked
};
public CheckableRelativeLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
initialise(attrs);
}
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initialise(attrs);
}
public CheckableRelativeLayout(Context context, int checkableId) {
super(context);
initialise(null);
}
/*
* #see android.widget.Checkable#isChecked()
*/
public boolean isChecked() {
return isChecked;
}
/*
* #see android.widget.Checkable#setChecked(boolean)
*/
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
for (Checkable c : checkableViews) {
c.setChecked(isChecked);
}
}
/*
* #see android.widget.Checkable#toggle()
*/
public void toggle() {
this.isChecked = !this.isChecked;
for (Checkable c : checkableViews) {
c.toggle();
}
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
final int childCount = this.getChildCount();
for (int i = 0; i < childCount; ++i) {
findCheckableChildren(this.getChildAt(i));
}
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CheckedStateSet);
}
return drawableState;
}
#Override
public boolean performClick() {
toggle();
return super.performClick();
}
/**
* Read the custom XML attributes
*/
private void initialise(AttributeSet attrs) {
this.isChecked = false;
this.checkableViews = new ArrayList<Checkable>(5);
}
/**
* Add to our checkable list all the children of the view that implement the
* interface Checkable
*/
private void findCheckableChildren(View v) {
if (v instanceof Checkable) {
this.checkableViews.add((Checkable) v);
}
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
final int childCount = vg.getChildCount();
for (int i = 0; i < childCount; ++i) {
findCheckableChildren(vg.getChildAt(i));
}
}
}
}
What i get is this
Here's a clean example on making a Checkable View:
import android.R;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.LinearLayout;
public class ActivatedLinearLayout extends LinearLayout implements Checkable{
public static final int[] CHECKED_STATE = {R.attr.state_checked};
private boolean mChecked;
public ActivatedLinearLayout(Context context) {
super(context);
}
public ActivatedLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ActivatedLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setChecked(boolean b) {
mChecked = b;
refreshDrawableState();
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
mChecked = !mChecked;
refreshDrawableState();
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] states = super.onCreateDrawableState(extraSpace + 1);
if (mChecked){
mergeDrawableStates(states, CHECKED_STATE);
}
return states;
}
}
And selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#drawable/checked"/>
<item android:drawable="#drawable/unchecked"/>
</selector>