How to set button height less then 30px? I tried the next:
setHeight(30); (set 150 is working, but set 30 is not)
setPadding(0,-20,0,-20); (width is changes, height is not)
LinearLayout.LayoutParams (set 150 is working, but set 30 is not)
new Button(this, null, android.R.attr.buttonStyleSmall); - effects only on button text
Button mainButton = new Button(this);
mainButton.setPadding(0, 0, 0, 0);
mainButton.setLayoutParams(new LayoutParams(FlowLayout.LayoutParams.WRAP_CONTENT,FlowLayout.LayoutParams.WRAP_CONTENT));
l.addView(mainButton);
SmallButton mainButton = new SmallButton(this);
mainButton.setText(s);
mainButton.setBackgroundResource(R.drawable.button_drawable);
mainButton.setLayoutParams(new LayoutParams(FlowLayout.LayoutParams.WRAP_CONTENT,FlowLayout.LayoutParams.WRAP_CONTENT));
l.addView(mainButton);
public class SmallButton extends Button {
public SmallButton(Context context) {
super(context);
}
public SmallButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SmallButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, 35));
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(0,-5);
super.onDraw(canvas);
canvas.restore();
}
}
I have a Shape drawable with gradient for my background as I don't know the exact width. I also tried to setup its height. Is it possible to make button wrap it text only?
EDIT:
The problem is solved with the use of TextView instead of the Button. Ofcourse if you are not using the specific/overriden things in Button.class.
There are two parameters.
Button.setMinimumHeight() and Button.setMinHeight(). Ensure that both of them are set to value "0".
Every View in Android can have a minimum width and height set for them. A Button will set these depending on the style it is using on the device it is using.
However, this can be overridden in the xml for the button:
android:minHeight="0dip"
android:minWidth="0dip"
As #Sudar Nimalan points out, this is related to the background of the button. If you don't wish to create your own button class, you can simply set the background to something smaller. Try setting the background to a solid colour, or create your own background for it.
try this
mainButton.setIncludeFontPadding(false);
I think, This causes due the default background drawable minimum height size, you can sent a empty background or color and test these scenarios.
If you want to change the height with default drawable, you can create your Custom Button extending the Button class and override on onMeasure and onDraw etc.
override the onDraw to shift the default button drawing:
onDraw(canvas){
canvas.save();
canvas.translate(0,value to shift);
super.onDraw(canves);
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, 35));
}
Related
I wrote a custom text view(it doesn't matter what kind of view actually) that extends from View. I added padding to this view in my XML document and read these padding and pass it to super to apply these padding. And in my onDraw and onMeasure I also took these padding into consideration and everything works just fine.
EXCEPT, if I scroll this view via the method View.scrollTo(), the padding no longer works. By saying no longer works, I mean the content that drawn on canvas doesn't respect the view's padding, like the images shown below:
I want to know if there's any workaround on this?(PS: don't tell me to use TextView instead of making my own. I'm doing this for some reason, the only problem I want to solve here is just the padding stuff, not some brilliant alternatives, thanks!)
EDIT:
my xml
<com.example.custom.MyTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text_area"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/text_bg"
android:padding="10dp"/>
and in my constructor:
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// by calling super, the super class will take care of the paddings
// internal, and after this, I just have to get the paddings by
// getPaddingTop(),getPaddingLeft(),getPeddingRight(),getPaddingBottom() etc.
}
and in my onMeasure:
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
......
setMeasuredDimension(getPaddingLeft()+contentWidth+getPaddingRight()
,getPaddingTop()+contentHeight+getPaddingBottom());
//whereas the contentWidth and contentHeight is determined by the widthMeasureSpec
// and heightMeasureSpec and some certain logic inside the view.
// I don't think this will cause the view's content to exceed the conten area
}
and in my onDraw:
public void onDraw(Canvas canvas){
Path path = new Path();
for(String eachLine: text){
path.moveTo(startX,startY);
path.lineTo(endX,endY);
canvas.drawTextOnPath(eachLine,path,0,0,painter);
...
}
....
//the startX,startY,endX, endY has already took the padding into consideration.
//*NOTE: The only solution that I can think of is that I control this
//drawing logic according to the padding. But this approach still won't fix the
//problem, for example: what if I scroll half line height? How do I draw the
//half of the line? So there must be some other approach that I don't know.
}
I have one imageView and I am trying to give it minus margin top as much as its height / 2. I can do it at programmatically but i wondred is it possible at xml also andorid published percentrelative layout . I don't know how to to do it or possible?
--Edit: As #aga suggests, there seems to be a way to achieve it via the Percent Support Library--
If you want to use this type of imageView more often throughout your application you could extend imageview and put your margin-code inside of it's onMeasure:
public class HalfMarginImageView extends ImageView {
public HalfMarginImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
((ViewGroup.MarginLayoutParams) getLayoutParams()).topMargin = -getMeasuredHeight() / 2;
}
}
for this to work the view must be part of a ViewGroup.Also make sure you use the constructor with AttributeSet, oltherwise you can't create the View from xml. Yo then just include a CustomView in your layout xml, select HalfMarginImageView and use it as normal imageView.
I have LinearLayout which contains two Button widgets with layout_weight=1. Depends on length of Button's text or screen resolution I get buttons with rectangular form (gray rectangles) but I need to keep the square form (blue squares).
I was trying to change height of LinearLayout param in onStart() method, depends on Button's width, but getWidth() returns 0. I understand that it's because view at that moment still not rendered. Please, help me to solve my problem.
There are many ways to achieve this. If you need to find the real width of an element, you can:
1) attach an OnGlobalLayoutListener to the view's ViewTreeObserver (but remember to remove it when you are done)
2) or you can manually measure what you need:
if(view.getMeasuredHeight() == 0){
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(metrics);
view.measure( metrics.widthPixels, metrics.heightPixels );
}
int realHeight = view.getMeasuredHeight();
//...your code
You are exactly right because at that time view will not be drawn so for that you have to use viewtreeobserver:
like this:
final ViewTreeObserver treeObserver = viewToMesure
.getViewTreeObserver();
treeObserver
.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
System.out.println(viewToMesure.getHeight()
+ "SDAFASFASDFas");
heith = viewToMesure.getHeight();
}
});
this view tree observer will be called after creating the view based on that you calculate and you can change.
You can use a custom view to set the view's height to be tha same as its width by overriding onMeasure:
public class SquareButton extends Button {
public SquareButton (Context context) {
super(context);
}
public SquareButton (Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareButton (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
}
}
All you have to is use the custom button in your xml layout and you don't have to do anything in the activity:
<com.package.name.SquareButton
android:layout_with="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
I'm trying to create a custom TextView. I look here for my guidance as well and I made it working, though I'm still confused by why the other component is not being drawn, this is just more simple than the reference guide of android but it's not working in mine.
From the custom class I made (CustomTextView w/c extends TextView),
I try to add a OnTouchListener() and invoke the invalidate() method for both this and other component w/c is a TextView but it still not being drawn.
CustomTextView.java
public class CustomTextView extends TextView {
TextView extra_detail;
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
extra_detail = new TextView(context);
extra_detail.setText("Hey!");
extra_detail.setPadding(20, 0, 0, 0);
extra_detail.setTextSize(2);
a.recycle();
//I also tried this in case the space isn't enough
setMinHeight(80);
extra_detail.invalidate();
this.invalidate();
}
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Here's my problem
//both are not being drawn
//even if I remove the other one and vice-versa
canvas.drawText("Hey", 10, 0, paint);
extra_detail.draw(canvas); //is this the right way to do this?
}
#Override
public boolean onTouchEvent(MotionEvent event) {
invalidate();
extra_detail.invalidate();
//still not being drawn
//after the invalidation
Toast.makeText(getContext(), "Hey!", Toast.LENGTH_SHORT).show();
return super.onTouchEvent(event);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
extra_detail.measure(widthMeasureSpec, heightMeasureSpec);
}
}
It seems I'm missing something here but cannot figure it out.
Update
I happen to extend my Activity with ActionBarActivity. Now with this kind of pre defined Activity, there is a title bar implemented and its hiding all the canvas.draw*() I made on the top-left-most of the screen. I figure it out after I invoke the setY(10) then the canvas.drawText() appears.
But I still have the problem of drawing another View in onDraw() event.
I have a custom Button and I want to set its dimensions in code (as opposed to in xml), so that users can customize the dimensions. The seemingly obvious way to this is:
public class MyButton extends Button
{
public MyButton(Context context, AttributeSet attrs)
{
super(context, attrs);
int buttonSize = getSize();
setLayoutParams(new LinearLayout.LayoutParams(buttonSize, buttonSize));
}
However, this fails to be generic because it only works if the Button's parent is a LinearLayout. Instead, I tried this:
#Override
protected void onMeasure(int specw, int spech)
{
int spec = MeasureSpec.makeMeasureSpec(getButtonSize()), MeasureSpec.EXACTLY);
super.onMeasure(spec, spec);
}
...which seems to work well. Is anyone aware of any shortcomings to this? or aware of a better way to generically set widget dimensions in code?
Doing it from onMeasure() is a good way to do it (even though your code doesn't work since you're not using the measure spec you've created.) You could also override onFinishInflate() and call getLayoutParams() and change the width and height fields.