When creating annotations their actual position is based on their index in the dataframe not on your variable xval.
import pandas as pd
from matplotlib import pyplot as plt
data = [
[0.0, 4.9, 19.9, 8.1, 0.0],
[0.12, 4.5, 27.0, 10.1, 0.0],
[0.24, 2.8, 9.3, 4.6, 0.0],
[0.36, 2.2, 9.1, 2.7, 0.0],
[0.48, 2.2, 7.3, 3.1, 0.0],
[1.0, 4.9, 26.4, 11.2, 0.0],
[1.12, 5.9, 25.3, 8.7, 0.0],
[1.24, 3.7, 13.3, 7.1, 0.0],
[1.36, 3.0, 9.5, 3.4, 0.0],
[1.48, 3.2, 8.9, 4.7, 0.0],
[2.0, 8.4, 24.8, 20.2, 0.0],
[2.12, 9.5, 19.3, 22.5, 0.0],
[2.24, 5.7, 11.8, 6.6, 0.0],
[2.36, 4.1, 11.1, 5.1, 0.0],
[2.48, 5.4, 8.0, 4.6, 0.0],
]
df = pd.DataFrame(columns=["xval", "y1", "y2", "y3", "y4"], data=data)
df1 = df.copy()
df1['total'] = df[['y1', 'y2', 'y3', 'y4']].sum(axis=1)
fig, ax = plt.subplots()
df.plot(x="xval", kind="bar", ax=ax, stacked=True, width=0.11)
padding = 0.03 #percentage, needed for putting some space between the annotations and bars
for i, x in enumerate(df1['xval']):
total = df1['total'][i]
ax.annotate(f'{x:.2f}-{df1["total"][i]:.2f}',
(i, total + padding * total), # Add padding to the y-coordinate
rotation='vertical',
fontsize=10,
ha='center',
va='bottom') #set position
#set xticks and labels
ax.set_xticks(range(len(df1['xval'])))
ax.set_xticklabels([f'{x:.2f}' for x in df1['xval']])
ax.set_ylim(0, 80) #makes space for the annotations
ax.grid(False) #looks better without grid in my opinion
plt.tight_layout()
plt.show()