Can anyone explain to me why this is happening?
I have a fairly simple class extending TextView. When I set the background colour to Color.BLUE, padding works fine. When I change the background resource to android.R.drawable.list_selector_background, my padding is no longer applied. What the F?
Here is my UI class:
public class GhostDropDownOption extends TextView {
TextView text_view;
public GhostDropDownOption(Context context, AttributeSet attrs) {
super(context, attrs);
setup(context);
}
public GhostDropDownOption(Context context) {
super(context);
setup(context);
}
private void setup(Context context) {
this.setClickable(false);
// THE 2 LINES BELOW ARE THE ONLY THING I'M CHANGING
//this.setBackgroundResource(android.R.drawable.list_selector_background);
this.setBackgroundColor(Color.BLUE);
}
}
And I'm using it in the layout like this:
<trioro.voyeur.ui.GhostDropDownOption
android:id="#+id/tv_dropdown_option_1"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="#string/request_control_dropdown_option_1"
android:textColor="#000000"
android:padding="10dip"/>
And this is the result of changing the background:
The call to:
this.setBackgroundResource(android.R.drawable.list_selector_background);
will remove any previosly set padding (this is to make it work properly with 9-patch assets).
Try to set the padding in code after the line above, like this:
this.setPadding(PADDING_CONSTANT, PADDING_CONSTANT, PADDING_CONSTANT, PADDING_CONSTANT);
Just remember that the values sent to setPadding is in pixels NOT dip!
You should set your background drawable in XML if at all possible. If you set it in code, it will use the padding from your drawable resources rather than what you set in XML, so if it's necessary to do it programmatically, you'll want to retrieve the current padding, store it temporarily, set the background, and then set the padding back as #TofferJ suggests.
The reason for this is that the drawables themselves can have padding, in the case of 9-patch images (where the bottom and right pixel borders define the amount of padding).
Your solution should be to just set your background resource in XML:
android:background="#android:drawable/list_selector_background"
although I believe that may be a private drawable resource that you'll have to copy into your project first.
Related
I am trying to create a custom preference used in a fragment. That preference will have an icon, a long text and a hyperlink to link somewhere.
For that I create a class that extends androidx.preference.Preference
The constructor is this:
public MyCustomPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWidgetLayoutResource(R.layout.my_custom_preference_layout);
}
I get it to work correctly and all that, but the problem is that its height is way too short. The preference size doesn't fit its content. It seems like it is always the same size. About two lines of text only.
I have tried with
android:singleLine="false"
android:minLines="50"
but nothing. The preference is displayed way too short.
Is there any limitation in the height of custom preferences?
I use a RelativeLayout for the layout and add the controls I need to it.
that Relative Layout have these values:
android:layout_width="match_parent"
android:layout_height="wrap_content"
I have tried setting match_parent to both, even setting a fixed value, for example 500dp, but it is always displayed in small height.
I've created a custom view which extends RelativeLayout, and I want to preview how it looks in the designer.
The java is something like this:
// The view for a snap in the search/browse fragment.
public class MyView extends RelativeLayout
{
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.the_layout, this);
}
public void setData(String text)
{
mText.setText(text);
}
// *** Views ***
private TextView mText;
#Override
protected void onFinishInflate()
{
super.onFinishInflate();
mText = (TextView)findViewById(R.id.text);
}
}
And the XML is like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- (And lots more views) -->
</RelativeLayout>
There are a few problems with this however:
This actually creates a RelativeLayout within a RelativeLayout which is pointless. It can be solved by changing the XML <RelativeLayout> to a <merge> but then I can't preview the layout at all!
I want to use the isInEditor() function (or whatever it is called) in the java to add some sample data for previewing purposes, but I can't find a way to tell the XML editor that it should display a preview of my class instead of the actual XML.
One unsatisfying solution I can think of is to create an empty preview.xml file with only <com.foo.bar.MyView/> in it... But that seems kind of silly. Is there a better way? (I don't really care about editing as much as previewing, since - let's face it - Eclipse/ADT are way too slow and flaky to make graphical layout editing usable.)
If I understand your problem correctly I would say that the solution is to just replace the "RelativeLayout" tags (or any other tag for that matter) in your xml layout with "your.packagename.MyView" as in:
<your.packagename.MyView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- (And lots more views) -->
</your.packagename.MyView>
If you'll get any exceptions regarding MyView class while running your app, add all the missing super/parent constructors.
I do this for almost all of my custom xml layouts. Extending your class with RelativeLayout, LinearLayout or any other GUI class also gives you great controll over how your GUI should behave (because you can also override parent methods etc.).
I created a background image bitmap for a view and now the view is being stretched to the size of the background image....
is this normal?
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/green"
android:tileMode="repeat"/>
here's how I apply it to my view
v.setBackgroundResource(R.drawable.backgroundgreen);
for instance...
if the image is 500px in height
and the view is 200px in height(being set wrap_content as height)
after setting the image as background my view becomes 500px in height...
I have faced this same problem.
If the background image has a size that is bigger than the view's size, the view's size will change to match the image's size.
Solution
Put the view inside a Relative Layout.
Remove the background image.
Add an ImageView before the View inside the Relative Layout
Set the src of the ImageView to your background image
<RelativeLayout
.
.
. >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/yourViewId"
android:layout_alignRight="#+id/yourViewId"
android:layout_alignTop="#+id/yourViewId"
android:layout_alignBottom="#+id/yourViewId"
android:adjustViewBounds="true"
//this will allow the image to resize with same proportions
android:src="#drawable/yourDrawable" />
<YourView
android:id="#+id/yourViewId"
.
..
... />
</RelativeLayout>
This all can be done in code of course.
According to me, the problem you are facing is not a problem, it is the way how Android is used to design the layouts.
This means that you can set the height and width with 3 default constant values:
FILL_PARENT
Special value for the height or width requested by a View. FILL_PARENT means that the View wants to be as big as its parent, minus the parent's padding if any. This value is deprecated starting in API Level 8 and replaced by MATCH_PARENT.
MATCH_PARENT
Special value for the height or width requested by a View. MATCH_PARENT means that the view wants to be as big as its parent, minus the parent's padding if any. Introduced in API Level 8.
WRAP_CONTENT
Special value for the height or width requested by a View. WRAP_CONTENT means that the View wants to be just large enough to fit its own internal content, taking its own padding into account.
Now, when you are setting the View's height/width to WRAP_CONTENT, you are allowing the view to take that much size that is sufficient to show to view's content. The background image is also the View's content, hence you view will be shown of as much size as the image. That's not a problem, that's how it's shown.
Okay, but in your situation that's an issue for you because you have a background to show and view should not be stretched for that. I can suggest few ways:
First and very obvious: make correctly sized images and keep them in different drawable folders.
Specify the size of view not using constants, but in DP. If it becomes necessary, make different layout XML files for different sizes and keep them in layout folders.
You can use a very useful thing for design layout is layout weight.
I suggest to create a wrapper layout and put the background image in there. i'm using it that way and fits very nicely.
see example below
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/settingstab_scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"
android:background="#drawable/wareninja_wallpaper_img"
>
<!-- your layouts and components goes here -->
</ScrollView>
...
Social Coding # AspiroTV
The reason is quite simple. You gotta see the View::getSuggestedMinimumWidth/Height method.
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
protected int getSuggestedMinimumHeight() {
return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
}
Seeing that, you may know why the background makes a view bigger, especially why assign a BitmapDrawable to it.
and the simple solution is to wrap that Drawable (eg. BitmapDrawable), then returns 0 for getMinimumHeight() and getMinimumWidth(), and better to override getIntrinsicHeight() and getIntrinsicWidth() to returns -1.
support-v7 has a DrawableWrapper which delegates calls to another drawable when necessary. you can extends that one and override methods talked above.
and if you don't use support-v7 (WoW! you are awesome), copy that class to your project is also fine.
https://android.googlesource.com/platform/frameworks/support/+/1949ae9aeaadf52ad7bd7bb74ca5419c67ea7f65/v7/appcompat/src/android/support/v7/internal/widget/DrawableWrapper.java
It's working for me.
< ?xml version="1.0" encoding="utf-8"?>
< LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/LinearLayoutTest">
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.prueba);
((LinearLayout)findViewById(R.id.LinearLayoutTest)).setBackgroundResource(R.drawable.greenrepeat);
}
in your code, what is v? It has params to fill_parent?
Don't use android:tileMode="repeat". Is your green drawable bigger or smaller than your view? Could add more details?
One good solution that is working perfectly in my case is extending the View and overriding onMeasure().
Here is the steps to do:
Create an own class and extend the View you want to use, here for
example I will use Button.
Override the method onMeasure() and insert the code at the bottom. This will set the background resource after the first measure has been done. For the second measure event, it will use the already measured paramters.
Example code for a custom view which extends Button (change Button to the View you would like to extend)
public class MyButton extends Button {
boolean backGroundSet = false;
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(backGroundSet) {
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
return;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
backGroundSet = true;
setBackgroundResource(R.drawable.button_back_selector);
}
}
The only thing to change here is the type of view you want to extend and in the onMeasure() method the background resource you want to use for the view.
After that, just use this view in your layout xml or add it programatically.
I modify Sherif elKhatib's code, now this works for me:
if we want background picture be stretched as view picture:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/yourViewId"
android:layout_alignTop="#+id/yourViewId"
android:layout_alignEnd="#+id/yourViewId"
android:layout_alignBottom="#+id/yourViewId"
android:scaleType="fitXY"
android:src="#drawable/bg_very_big_picture" />
<LinearLayout
android:id="#+id/yourViewId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
if we want background picture not to be stretched, but to be cutted to fit view picture:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/yourViewId"
android:layout_alignTop="#+id/yourViewId"
android:layout_alignEnd="#+id/yourViewId"
android:layout_alignBottom="#+id/yourViewId"
android:scaleType="centerCrop"
android:src="#drawable/bg_very_big_picture" />
<LinearLayout
android:id="#+id/yourViewId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
I have a list, each row in the list has text. Some of the text extends beyond the edge of the screen. I have no problem making it truncate the text and show ellipses. I have no problem to 'fade the edge of the text' however, the fade occurs at the edge of every text, not just the ones the are too large for the textview.
I have searched and searched and can't find a way to, essentially, do exactly what the ellipses do, but, instead of ellipses, fade the edge of the text only if it is going off the edge of the screen. Can anyone please help? Right now, my text view contains:
android:fadingEdge="horizontal"
android:inputType="text"
android:maxLines="1"
I have tried many other things to no avail.
To enable marquee and simulateouly not affecting the list Selections Just use following:
In the code just use two methods on that text View.
textViewObj.setSelected(true);
textViewObj.setEllipsize(TextUtils.TruncateAt.MARQUEE);
The specific method call to enable the horizontal edge fade (on the right-hand side) is
setHorizontalFadingEdgeEnabled(true)
Here is an example from the constructor in my class ScrollTextView, which extends TextView:
public ScrollTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
setHorizontalFadingEdgeEnabled(true);
}
I am making a small app for Android, where I have a RelativeLayout, which amongst other things contains a custom ImageView. In my Java code I have this class:
package com.example.android.helloactivity;
class ArrowImageView extends ImageView {
public ArrowImageView(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(10,10,10,null);
}
}
Then in my RelativeLayout xml I have the following:
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#FFF"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button ...... />
<TextView ......./>
<com.example.android.helloactivity.ArrowImageView
android:id="#+id/hello_activity_bearingarrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
When I run my main class (not shown here) then my program crashes. If I omit the xml reference to ArrowImageView, then it does not crash.
Am I referring to my custom class te wrong way, or what is going on?
When extending the View widgets, if you plan to use them in XML layouts you need to also override the constructors that take the AttributeSet argument.
First don't extend ImageView but just View, unless there is something special about ImageView that you know and want to use.
Second, as Leffel said, you need to state attribute set like this
public ArrowImageView(Context context, AttributeSet set) {
super(context, set);
}
Also you may need to give some size to the custom view by setting witdh and height to something like 100dp. I am not sure what a custom View can "wrap" when there is no other views inside.
Thanks for the answers. I found a bug in the onPaint method itself which still made things crash. After implementing your suggestions and changing the onPaint into:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.MAGENTA);
canvas.drawCircle(10,10,10,paint);
}
everything worked!
Thank you very much for your help :-)