I've a custom view that extend from view now I want to compound two of them in one and make a new custom view. Now I want to know whether I should redraw my child views in new custom view or there is a way to add them in new custom view.
public class Selector extends View {
// properties and methods
private void init(Context context) {
}
public Selector(Context context) {
super(context);
init(context);
}
public Selector(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// set measures
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// drawing
}
}
Now I want to compound two of Selectors in a view. how can I do it? Thanks
you could try something like this
public class myView extends LinearLayout {
public myView(Context context) {
super(context);
addView(new Selector(context));
addView(new Selector(context))
}
}
Related
I'm trying to animate adding child views to a LinearLayout. Just wanted to know if there is a better way to go about this or if this approach have any drawbacks.
And if this post helped don't forget to up vote :)
Here is what I did:
public class CardLayout extends LinearLayout {
public CardLayout(Context context) {
super(context);
initLayoutObserver();
}
public CardLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initLayoutObserver();
}
#Override
public void addView(View child) {
super.addView(child);
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up_in);
animation.setStartOffset(getChildCount() * 100 + getResources().getInteger(R.integer.screen_transition_time_fade_in));
child.startAnimation(animation);
}
}
I have a class MyLayout extending RelativeLayout which includes View type field. MyLayout object is created in xml layout file, so all properties are set there. I need to programatically set size of View field which depends on size of it's parent (MyLayout).
I was trying to set it in constructor, but when I try to use getWidth() method, it returns 0, so I assume that the size is not yet set inside a constructor. I was also trying to set it in onDraw() method, but when I run an application, this internal View is displayed for like second with it's default size and after that time it's scaled to the right size. Then I tried putting it inside onMeasure() method, but this one is called a few times, so again it doesn't seem to be efficient at all.
So what could be the best place to set it?
This is my class:
public class MyLayout extends RelativeLayout {
private View pointer;
public MyLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyLayout(Context context) {
super(context);
init(context);
}
private void init(Context c) {
pointer = new View(c);
pointer.setBackgroundResource(R.drawable.pointer);
addView(pointer);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams();
lp.height = (int)(getHeight() * 0.198);
lp.width = (int)(getWidth() * 0.198);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
in your MyLayout class, override onSizeChanged():
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams();
lp.height = (int)(getHeight() * 0.198);
lp.width = (int)(getWidth() * 0.198);
};
I'm fairly proficient at creating complex custom layouts based on ViewGroup. The only thing I'm missing is the ability to create my custom LayoutParams. I really need the ability to get the margins and why not create other extra params to pass in to the parent.
How can I go about creating a custom LayoutParam and using it via xml? I tried using a LinearLayout.LayoutParam but it's obviously crashing since the parent is not a LinearLayout. How can I work with LayoutParams on custom layouts?
Update:
As of now I'm sticking with using a FrameLayout and overriding the onMeasure and onLayout functions to do the layout myself. This does provide FrameLayout.LayoutParams. I'm guessing the childs would have to support the custom LayoutParam?
In your custom layout, create a nested class extending ViewGroup.LayoutParams. Then override some methods (all of the required ones are in my example). Here's a stripped-down version of one of my custom layouts:
public class MyLayout extends ViewGroup {
public MyLayout(Context context) {
}
public MyLayout(Context context, AttributeSet attrs) {
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams();
}
#Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
#Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return generateDefaultLayoutParams(); // TODO Change this?
}
public static class LayoutParams extends ViewGroup.LayoutParams {
public LayoutParams() {
}
public LayoutParams(int width, int height) {
}
public LayoutParams(Context context, AttributeSet attrs) {
}
}
}
Further explanation: How to create a FlowLayout (thanks for the link Luksprog!)
I want to do a custom horizontal navigation bar, which consists of as many dots as i have pages.
My thoughts are:
Create a Custom ListView
Create Class Dot extends from View
Add all these dots to the custom listview dynamically..
Is this right to do so?
EDIT:
public class NavigationBarLesson extends LinearLayout {
private LessonConfig config = LessonConfig.getInstance();
private ArrayList<NavigationCircle> navigationCircles;
private int pageCount;
public NavigationBarLesson(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public NavigationBarLesson(Context context) {
super(context);
init(context);
}
private void init(Context context) {
Log.i("init","yes");
pageCount = config.getLektionCount();
navigationCircles = new ArrayList<NavigationCircle>();
for(int i=0; i < pageCount; i++){
this.addView(new NavigationCircle(context));
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
}
public class NavigationCircle extends ImageView{
private static Bitmap img;
private Bitmap activeImg;
public NavigationCircle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public NavigationCircle(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public NavigationCircle(Context context) {
super(context);
init();
}
public void init() {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(0, 0, 5, 0);
this.setLayoutParams(lp);
this.setBackgroundResource(R.drawable.upcoming_pages);
}
public Bitmap getImg() {
return img;
}
public Bitmap getActiveImg() {
return this.activeImg;
}
}
Well, I do not see why you would need a ListView. Create a horizontal LinearLayout with some simple views like TextView's or ImageView's etc added dynamically to the LinearLayout.
I have a custom ImageView('CustomImageView') and an Edit-text in a linear layout of an activity 'ImageViewActivity'. The Edit-text is initially set invisible. When the customimageview is touched, and onDraw() is called, I want the visibility of the Edit-text to be set visible. Where should I put the code for this?
Code for ImageViewActivity:
public class ImageViewActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_imageview);
}
}
And the code for CustomImageView is:
public class CustomImageView extends ImageView {
Paint paint = new Paint();
float xp = -1, yp = -1;
private Options opt;
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
xp = event.getX();
yp = event.getY();
invalidate();
}
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//some code
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (xp >= 0 && yp > 0) {
canvas.drawCircle(xp, yp, 20, paint);
}
}
}
Implement touch listener on your customImageview class and then call the edittext to hide it or show is as you need, for results of touch on custom view you have to define touchlistener on your customview not of activity and you can manage views of parent activity in touchevent of customview OR other method is implement touch listener on you activity and find the view which is touched if touched view is your custom view then make visible your Edittext. Then you will not need to do anything in onDraw() as regarding the edittext.
I'd recommend setting the view to visible once you have detected a touch motion on your particular view. Specifically it doesn't matter how the user touches it, since once they touch it you want to show your view (at least that is what you said you wanted).