I am trying to implement horizontal timeline. SO I have written the code to design the horizontal line but I am able to figure out how I will write text on the above and below of the line.
One more thing I don't want to use any other library.
I have try to solve it through Custom view as people here have been suggested but got struck.
timeline_segment.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:weightSum="1"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:padding="3dp"
android:textAlignment="textEnd"
android:text="Top"
android:id="#+id/top_data"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_gravity="center"
android:layout_weight="0.5"
android:background="#color/alphabet_a"
android:layout_width="wrap_content"
android:layout_height="2dp" />
<ImageView
android:background="#drawable/circle1"
android:layout_width="15dp"
android:layout_height="15dp" />
<TextView
android:layout_weight="0.5"
android:layout_gravity="center"
android:background="#color/alphabet_a"
android:layout_width="wrap_content"
android:layout_height="2dp" />
</LinearLayout>
<TextView
android:padding="3dp"
android:gravity="center"
android:text="bottom"
android:id="#+id/bottom_data"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</merge>
timeline_segment.java
public class timeline_segement extends LinearLayout {
View rootView;
TextView upperText;
TextView startLine;
TextView endLine;
ImageView circleView;
TextView bottomText;
public timeline_segement(Context context) {
super(context);
init(context);
}
public timeline_segement(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public timeline_segement(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
rootView=inflate(context, R.layout.timeline_segment, this );
upperText=(TextView) rootView.findViewById(R.id.top_data);
bottomText=(TextView) rootView.findViewById(R.id.bottom_data);
upperText.setText("Top");
bottomText.setText("Bottom");
}
public void setUpperText(String string)
{
upperText.setText(string);
}
public void setBottomText(String string)
{
bottomText.setText(string);
}
}
Decided to answer because the comment box is kinda limiting. This is my comment:
You'll need a custom view to achieve this. You can either composite ready-made views or go full custom
If you choose to composite views, then you start by breaking down that image level by level. At the highest level, its a horizontal layout with 'TimelineCell's (or whatever you choose to call it).
A TimelineCell will basically be a vertical LinearLayout with a right aligned TextView, a View that draws the line and another center aligned TextView.
You can then create these programmatically and add them to a parent horizontal LinearLayout.
If you however choose to go full custom, Youll have to handle measuring, layouting and drawing of all the components including the text above and below the line.
Take a look at this link for a good introduction to custom views on android
Related
I have a weird problem that I'm having problems even articulating.
My layout is a relative layout that contains a scrollview that contains chips and an edit text. Below the scroll view, is a listview for auto completion, below which is a linear layout that houses an edit text and a button. (Screen shots at the end of this post).
When the fragment loads and the user types into the edittext inside the scroll view, the listview with auto complete options pops up. When an auto complete option is selected that is added as a selected chip. The library that generates those chips does not clear focus of the edit text, but something is jogging the OS to move focus to the bottom edit text. This results in the weird state that BOTH edit texts are blinking as if they had focus. If the user starts typing on the keyboard again the focus is actually on the the lower edit text, and it's now impossible to focus on the first edit text again to type.
The code for the NonFocusingScrollView is as follows. This properly fixed my issue where the scroll view around the ChipsView was grabbing focus and preventing the edit text from working correctly at all. (The SevenChipsView in the layout is merely an extension of ChipsView).
I've tried, programatically, removing focus from the lower edit text, and explicitly putting it back into the edit text in the scroll view, but that doesn't do anything.
Is there a way that I can prevent the OS from shifting focus around, and stay in the top edit text until the user taps the bottom edit text?
public class NonFocusingScrollView extends ScrollView {
public NonFocusingScrollView(Context context) {
super(context);
}
public NonFocusingScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
#Override
public ArrayList getFocusables(int direction) {
return new ArrayList();
}
#Override
public void requestChildFocus(View child, View focused) {
// avoid scrolling to focused element all together
}
}
Layout XML
<?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"
android:orientation="vertical">
<LinearLayout
android:id="#+id/messaging_announcement_recipient_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#color/screen_background"
android:orientation="horizontal"
android:padding="8dip">
<TextView
style="#style/default_textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="8dip"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dip"
android:layout_marginStart="0dp"
android:gravity="center_vertical"
android:text="#string/recipient_to"
android:textColor="#android:color/white" />
<com.sevenshifts.android.views.NonFocusingScrollView
android:id="#+id/messaging_announcements_recipients_scroll_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:focusable="true"
android:focusableInTouchMode="true"
android:padding="0dp">
<com.sevenshifts.android.views.SevenChipsView
android:id="#+id/messaging_announcements_recipients"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:textColor="#android:color/white"
app:cv_bg_color_clicked="#color/primary"
app:cv_color_clicked="#color/primary"
app:cv_icon_placeholder="#drawable/ic_house" />
</com.sevenshifts.android.views.NonFocusingScrollView>
</LinearLayout>
<se.emilsjolander.stickylistheaders.StickyListHeadersListView
android:id="#+id/messaging_announcements_recipient_autocomplete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/messaging_announcement_recipient_container"
android:visibility="gone" />
<LinearLayout
android:id="#+id/messaging_announcements_compose_post_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip"
android:minHeight="44dip"
android:orientation="horizontal">
<EditText
android:id="#+id/messaging_announcement_post_text"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="#string/announcement_hint"
android:inputType="textMultiLine|textCapSentences|textAutoCorrect"
android:maxLines="5" />
<Button
android:id="#+id/messaging_announcement_post_button"
android:layout_width="80dp"
android:layout_height="44dip"
android:background="#null"
android:text="#string/send"
android:textColor="#color/primary" />
</LinearLayout>
<include layout="#layout/component_loading" />
</RelativeLayout>
Screen shot flow is in this imgur gallery - there's too many to not crowd this post: http://imgur.com/a/zWY0D
I am writing an app on Android Studio and I am trying to create a custom view with a specific form I need, something like:
Custom View Example
(I used different colors to show how the layout is supposed to go)
Here's the xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="150dp"
android:weightSum="2"
android:background="#android:color/holo_red_dark">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="1"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<TextView
android:layout_width="match_parent"
android:layout_height="75dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/hourLbl"
android:layout_gravity="center"
android:background="#android:color/holo_blue_bright"/>
<TextView
android:layout_width="match_parent"
android:layout_height="75dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/minuteLbl"
android:layout_gravity="center"
android:background="#android:color/holo_orange_dark"/>
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/actionName"
android:layout_weight="1"
android:gravity="center"
android:background="#android:color/darker_gray"/>
</LinearLayout>
The problem comes when I try to add this view to another layout in the app.. It comes as a blank square. I have been trying to look for an answer on how to properly do this, but nothing helps.
This is what I have in the xml of the activity where I want the view (ActionView):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".HomeActivity">
<...ActionView
android:layout_width="match_parent"
android:layout_height="150dp"
android:id="#+id/firstAction" />
</RelativeLayout>
Here's the ActionView's constructors I have (not sure what to do with them to be honest, just copied them from a tutorial):
public ActionView(Context context) {
super(context);
}
public ActionView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.ActionView,
0, 0);
try {
mHourLbl = a.getString(R.styleable.ActionView_hourLbl);
mMinuteLbl = a.getString(R.styleable.ActionView_minuteLbl);
mActionName = a.getString(R.styleable.ActionView_actionName);
} finally {
a.recycle();
}
}
public ActionView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
I think you're missing the most important part. You're not tying your layout to your ActionView object...
Add:
LayoutInflater.from(context).inflate(R.layout.<xml_of_action_view>, this, true);
inside your ActionView constructor.
I have a custom header bar (something like actionbar).
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#drawable/bg_header">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ibSlider"
android:src="#drawable/ic_drawer"
android:background="#color/transparent"
android:layout_marginLeft="#dimen/side_margin"
android:contentDescription="#string/general_content_description"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="#string/header_branding"
android:id="#+id/tvAppName"
android:layout_toRightOf="#+id/ibSlider"
android:gravity="center_vertical"
android:layout_marginLeft="#dimen/side_margin"
style="#style/branding_orange"/>
<ProgressBar
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/pbLoading"
android:layout_alignParentRight="true"
android:indeterminate="true"
android:layout_marginRight="#dimen/side_margin"
android:layout_centerVertical="true"/>
</RelativeLayout>
When I'm adding this custom view in my activity, there is padding right that I have no idea comes from where! I have added green background to the view in order to find I'm talking about where.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<view
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="#+id/headerBar"
android:background="#color/green"
class="com.kamalan.widget.HeaderBar"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/headerBar"/>
</RelativeLayout>
And this is the code of my HeaderBar.
public class HeaderBar extends RelativeLayout {
private static final String TAG = "HeaderBar";
private Context mContext;
private ProgressBar progressBar;
private ImageButton ibMenuSlider;
public HeaderBar(Context context) {
super(context);
this.mContext = context;
init();
}
public HeaderBar(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
init();
}
public HeaderBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
init();
}
private void init() {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout view = (RelativeLayout) mInflater.inflate(R.layout.widget_headerbar, null);
addView(view);
progressBar = (ProgressBar) view.findViewById(R.id.pbLoading);
ibMenuSlider = (ImageButton) view.findViewById(R.id.ibSlider);
}
...
}
Image 1 shows preview of class header (first xml code) and second image displays when it has been added to my activity. I have no idea that green padding comes from where! any idea would be appreciated. thanks.
Problem was the image that I was using as background of Header. Have no Idea why it works on first image but doesn't work on second one. Maybe activity is messing or Theme has bug, as Bob said in comment.
Anyways, I fixed the problem by not using image :)
For other's reference, I changed xml of header as below and I could fix the problem in this way.
<?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="#dimen/header_bar_height"
android:background="#color/gray">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ibSlider"
android:src="#drawable/ic_drawer"
android:background="#color/transparent"
android:layout_marginLeft="#dimen/side_margin"
android:contentDescription="#string/general_content_description"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="#string/header_branding"
android:id="#+id/tvAppName"
android:layout_toRightOf="#+id/ibSlider"
android:gravity="center_vertical"
android:layout_marginLeft="#dimen/side_margin"
style="#style/branding_orange"/>
<ProgressBar
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/pbLoading"
android:layout_alignParentRight="true"
android:indeterminate="true"
android:layout_marginRight="#dimen/side_margin"
android:layout_centerVertical="true"/>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#color/header_divider"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
I also face same problem but i get success when i try customize Actionbar.I am unable to resolve your problem due to absence of drawable and string resource so please provide zip of this one so that i can see directly .....
I'm getting a null pointer exception in my custom view (which is derived from a LinearLayout) because it can't find its child views. Here is the code:
public class MyView extends LinearLayout
{
public MyView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
private TextView mText;
#Override
protected void onFinishInflate()
{
super.onFinishInflate();
mText = (TextView) findViewById(R.id.text);
if (isInEditMode())
{
mText.setText("Some example text.");
}
}
}
Here is the layout (my_view.xml):
<?xml version="1.0" encoding="utf-8"?>
<com.example.views.MyView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</com.example.views.MyView>
And here is how I put it in the XML file:
<com.example.views.MyView
android:id="#+id/my_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
But when I try to preview it in the layout editor I get an NPE on mText.setText(...) because getViewById() returns null.
What's going on?
Clarification
The reason I expect this to work, is if I do
MyView v = (MyView)inflater.inflate(R.layout.my_view);
((TextView)v.findViewById(R.id.text)).setText("Foo");
everything works fine. Is that not what the layout inflater does when it goes through a layout file? In any case, how can I handle both situations correctly (without getting pointless nested views)?
In you XML file you are trying to use a custom view class (com.example.views.MyView) and in the same time trying to add a TextView inside. It's not possible.
Here is what you need to change:
You must inflate XML file in the code:
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
LayoutInflater.from(context).inflate(R.layout.<your_layout>.xml, this);
}
And modify the XML layout file like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</LinearLayout>
I am working on an android application that will get data from an xml file and insert it in a listview
but I want to change the UI and instead of displaying the data in a listview vertically, I want to display them horizontally in a scrollview
My question is if I have the following code
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="#+id/linearLayout1"
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:padding="2dp">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="wrap_content"
android:id="#+id/imageView11"
android:layout_height="wrap_content"
android:src="#drawable/i1"/>
<TextView
android:id="#+id/TextOnImage11"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Fantasia Reviews"
android:layout_alignParentBottom="true"
android:paddingLeft="2dp"
android:background="#drawable/txt_bg"
android:textSize="10dp"
android:paddingTop="2dp"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:width="0dp" />
</RelativeLayout>
</LinearLayout>
</HorizontalScrollView>
how can I add more images and text dynamically from the java code ??
Thank you
I presume that your intent would be to add another RelativeLayout with it's own image/text pair straight after the RelativeLayout that you have shown in your code sample?
In that case as it is not simply adding one more view, I would take the time to create a class that represents your "structure" that you want to insert.
e.g. A class called "TextImagePair" that extends "RelativeLayout"
public class TextImagePair extends RelativeLayout {
public ReportDetailRow(Context context){
super(context);
}
public TextImagePair(Context context,AttributeSet attributeSet){
super(context, attributeSet);
}
public TextImagePair(Context context,AttributeSet attributeSet, int i){
super(context, attributeSet,i);
}
public TextImagePair(Context context, AttributeSet attributeSet, String text, int drawableResource) {
super(context, attributeSet);
// Inflate the layout
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflator.inflate(R.layout.lay_textimagepair, this);
TextView tvText = (TextView)this.findViewById(R.id.layTextImagePair_textview);
tvText.setText(text);
ImageView imgView = (ImageView)this.findViewById(R.id.layTextImagePair_imageview);
imgView.setDrawable(getResources().getDrawable(drawableResource));
}
}
You would then have a seperate xml layout file (named lay_textimagepair in my code) that just contains the text and image views.
You would then add this to your view at run time with:
LinearLayout parent = (LinearLayout)findViewById(R.id.layParentView_liniearlayout);
TextImagePair tip = new TextImagePair(null,null,"Blah Blah Blah",R.drawable.something);
parent.addView(tip);
Sorry if there are any bugs in the above code but I am writing it without access to Eclipse!