How do I get height in self-defined layout when i set layout_weight="1" in vertical LinearLayout?
Here is my code:
<LinearLayout
android:id="#+id/timer_layout1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.zzb.resume.views.DotView
android:id="#+id/timer_line1"
android:layout_width="2dp"
android:layout_height="30dp" />
<ImageView
android:id="#+id/timer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/timer_line1"
android:src="#mipmap/time2"/>
<com.zzb.resume.views.DotView
android:id="#+id/timer_line2"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
In DotView I get height=0. How can I get height when layout_weight="1"?
DotView.java:
public class DotView extends View {
private Paint p;
private int height;
private int dash;
public DotView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DotView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStyle(Style.FILL);
p.setColor(context.getResources().getColor(R.color.color_divide));
Log.d("TAG", "--getMeasuredHeight>>" + height);
Log.d("TAG", "--getHeight>>" + getHeight());
final float scale = context.getResources().getDisplayMetrics().density;
dash = (int) (6 * scale + 0.5f);
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
height = getMeasuredHeight();
Log.d("TAG", "--onGlobalLayout>>" + height);
}
});
}
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
height = getMeasuredHeight();
Log.d("TAG", "--onPreDraw>>" + height);
return true;
}
});
}
#Override
protected void onDraw(Canvas canvas) {
if(height>10){
for(int i=0;i<height;i+=dash){
canvas.drawLine(0, i, 0, i+=dash, p);
}
}
super.onDraw(canvas);
}
#Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
height=h;
p.setStrokeWidth(height);
this.postInvalidate();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
height = MeasureSpec.getSize(heightMeasureSpec);
Log.d("TAG", "--onMeasure>>" + height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Logcat is shown: all result is 0.
You should not get the height in onCreate() , you can set a listener after the view initiates . Here is the code you can see also:
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
vto.removeOnPreDrawListener(this);
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
return true;
}
});
I hope this may help you.
to achieve this you need to give weightsum in linear layout
<LinearLayout
android:id="#+id/timer_layout1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:weightSum="2"
android:orientation="vertical">
<com.zzb.resume.views.DotView
android:id="#+id/timer_line1"
android:layout_width="2dp"
android:layout_height="30dp" />
<ImageView
android:id="#+id/timer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/timer_line1"
android:src="#mipmap/time2"/>
<com.zzb.resume.views.DotView
android:id="#+id/timer_line2"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Related
I have a textView which I want to remove every padding and extra space at the top and bottom of the text. This is my XML:
<TextView
android:id="#+id/stid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/quicksand"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:maxLines="1"
android:text="#string/st"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I am wrapping content and removing font padding but there is still a large padding at the top and at the bottom of the text which I want to remove. (on the sides it is fine just top and bottom)
this is a screenshot as requested
Did you try?
android:includeFontPadding="false"
android:lineSpacingExtra="-5dp"
Use this class and compile your project.
public class NoPaddingTextView extends TextView {
private int mAdditionalPadding;
public NoPaddingTextView(Context context) {
super(context);
init();
}
public NoPaddingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setIncludeFontPadding(false);
}
#Override
protected void onDraw(Canvas canvas) {
int yOff = -mAdditionalPadding / 6;
canvas.translate(0, yOff);
super.onDraw(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
getAdditionalPadding();
int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode != MeasureSpec.EXACTLY) {
int measureHeight = measureHeight(getText().toString(), widthMeasureSpec);
int height = measureHeight - mAdditionalPadding;
height += getPaddingTop() + getPaddingBottom();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int measureHeight(String text, int widthMeasureSpec) {
float textSize = getTextSize();
TextView textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
textView.setText(text);
textView.measure(widthMeasureSpec, 0);
return textView.getMeasuredHeight();
}
private int getAdditionalPadding() {
float textSize = getTextSize();
TextView textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
textView.setLines(1);
textView.measure(0, 0);
int measuredHeight = textView.getMeasuredHeight();
if (measuredHeight - textSize > 0) {
mAdditionalPadding = (int) (measuredHeight - textSize);
Log.v("NoPaddingTextView", "onMeasure: height=" + measuredHeight + " textSize=" + textSize + " mAdditionalPadding=" + mAdditionalPadding);
}
return mAdditionalPadding;
}
}
Replace TextView with NoPaddingTextView Class Name in your XML file
<YourPackage.NoPaddingTextView
android:id="#+id/stid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/quicksand"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:maxLines="1"
android:text="#string/st"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Source : Github
StackOverFlow
For some reason my custom viewgroup is not showing all children when i add weight to my Horizontalscrollview but it works perfect when i removed the weight here is my xml. Does anyone have any idea what is going on?
XML
<?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="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
android:orientation="vertical">
</LinearLayout>
<HorizontalScrollView
android:id="#+id/handScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_weight="2"
android:background="#color/colorAccent">
<com.example.example.cardgame.bin.template.HandViewLayout
android:id="#+id/handView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/black_grey">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/cardview_light_background"
android:text="View1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/cardview_dark_background"
android:text="View2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/face_down"
android:text="View3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorAccent"
android:text="View4" />
</com.example.example.cardgame.bin.template.HandViewLayout>
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>
However when i set my Horizontal scrollview to wrap_content or match_parent, it works as desired, why is it not working when i set weight attribute?
Here is my Class HandViewLayout
public class HandViewLayout extends ViewGroup {
private int mLeftWidth;
public float coverCard = 0;
private int mRightWidth;
private final Rect mTmpContainerRect = new Rect();
private final Rect mTmpChildRect = new Rect();
public OnClickListenerViewGroup onClickListenerViewGroup;
public HandViewLayout(Context context) {
super(context);
setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);
}
public void setCoverCard(float coverCard) {
this.coverCard = -Math.abs(coverCard);
}
public float getCoverCard() {
return this.coverCard;
}
public HandViewLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HandViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnClickListenerViewGroup(OnClickListenerViewGroup onClickListenerViewGroup) {
this.onClickListenerViewGroup = onClickListenerViewGroup;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
// These are the far left and right edges in which we are performing layout.
int leftPos = getPaddingLeft();
int rightPos = r - l - getPaddingRight();
// This is the middle region inside of the gutter.
final int middleLeft = leftPos + mLeftWidth;
final int middleRight = rightPos - mRightWidth;
// These are the top and bottom edges in which we are performing layout.
final int parentTop = getPaddingTop();
final int parentBottom = b - t - getPaddingBottom();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();
final int index = i;
child.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onClickListenerViewGroup.onClickListenerViewGroup(index);
}
});
if (i > 0) {
final View previousChild = getChildAt(i - 1);
mTmpContainerRect.left = middleLeft + lp.leftMargin + previousChild.getLeft() + previousChild.getWidth() + (int) coverCard;
mTmpContainerRect.right = middleRight - lp.rightMargin;
mTmpContainerRect.top = parentTop + lp.topMargin;
mTmpContainerRect.bottom = parentBottom - lp.bottomMargin;
} else {
mTmpContainerRect.left = middleLeft + lp.leftMargin;
mTmpContainerRect.right = middleRight - lp.rightMargin;
mTmpContainerRect.top = parentTop + lp.topMargin;
mTmpContainerRect.bottom = parentBottom - lp.bottomMargin;
}
// Use the child's gravity and size to determine its final
// frame within its container.
Gravity.apply(lp.gravity, width, height, mTmpContainerRect, mTmpChildRect);
// Place the child.
child.layout(mTmpChildRect.left, mTmpChildRect.top,
mTmpChildRect.right, mTmpChildRect.bottom);
}
}
#Override
protected boolean awakenScrollBars() {
return true;
}
#Override
protected int computeVerticalScrollExtent() {
return super.computeVerticalScrollExtent();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
mLeftWidth = 0;
mRightWidth = 0;
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
// Log.e("child Text", i + ": " + ((TextView) child).getText().toString());
if (child.getVisibility() != GONE) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
// last one show all
if (i == getChildCount() - 1) {
maxWidth += child.getMeasuredWidth();
} else {
maxWidth += child.getMeasuredWidth() + coverCard;
}
Log.d("Spacer", "spacer, " + i + "," + maxWidth);
maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
}
}
setMeasuredDimension(resolveSizeAndState(maxWidth, heightMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState));
}
#Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new HandViewLayout.LayoutParams(getContext(), attrs);
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
#Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
#Override
public boolean shouldDelayChildPressedState() {
return false;
}
public static class LayoutParams extends MarginLayoutParams {
public int gravity = Gravity.TOP | Gravity.START;
public static int POSITION_MIDDLE = 0;
public static int POSITION_LEFT = 1;
public static int POSITION_RIGHT = 2;
public int position = POSITION_MIDDLE;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray atts = c.obtainStyledAttributes(attrs, R.styleable.HandViewLayout);
gravity = atts.getInt(R.styleable.HandViewLayout_android_layout_gravity, gravity);
position = atts.getInt(R.styleable.HandViewLayout_layout_position, position);
atts.recycle();
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
}
}
Attributes xml
<declare-styleable name="HandViewLayout">
<attr name="layoutColor" format="color" />
<attr name="android:layout_gravity" />
<attr name="layout_position">
<enum name="middle" value="0" />
<enum name="left" value="1" />
<enum name="right" value="2" />
</attr>
</declare-styleable>
PIC
I didn't describe the question in a good way, so I edit the question to be clear.
I am so confused about this: I wrote a RelativeLayout with a DragViewGroup and a gridview, and I noticed that every time when I used notifyDatasetChanged() method would cause the DragViewGroup do the redrawing thing.And the DragViewGroup extends from LinearLayout which uses ViewDragHelper, so I could not maintain the position already scrolled to.
Here is my xml file:
<?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">
<com.xxxx.DragViewGroup
android:id="#+id/dragview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#3f83f7"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="665dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="310dp"
android:id="#+id/mainview"
>
...
</RelativeLayout>
<include
android:layout_width="match_parent"
android:layout_height="355dp"
android:layout_marginBottom="62dp"
layout="#layout/fake_panel" />
</LinearLayout>
</com.xxxx.DragViewGroup>
<RelativeLayout
android:layout_width="match_parent"
android:id="#+id/layout"
android:layout_alignParentBottom="true"
android:layout_height="210dp"
android:background="#ffffff"
android:clickable="true"
>
<HorizontalScrollView
android:id="#+id/btn_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
android:layout_alignParentBottom="true"
android:layout_marginBottom="26dp"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:listSelector="#color/transparent"
android:horizontalSpacing="6dp"
android:scrollbars="none" />
</LinearLayout>
</HorizontalScrollView>
<com.xxxx.UniversalSeekBar
....
android:layout_marginTop="18dp"/>
</RelativeLayout>
</RelativeLayout>
DragViewGroup code:
public class DragViewGroup extends LinearLayout {
private ViewDragHelper viewDragHelper;
private View mainView;
private int mainHeight;
public DragViewGroup(Context context) {
super(context);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mainView = getChildAt(0);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mainHeight = mainView.findViewById(R.id.mainview).getMeasuredHeight();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return viewDragHelper.shouldInterceptTouchEvent(ev);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);
return true;
}
#Override
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
private void initView() {
viewDragHelper = ViewDragHelper.create(this, callback);
}
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
#Override
public boolean tryCaptureView(View child, int pointerId) {
return mainView == child;
}
#Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return 0;
}
#Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
#Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (mainView.getTop() > -500) {
viewDragHelper.smoothSlideViewTo(mainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
} else {
viewDragHelper.smoothSlideViewTo(mainView, 0, -mainHeight);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
}
Once I use the notifyDatasetChanged() method to update the gridview, my DragViewGroup will slide to the original position itself although it has been dragged before. Apparently the method draw the whole layout instead of only drawing gridview itself.
I need to maintain the dragged position of DragViewGroup, I have tried that override onDraw method in DragViewGroup like this:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// set isDragged label in onViewReleased()
if (isDragged) {
viewDragHelper.smoothSlideViewTo(main, 0, -mainHeight);
}
}
It works, but there is a visible sliding process which I don't want.
Hope someone could help me.Thanks very much.
Store ScrollValue at the time of the scrolling the view, and just use setSelectionMethod on your gridview
gridview.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
int count = gridview.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (gridview.getLastVisiblePosition() >= count
- 1) {
scrollPos = <positionOfList>;
}
}
}
});
Here enter your last position insted of "positionOfList"
And just after calling notifydatasetChanged() call gridview.setSelection(scrollPos)
Hope this will help you!
Just use bellow code in class that you update display:
int index = myList.getFirstVisiblePosition();
View v = myList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
myList.setAdapter(adapter);
adapter.notifyDataSetChanged();
myList.setSelectionFromTop(index, top);
I am making an application in Android and I am currently trying to make a vertical TextView. I want it to look similar to this.
Does anyone know how to achieve this, or at least an existing library which I can use to get this effect.
Thanks
If you want vertical Text View like this then you need to pass \n to Text View text property.
Refer 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/description"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:background="#000"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="5dp"
android:text="A\nB\nC\nD\n"
android:textColor="#FFF"
android:textSize="18dp" />
</RelativeLayout>
You must create custom view
For example:
public class VerticalTextView extends AppCompatTextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
} else
topDown = true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected boolean setFrame(int l, int t, int r, int b) {
return super.setFrame(l, t, l + (b - t), t + (r - l));
}
#Override
public void draw(Canvas canvas) {
if (topDown) {
canvas.translate(getHeight(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getWidth());
canvas.rotate(-90);
}
canvas.clipRect(0, 0, getWidth(), getHeight(), Region.Op.REPLACE);
super.draw(canvas);
}
}
I have a fullscreen activity that should look like this:
where the big white circle would have some text, I've already done it, but the problem is that I don't know how to do that dashed lines between the icons, also they want a little animation in the icons, so I assumed that each one should be a separate view, so far I've done this (it doesn't need to look exactly the same):
So, how could I draw that lines? Also if I could make that dashes to "run" acrross the lines would be awesome.
this is my xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rlt_welcome"
android:layout_weight="9"
android:background="#drawable/bg"
>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="2"
android:orientation="vertical"
android:padding="10dp"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:id="#+id/img_youtube"
android:src="#drawable/youtube_circle"
android:layout_marginTop="60dp"
android:layout_marginRight="60dp"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/tablet_circle"
android:layout_height="wrap_content"
android:layout_above="#+id/img_stats"
android:layout_marginRight="30dp"
android:layout_below="#+id/img_youtube"
/>
<ImageView
android:layout_width="wrap_content"
android:id="#+id/img_stats"
android:src="#drawable/stats_circle"
android:layout_height="wrap_content"
android:layout_marginRight="70dp"
android:layout_marginBottom="20dp"
android:layout_alignParentBottom="true"/>
<ImageView
android:id="#+id/img_iphone"
android:layout_width="wrap_content"
android:src="#drawable/iphone_circle"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/imac_circle"
android:layout_height="wrap_content"
android:layout_below="#+id/img_iphone"
android:layout_marginLeft="70dp"
android:layout_marginTop="-30dp"
/>
<ImageView
android:layout_width="wrap_content"
android:src="#drawable/webcam_circle"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="5"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical"
android:padding="40dp"
android:textSize="25sp"
android:textColor="#color/text1"
android:layout_margin="20dp"
android:text="Bienvenido"
android:background="#drawable/flat_circle"
android:id="#+id/txt_welcome"
android:layout_centerInParent="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/arrow_circle"
android:id="#+id/img_arrow"
android:layout_alignParentTop="true"
android:layout_marginRight="60dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/news_circle"
android:layout_below="#+id/img_arrow"
android:layout_marginTop="-90dp"
android:layout_marginRight="2dp"
android:layout_marginLeft="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/line_circle"
android:id="#+id/img_line"
android:layout_below="#+id/img_arrow"
android:layout_marginTop="-10dp"
android:layout_marginRight="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/money_circle"
android:layout_below="#+id/img_line"
android:layout_marginRight="6dp"
android:layout_marginTop="-70dp"
android:layout_marginLeft="70dp"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/mouse_circle"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginRight="80dp"
/>
</RelativeLayout>
</LinearLayout>
Please check this, may be this will help you
http://www.rengelbert.com/tutorial.php?id=182
How do I get this work, I made a new activity that holds a Canvas controller, and place the bitmaps on the canvas and draw the lines between them with this, I didn't use any external library:
Hope someone could reuse some code and not only been told to google it.
MainActivty.java
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
relativeMainActivity = (RelativeLayout) findViewById(R.id.rlt_main);
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
final int heightS = dm.heightPixels;
final int widthS = dm.widthPixels;
Log.d("MainActvitiy", "widht:" + widthS);
myPanel = new Panel(getApplicationContext(),this,widthS, heightS);
relativeMainActivity.addView(myPanel);
RelativeLayout RR = new RelativeLayout(this);
RR.setGravity(Gravity.CENTER);
relativeMainActivity.addView(RR,400,150);
RR.setX(0);
LayoutInflater myInflater = (LayoutInflater) getApplicationContext().getSystemService(getApplicationContext().LAYOUT_INFLATER_SERVICE);
}
Panel.java
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
public MainThread thread;
private Background background;
private CircleManager CM;
public int ScreenWidth;
public int Screenheigt;
private CircleIcon icon1;
private CircleIcon icon2;
private CircleIcon icon3;
//and so on
public MainActivity myMain;
public Panel(Context context, MainActivity _main, int width , int height) {
super(context);
getHolder().addCallback(this);
this.myMain = _main;
this.ScreenWidth=width;
this.Screenheigt=height;
thread = new MainThread(getHolder(),this);
background = new Background(BitmapFactory.decodeResource(getResources(), R.drawable.bg), Screenheigt, this);
CM = new CircleManager( this,context,ScreenWidth);
CM.setScreen(ScreenWidth, Screenheigt);
SetIcons();
CM.setManager();
setFocusable(true);
}
void SetIcons()
{
icon1 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_iphone),39,40);
icon2 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_chat),280,40);
icon3 = new CircleIcon(BitmapFactory.decodeResource(getResources(),R.drawable.circle_youtube),60,200);
//and so on
icon1.myConnections.add(2);
icon1.myConnections.add(3);
icon2.myConnections.add(15);
icon3.myConnections.add(4);
icon3.myConnections.add(5);
//and so on
CM.iconsList.add(icon1);
CM.iconsList.add(icon2);
CM.iconsList.add(icon3);
//and so on
}
void Draw(Canvas canvas){
if (canvas!=null)
{
background.draw(canvas);
CM.draw(canvas);
iconEvent.draw(canvas);
}
}
void Update(float dt)
{
CM.Update(dt);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
while (retry)
{
try
{
thread.join();
retry=false;
}
catch (InterruptedException e)
{
}
}
}
}
Background.java
public class Background {
Bitmap BackBitmap;
int x,y;
int ScreenHeight;
Panel root_panel;
public Background(Bitmap bitmap , int Screen_h, Panel _panel) {
this.BackBitmap = bitmap;
this.x=0;
this.y=0;
this.ScreenHeight=Screen_h;
root_panel =_panel;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(BackBitmap,x,y, null);
}
}
CircleIcon.java
public class CircleIcon {
private Bitmap bitmap;
private int x;
private int y;
CircleManager circManager;
ArrayList<Integer> myConnections;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y=y;
}
public CircleIcon(Bitmap icon, int x, int y) {
bitmap=icon;
this.x=x;
this.y=y;
myConnections = new ArrayList<>();
}
public ArrayList<Integer> getMyConnections() {
return myConnections;
}
public void setMyConnections(ArrayList<Integer> myConnections) {
this.myConnections = myConnections;
}
public void setManager(CircleManager icManager) {
circManager = icManager;
}
public Bitmap getBitmap()
{
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
}
public void update()
{
// x=+1; example
}
}
CircleManager.java
public class CircleManager {
Bitmap icons;
int screenWidth;
int hour;
int min;
Context myContext;
int ScreenWidht;
public Panel myPanel;
public ArrayList<CircleIcon> iconsList;
public CircleManager(Panel _Panel, Context context,int screenW) {
this.myPanel = _Panel;
this.screenWidth = screenW;
this.myContext = context;
iconsList = new ArrayList<CircleIcon>();
}
public void setScreen(int screenWidth, int screenHeight)
{
this.ScreenWidht=screenWidth;
}
public void draw(Canvas canvas)
{
drawLines(canvas);
for(CircleIcon myIcon: iconsList)
{
myIcon.draw(canvas);
}
}
public void Update(float dt)
{
//some animation updates
}
public void drawLines(Canvas canvas)
{
Paint mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(2);
mPaint.setPathEffect(new DashPathEffect(new float[]{7, 5}, 0));
for (CircleIcon myIcon: iconsList)
{
for( int connectedIcon: myIcon.getMyConnections())
{
Path mPath;
mPath = new Path();
mPath.moveTo(myIcon.getX()+myIcon.getBitmap().getWidth()/2, myIcon.getY()+myIcon.getBitmap().getHeight()/2);
mPath.lineTo(iconsList.get(connectedIcon-1).getX()+myIcon.getBitmap().getWidth()/2, iconsList.get(connectedIcon-1).getY()+myIcon.getBitmap().getHeight()/2);
canvas.drawPath(mPath, mPaint);
}
}
}
public void setManager()
{
for(CircleIcon myIcon: iconsList)
{
myIcon.setManager(this);
}
}
}