I know how to change to color of the Headings inside a PreferenceCategory.
public class PreferenceCategory1 extends PreferenceCategory {
public PreferenceCategory1(Context context) {
super(context);
}
public PreferenceCategory1(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PreferenceCategory1(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setTextColor(Color.rgb(238, 120, 30));
}
}
But I also want to change the Divider between the PreferenceCategory and the elements beneath. I've tried to grab the listview and using the setDivider() method:
ListView v = (ListView)view.findViewById(android.R.id.list);
v.setDivider(new ColorDrawable(Color.rgb(238, 120, 30)));
But this causes a NullPointerException due to the fact that it can't find the list in this view. I am aware that I can set this in an xml file and add this as a style, but I want, if possible to do this in java. Any suggestions?
Related
I have a xml layout with an element i use multiple times... so i decided to use <include> in the xml to avoid excess code.
My problem is that i want to make a class that is connected to this included xml component and reference to it, rather than writing the same code multiple times.
I tried to read up on a custom view component and created a class ParcelPopbarView:
public ParcelTopBarView extends View {
/...
public ParcelTopBarView(Context context, ParcelListItem parcelListItem) {
super(context);
this.parcelListItem = parcelListItem;
this.context = context;
titleTextView = findViewById(R.id.title_textview);
subtitleTextView = findViewById(R.id.subtitle_textview);
deliveryInfoTextView = findViewById(R.id.delivery_info_textview);
thumbnailLogo = findViewById(R.id.thumbnail_logo);
}
public void setTopbar(){
titleTextView.setText("hello!");
}
But i felt like custom views mostly is about drawing on a canvas, i am not doing that... so i dont know if using view is right either.
Either way, the titleTextView is null cause it cannot find the refrence to the xml file, and i have no idea how to reference to it hahah.
Does anyone have a smart solution to how i can do this the right way?
You need to inflate the layout for all the constructors of your custom view to be able to access them later.
public class ParcelTopBarView extends View {
public ParcelTopBarView(Context context) {
super(context);
init();
}
public ParcelTopBarView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ParcelTopBarView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public ParcelTopBarView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
View view = inflate(getContext(), R.layout.parcel_top_bar, this);
titleTextView = findViewById(R.id.title_textview);
subtitleTextView = findViewById(R.id.subtitle_textview);
deliveryInfoTextView = findViewById(R.id.delivery_info_textview);
thumbnailLogo = findViewById(R.id.thumbnail_logo);
}
Given a Button created at runtime:
Button button = Button(context)
The way to set a custom typeface is:
button.setTypeface(myTypeface)
However I find it only works before I add it to a ViewGroup and not after.
I've also tried:
button.setTypeface(myTypeface, myStyle)
but it didn't work either. I need to change my Button font dynamically. I've tried invalidate() and requestLayout() but the font never changes.
Solution:- you can subclass the Button class with your custom font and use it instead of button.
public class MyButton extends AppCompatButton {
public MyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyButton(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "font.ttf");
setTypeface(tf);
}
}
}
I have a custom RelativeLayout and I inflate an xml res file in it.
This works fine if I use the custom layout in an xml file and set it as contentview, but if I try to add it in the code with new LocationItem(this) and addChild() the findViewById method always returns null in the constructor of the custom RelativeLayout.
Here is the code:
public class LocationItem extends RelativeLayout {
private String parcelType;
private int countIntoBox, countFromBox;
private RelativeLayout deliveryContainer, pickupContainer;
private TextView countPickup, countDelivery;
public LocationItem(Context context) {
this(context, null);
}
public LocationItem(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
}
private OnClickListener getShowNumberPickerListener() {
return new OnClickListener() {
#Override
public void onClick(View view) {
showNumberPickerDialog(view);
}
};
} ...
}
Add custom view in activity
mRootLayoutLocations.addView(new LocationItem(this));
The view is inflated correctly, because I can see it, but when I try to access a view inside the custom view the app crashes with a NullPointerException.
Ok i inflated the view into a View(holder)
View v = inflate(getContext(), R.layout.list_item_location, this);
and then access the views via v.findViewById. Now it's working.
Code:
View v = inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) v.findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) v.findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) v.findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) v.findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
You need to be using appropriate constructors, not overloading them.
public class LocationItem extends RelativeLayout {
private String parcelType;
private int countIntoBox, countFromBox;
private RelativeLayout deliveryContainer, pickupContainer;
private TextView countPickup, countDelivery;
public LocationItem(Context context) {
super(context);
init(context, null, 0);
}
public LocationItem(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
}
private OnClickListener getShowNumberPickerListener() {
return new OnClickListener() {
#Override
public void onClick(View view) {
showNumberPickerDialog(view);
}
};
}
...
}
I fear you must inflate the view instead of finding it from nowhere. The method
findindViewById(int Id)
must be called within the Actvity's onCreate or with a view within which the child view/widget you are trying to find is resides in.
If all of the child views resides in a single xml file(within single parent root)
View rootView=(View) LayoutInflater.from(context).inflate(R.layout.list_item_location);
pickupContainer = (RelativeLayout) rootview.findViewById(R.id.rl_location_pickup_container);
you can try this. init views in the method onFinishInflate().This method will be called called as the last phase of inflation, after all child views have been added.So you can avoid NPE.
this should work
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this = inflate(getContext(), R.layout.list_item_location,null);
...
I created a custom Button, TextView, and ImageView. None of these appear properly in the Graphical Layout of any XML. Instead of showing a button or text with a custom font, it instead shows a huge grey box with the name of the custom class I'm calling. How do I get these to show in the preview?
public class FontTextView extends TextView {
public static Typeface FONT_NAME;
public FontTextView(Context context) {
super(context);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "font.ttf");
this.setTypeface(FONT_NAME);
}
public FontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "font.ttf");
this.setTypeface(FONT_NAME);
}
public FontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "font.ttf");
this.setTypeface(FONT_NAME);
}
and
<com.example.gesturetest.FontTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text placeholder" />
You can do this in your Custom View:
if(!isInEditMode()){
// Your custom code that is not letting the Visual Editor draw properly
// i.e. thread spawning or other things in the constructor
}
Reference
do this in the constructor of your customView
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
createTypeface(context, attrs); //whatever added functionality you are trying to add to Widget, call that inside this condition.
}
}
I am creating my own layout based on RelativeLayout as a class in code
I have basics of the layout defined in XML R.layout.menu_layout (style, drawable for background, margin, height)
If I would not need a class then I would call inflater to do this:
RelativeLayout menuLayout = (RelativeLayout)inflater.inflate(R.layout.menu_layout, root);
But I would like to be calling my own class instead
MenuLayout menuLayout = new MenuLayout(myparams);
Since I need to create a class I need to somehow inherit the R.layout.menu_layout in constructor, how can I do that? I guess there is no this.setLayout(res); or this.setResource(res); in View. Maybe I can use the other two parameters in View constructor but I did not find any tutorial how to do that either.
public class MenuLayout extends RelativeLayout {
public MenuLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
public MenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public MenuLayout(Context context) {
super(context);
initView(context);
}
private void initView(Context context) {
View view = LayoutInflater.from(context).inflate(R.layout.menu_layout, null);
addView(view);
}
}
now you can use
MenuLayout menuLayout = new MenuLayout(myparams);
you can change constructors for params i think