效果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdzFWRoRXdvN1LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9sGVPJTQU9keFpXTmZEWjZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO0IDOwMTN0EzNyITM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
由一個橫向ScrollView動态布置的一個可滑seekbar效果。
等級的Model
package com.leveldemo;
/**
* Created by KID on 2017/12/27.
*/
public class SimpleLevelModel {
private int levelId;
private int minExp;
public int getLevelId() {
return levelId;
}
public void setLevelId(int levelId) {
this.levelId = levelId;
}
public int getMinExp() {
return minExp;
}
public void setMinExp(int minExp) {
this.minExp = minExp;
}
}
一個px和dp的轉換工具
import android.content.Context;
import android.util.TypedValue;
/**
* Created by Administrator on 2017/5/9 0009.
*/
public class DensityUtils {
private DensityUtils(){
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* dp 轉 px
*
* @param context
* @param
* @return
*/
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp轉px
* @param context
* @param spVal
* @return
*/
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px轉dp
* @param context
* @param pxVal
* @return
*/
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px轉sp
* @param context
* @param pxVal
* @return
*/
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
布局檔案xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
android:gravity="center_vertical"
android:background="#356485">
<!-- 橫向seekbar布局-->
<HorizontalScrollView
android:id="@+id/scrollview_level"
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="80dp"
android:scrollbars="none"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<View
android:layout_centerVertical="true"
android:id="@+id/white_line"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="5dp"/>
<View
android:layout_centerVertical="true"
android:id="@+id/red_line"
android:background="@color/red"
android:layout_width="match_parent"
android:layout_height="5dp"/>
<TextView
android:textStyle="bold"
android:gravity="center"
android:id="@+id/tv_exp"
android:text="125"
android:textSize="9sp"
android:background="@drawable/exp_perent_bg"
android:textColor="@color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/red_line"
android:visibility="visible"/>
<LinearLayout
android:id="@+id/ll_content_img"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
</HorizontalScrollView>
</LinearLayout>
看到布局,可能你已經大概猜測到實作原理了。嗯哼~其實這個功能本身就應該由一些線條,動态添加布局實作。或者你想過做成自定義View,去draw線和圓。道理我們都懂……怎麼簡單怎麼實作呗
業務代碼
package com.leveldemo;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
//橫向seekbar的容器
private HorizontalScrollView horizontalScrollView;
private LinearLayout contentLl;
//經驗值懸浮窗
private TextView expTv;
//目前等級到下一等級的百分比
private double percent;
//橫向seekbar的寬度
private int width;
//底色白線
private View whiteLine;
//經驗紅線
private View redLine;
private SparseArray<ImageView> imageViews;
private SparseArray<TextView> textviews;
private List<SimpleLevelModel> simpleLevelModelList;
private int myLevel=;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView() {
horizontalScrollView= (HorizontalScrollView) findViewById(R.id.scrollview_level);
contentLl= (LinearLayout) findViewById(R.id.ll_content_img);
expTv = (TextView) findViewById(R.id.tv_exp);
redLine=findViewById(R.id.red_line);
whiteLine=findViewById(R.id.white_line);
expTv.setText("10234");
simpleLevelModelList=new ArrayList<>();
for (int i = ; i < 50; i++) {
SimpleLevelModel moel=new SimpleLevelModel();
moel.setLevelId(i+);
simpleLevelModelList.add(moel);
}
}
private void initData() {
if (imageViews == null){
imageViews = new SparseArray<>();
}
if(textviews==null){
textviews=new SparseArray<>();
}
for (int i = ; i <simpleLevelModelList.size(); i++) {
if(i!=simpleLevelModelList.size()-){
contentLl.addView(getRadioView(i,false),i);
}else {
contentLl.addView(getRadioView(i,true),i);
}
}
contentLl.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onGlobalLayout() {
width=contentLl.getWidth();
contentLl.getViewTreeObserver().removeOnGlobalLayoutListener(this);
setDefault(myLevel);
}
});
}
private View getRadioView(final int i,boolean isLast){
View view = null;
if(!isLast){
view = LayoutInflater.from(this).inflate(R.layout.item_lv_tagpoint,contentLl,false);
ImageView imageview = (ImageView) view.findViewById(R.id.image);
TextView textview = (TextView) view.findViewById(R.id.tv_level_seekbar);
textview.setText("LV"+simpleLevelModelList.get(i).getLevelId());
imageViews.put(i,imageview);
textviews.put(i,textview);
}else {
view = LayoutInflater.from(this).inflate(R.layout.item_lv_lastpoint,contentLl,false);
ImageView imageview = (ImageView) view.findViewById(R.id.image);
TextView textview = (TextView) view.findViewById(R.id.tv_level_seekbar);
textview.setText("LV"+simpleLevelModelList.get(i).getLevelId());
imageViews.put(i,imageview);
textviews.put(i,textview);
}
return view;
}
private void setDefault(int level) {
percent= ;
for (int i = ; i <imageViews.size() ; i++) {
if(i<level){
imageViews.get(i).setImageResource(R.drawable.level_red_point);
}else {
imageViews.get(i).setImageResource(R.drawable.level_white_point);
}
}
// textviews.get(level).setText("LV"+simpleLevelModelList.get(level).getLevelId());
// backLine.getLayoutParams().width= width-((int)DensityUtils.dp2px(getApplicationContext(),itemwidth));
//進度底色
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) whiteLine.getLayoutParams();
lp.width= (simpleLevelModelList.size()-)* DensityUtils.dp2px(getApplicationContext(),F);
lp.setMargins(DensityUtils.dp2px(getApplicationContext(),F),,,);
// backLine.getLayoutParams().width= (titles.size()-)*DensityUtils.dp2px(getApplicationContext(),F);
whiteLine.setLayoutParams(lp);
RelativeLayout.LayoutParams lp1 = (RelativeLayout.LayoutParams) redLine.getLayoutParams();
lp1.width= (myLevel-)*DensityUtils.dp2px(getApplicationContext(),F)+(int)(percent*DensityUtils.dp2px(getApplicationContext(),F));
lp1.setMargins(DensityUtils.dp2px(getApplicationContext(),F),,,);
redLine.setLayoutParams(lp1);
horizontalScrollView.scrollTo(lp1.width,);
RelativeLayout.LayoutParams lp2 = (RelativeLayout.LayoutParams) expTv.getLayoutParams();
//偏移時需要加懸浮窗寬度+point的寬度
lp2.setMargins(lp1.width+DensityUtils.dp2px(getApplicationContext(),F)-expTv.getWidth()/,,,DensityUtils.dp2px(getApplicationContext(),F));
expTv.setLayoutParams(lp2);
}
}
其中setDefault(int level)是根據背景傳回的資料設定預設的等級和經驗值。
item_lv_tagpoint.xml和item_lv_lastpoint.xml是小圓點的布局,一個是normal态,一個是最後一個小球。 是以别問我為什麼兩個布局一樣- -!,按照産品的尿性,達到最終等級總是要有一張不一樣的圖檔的(¯﹃¯),隻是我找不到我要的滑闆鞋~~~
代碼連結http://download.csdn.net/download/qq_31390699/10176050